Skip to content
Security
Skill

/pe-analysis

Activate this skill whenever the user mentions PE analysis, PE file, PE header, portable executable, Windows executable analysis, EXE analysis, DLL analysis, SYS driver analysis, OCX analysis, PE structure, PE format, PE parsing, PE triage, PE inspection, binary headers, file

From plugin
fsociety
2025 skills7 agents63 commands
Install
$ npx -y skills add ogrodev/fsociety --skill pe-analysis --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/pe-analysis

Context preview

The summary Claude sees to decide when to auto-load this skill.

Activate this skill whenever the user mentions PE analysis, PE file, PE header, portable executable, Windows executable analysis, EXE analysis, DLL analysis, SYS driver analysis, OCX analysis, PE structure, PE format, PE parsing, PE triage, PE inspection, binary headers, file

SKILL.md

pe-analysis.SKILL.md
name: pe-analysis
description: |
  Activate this skill whenever the user mentions PE analysis, PE file, PE header, portable executable,
  Windows executable analysis, EXE analysis, DLL analysis, SYS driver analysis, OCX analysis,
  PE structure, PE format, PE parsing, PE triage, PE inspection, binary headers, file headers,
  DOS header, MZ header, COFF header, optional header, PE signature, image base, entry point,
  AddressOfEntryPoint, section table, section headers, section entropy, section permissions,
  .text section, .rdata section, .rsrc section, .reloc section, .data section, UPX section,
  import table, IAT, import address table, import directory, DLL imports, suspicious imports,
  API hashing, GetProcAddress hashing, delayed imports, bound imports,
  export table, EAT, export address table, DLL exports, forwarded exports, ordinal exports,
  resource table, resource directory, embedded resources, PE resources, resource extraction,
  version info, file version, manifest, embedded manifest, icon extraction,
  overlay data, appended data, PE overlay, data after last section,
  PE anomalies, header anomalies, suspicious PE, malformed PE, corrupted PE,
  timestamp analysis, compile time, TimeDateStamp, checksum validation, PE checksum,
  rich header, Rich signature, linker info, compiler detection,
  debug directory, PDB path, debug info, CodeView,
  authenticode, digital signature, signed binary, certificate validation,
  TLS callbacks, TLS directory, thread local storage,
  data directories, CLR header, .NET PE, COM descriptor,
  pefile, pestudio, PE-bear, CFF Explorer, dumpbin, objdump, readpe,
  packed binary detection, packer identification, UPX detection, section padding,
  security features check, ASLR, DEP, NX, CFG, SafeSEH, guard flags,
  PE file triage, unknown binary triage, suspicious binary, malware triage,
  binary classification, executable classification, initial binary assessment.
version: 2.0.0

PE File Analysis

Portable Executable analysis is the foundation of Windows binary reverse engineering. Every .exe, .dll, .sys, .ocx, and .scr on Windows follows the PE format. Master PE structure and you can triage unknown binaries in minutes -- determine if they are packed, what they do, what anomalies they exhibit, and whether they warrant deeper analysis.

Triage Workflow

Follow this sequence when analyzing an unknown PE file. Each step builds on the previous one.

Step 1 — Compute Hashes and Basic Identification

Hash the binary first. Check hashes against known databases before spending time on manual analysis.

# SHA256 + MD5 + file type
node ${CLAUDE_PLUGIN_ROOT}/scripts/binary-hasher.js hash <binary>
file <binary>

# Check analysis database for prior work
node ${CLAUDE_PLUGIN_ROOT}/scripts/analysis-tracker.js check <sha256> pe-analysis

Record the hash immediately. Every subsequent finding references this hash.

Step 2 — Header Analysis

Extract PE headers to determine architecture, compile time, entry point, and security features.

# Full header dump with radare2
r2 -qc 'iH' <binary>
r2 -qc 'iI' <binary>
import pefile, time
pe = pefile.PE('<binary>')

# Compile timestamp
ts = pe.FILE_HEADER.TimeDateStamp
print(f"Compile time: {time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(ts))} UTC")
print(f"Machine: {hex(pe.FILE_HEADER.Machine)}")
print(f"Entry point: {hex(pe.OPTIONAL_HEADER.AddressOfEntryPoint)}")
print(f"Image base: {hex(pe.OPTIONAL_HEADER.ImageBase)}")
print(f"Subsystem: {pe.OPTIONAL_HEADER.Subsystem}")

# Security features
flags = pe.OPTIONAL_HEADER.DllCharacteristics
print(f"ASLR: {bool(flags & 0x40)}, DEP: {bool(flags & 0x100)}, CFG: {bool(flags & 0x4000)}")
print(f"No SEH: {bool(flags & 0x400)}, Force integrity: {bool(flags & 0x80)}")

Check for anomalies: future timestamps, epoch zero, entry point outside `.text`, missing ASLR/DEP.

See `references/pe-headers.md` for complete field reference.

Step 3 — Section Analysis

Sections reveal packing, encryption, and structural manipulation.

r2 -qc 'iS' <binary>       # Section table
r2 -qc 'iSS' <binary>      # Sections with entropy
for s in pe.sections:
    name = s.Name.decode().rstrip('\x00')
    entropy = s.get_entropy()
    raw = s.SizeOfRawData
    virt = s.Misc_VirtualSize
    ratio = virt / raw if raw > 0 else float('inf')
    chars = s.Characteristics
    rwx = f"{'R' if chars & 0x40000000 else '-'}{'W' if chars & 0x80000000 else '-'}{'X' if chars & 0x20000000 else '-'}"
    packed = "PACKED" if entropy > 7.0 else "HIGH" if entropy > 6.5 else ""
    inflated = "INFLATED" if ratio > 10 else ""
    print(f"{name:8s} raw={raw:>8d} virt={virt:>8d} ratio={ratio:>6.1f} entropy={entropy:.2f} {rwx} {packed} {inflated}")

Red flags: entropy > 7.0, VirtualSize >> RawSize, RWX permissions, packer section names (.UPX, .aspack, .themida, .vmp).

See `references/section-analysis.md` for section deep dive.

Step 4 — Import Analysis

Imports reveal the binary's capabilities. Missing or minimal imports suggest packing or dynamic resolution.

r2 -qc 'ii' <binary>
r2 -qc 'ii~CreateRemote' <binary>    # Search for injection APIs
r2 -qc 'ii~Virtual' <binary>         # Search for memory manipulation
if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'):
    for entry in pe.DIRECTORY_ENTRY_IMPORT:
        dll = entry.dll.decode()
        funcs = [i.name.decode() if i.name else f"ord#{i.ordinal}" for i in entry.imports]
        print(f"{dll} ({len(funcs)} imports): {', '.join(funcs[:5])}{'...' if len(funcs) > 5 else ''}")
else:
    print("NO IMPORT TABLE — likely packed or manually resolved")

Few imports (< 5 functions) from kernel32.dll only = strong packing indicator. Look for LoadLibrary + GetProcAddress as the only imports -- this means the binary resolves everything at runtime.

See `references/import-export-tables.md` for import/export deep dive.

Step 5 — Resource Analysis

Resources can contain embedded

Read more
Ships withfsociety

Multi-plugin marketplace for Claude Code offensive security plugins

Get the whole plugin

Other skills on fsociety.