Reading a PE header without running the file

The structure that tells you what a Windows executable is before you ever execute it, and the fields worth checking first.

pe-formatstatic-analysiswindows

Every Windows executable carries a substantial amount of self-description before a single instruction runs. Most triage questions can be answered from that structure alone, which is worth knowing when the alternative is detonating something in a sandbox and waiting.

Where to start

The DOS header at offset zero is largely vestigial, but its e_lfanew field at offset 0x3C points to the PE signature, and from there the COFF file header gives you the target machine, the number of sections, and the timestamp.

That timestamp is worth a moment. It is a build-time value written by the linker, trivially forgeable, and frequently either zeroed for reproducible builds or set to an obviously synthetic value. Treat a plausible timestamp as weak evidence and an implausible one as interesting.

The fields that carry the most signal

Section names and characteristics. The standard set is .text, .data, .rdata, .rsrc, .reloc. Names outside that set, sections that are both writable and executable, or a .text section with very high entropy all suggest packing or obfuscation.

The import table. What a binary imports is the closest thing to a statement of intent available without execution. A utility that imports only from kernel32 and msvcrt is doing something narrow. One that pulls in ws2_32, wininet, and advapi32 for registry and service functions is describing a much broader capability surface.

A very short import table on a large binary is itself a finding: it usually means imports are resolved at runtime, which is a deliberate choice.

The resource directory. Version resources hold the publisher name, product name, and file version that most inventory tools display. None of it is authenticated: it is metadata a compiler wrote because someone put it in a .rc file. It is useful as attribution when a signature is absent, and it should be weighted accordingly.

Why this matters for inventory

The gap between what a file claims to be and what its structure indicates is where useful categorisation lives. A file named TSClient.exe with a version resource naming one vendor, an import table describing something else entirely, and no signature is not an unknown. It is a specific finding with a specific confidence level attached.

More of this

New posts on what a file tells you before you run it: headers, signatures, manifests, overlays, the fields most inventory never reads. Only when there is something worth the write-up.

We intend to offer a tool that does this across every file on an endpoint. You get one message when you can use it.

One field, any address. Those two things and nothing else, and replying to any of it removes you.