PE Header Analysis
Analyzing Portable Executable headers including DOS header, COFF header, optional header, section tables, Import Address Table, and detecting packed binaries.
Contents
- 1. Tools for PE Analysis
- Quick Setup
- All Necessary Information
- 2. PE File Format Structure
- 3. DOS Header
- Quick Check
- 4. COFF File Header (IMAGE_FILE_HEADER)
- Timestamp Analysis
- 5. Optional Header (Key Fields)
- DllCharacteristics Security Flags
- 6. Section Headers (IMAGE_SECTION_HEADER)
- Standard Sections
- Suspicious Section Indicators
- 7. Packed Binary Detection
- What Happens When You Run a Packed Binary
- Packing Detection Checklist
- Common Packers & Their Signatures
- 8. Import Address Table (IAT) Analysis
- What to Check
- Red-Flag Import Patterns
- 9. Resources Section (.rsrc)
- Tools for Resource Analysis
- 10. Data Directories
- Debug Directory — Developer Info Leak
- 11. Quick PE Analysis Checklist
- Pro Tips
PE Header Analysis
Purpose: Analyze the structure of Windows executables (PE format) to identify compilation details, packing, suspicious characteristics, and behavioral indicators — all before running the file.
1. Tools for PE Analysis
Quick Setup
- PE-bear — Open PE-bear → File → Load PEs → drop executable
- PEAnatomist — Drop file into PEAnatomist for detailed timestamp and header analysis
- CFF Explorer — Full PE editor with hex view and structure browser
- pestudio — Automated PE analysis with threat indicators
- Detect It Easy (DiE) — Packer/compiler detection, entropy visualization
All Necessary Information
All header info, imports, resources, and debug info are visible on the main screen of PE-bear.
2. PE File Format Structure
+-----------------------------+
| DOS Header | <- Starts with "MZ" (0x4D 0x5A)
| (64 bytes) |
+-----------------------------+
| DOS Stub | <- "This program cannot be run in DOS mode"
| (Variable) |
+-----------------------------+
| PE Signature | <- "PE\0\0" (0x50 0x45 0x00 0x00)
+-----------------------------+
| COFF File Header | <- Machine type, number of sections, timestamp
| (20 bytes) |
+-----------------------------+
| Optional Header | <- Entry point, image base, subsystem
| (PE32: 96 + data dirs) |
| (PE32+: 112 + data dirs)|
+-----------------------------+
| Section Headers | <- .text, .data, .rdata, .rsrc, etc.
| (40 bytes each) |
+-----------------------------+
| Section Data |
| .text (code) |
| .rdata (read-only data) |
| .data (global vars) |
| .rsrc (resources) |
| .reloc (relocations) |
+-----------------------------+
3. DOS Header
- MZ on the blue screen or
4D 5Aon the white sheet (hex view) = it is an executable file - The DOS header is a legacy structure from MS-DOS — the only important field is:
e_lfanew(offset 0x3C) -> points to the PE signature
Quick Check
If first 2 bytes = "MZ" (0x4D 0x5A) -> Valid PE file
If e_lfanew points to "PE\0\0" -> Valid PE header found
4. COFF File Header (IMAGE_FILE_HEADER)
| Field | Offset | Meaning | Malware Relevance |
|---|---|---|---|
| Machine | 0x00 | Target architecture | 0x14C = x86, 0x8664 = x64 |
| NumberOfSections | 0x02 | How many sections | Unusual count = suspicious |
| TimeDateStamp | 0x04 | Compilation timestamp | When was it compiled? Fake? Future? |
| PointerToSymbolTable | 0x08 | Symbol table offset | Usually 0 for release builds |
| NumberOfSymbols | 0x0C | Symbol count | Usually 0 |
| SizeOfOptionalHeader | 0x10 | Optional header size | Varies by PE32/PE32+ |
| Characteristics | 0x12 | File attributes | DLL flag, executable, etc. |
Timestamp Analysis
PEAnatomist -> File Header section -> TimeDateStamp
Things to check:
- Is the timestamp realistic? (not year 1970 or 2038)
- Is it in the future? (forgery)
- Does it match other samples in the campaign?
- Is it 0x00000000? (stripped)
- Epoch converter: https://www.epochconverter.com/
5. Optional Header (Key Fields)
| Field | Meaning | Malware Relevance |
|---|---|---|
| Magic | 0x10B = PE32, 0x20B = PE32+ (64-bit) | Architecture identification |
| AddressOfEntryPoint | RVA where execution begins | Unusual location -> packed/injected |
| ImageBase | Preferred load address | Default: 0x400000 (exe), 0x10000000 (DLL) |
| SectionAlignment | Memory alignment | Usually 0x1000 (4KB) |
| FileAlignment | Disk alignment | Usually 0x200 (512 bytes) |
| SizeOfImage | Total memory size | Must match actual sections |
| Subsystem | GUI=2, Console=3, Driver=1 | What type of executable |
| DllCharacteristics | Security features | ASLR, DEP/NX, CFG, SEH flags |
| NumberOfRvaAndSizes | Data directory count | Usually 16 |
DllCharacteristics Security Flags
| Flag | Value | Meaning |
|---|---|---|
IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE | 0x0040 | ASLR enabled |
IMAGE_DLLCHARACTERISTICS_NX_COMPAT | 0x0100 | DEP/NX enabled |
IMAGE_DLLCHARACTERISTICS_NO_SEH | 0x0400 | No SEH (Structured Exception Handling) |
IMAGE_DLLCHARACTERISTICS_GUARD_CF | 0x4000 | Control Flow Guard enabled |
Malware with no security flags = compiled without protections (intentional or old compiler)
6. Section Headers (IMAGE_SECTION_HEADER)
Standard Sections
| Section | Purpose | Expected Characteristics |
|---|---|---|
.text | Executable code | IMAGE_SCN_MEM_EXECUTE + IMAGE_SCN_MEM_READ |
.rdata | Read-only initialized data, imports | IMAGE_SCN_MEM_READ |
.data | Read-write initialized data | IMAGE_SCN_MEM_READ + IMAGE_SCN_MEM_WRITE |
.bss | Uninitialized data | IMAGE_SCN_MEM_READ + IMAGE_SCN_MEM_WRITE |
.rsrc | Resources (icons, dialogs, version) | IMAGE_SCN_MEM_READ |
.reloc | Relocation data (for ASLR) | IMAGE_SCN_MEM_READ |
Suspicious Section Indicators
| Indicator | What It Means |
|---|---|
Section with RWX (Read+Write+Execute) | Self-modifying code or shellcode unpacking |
Unknown section names (.upx0, .aspack) | Known packer sections |
Entry point outside .text section | Packed — stub in different section |
.text section is WRITEable | Self-modifying code |
| Very high entropy in a section (>7.0) | Compressed or encrypted content |
| Huge gap between VirtualSize and RawSize | Packer will expand data in memory |
7. Packed Binary Detection
- If the size of raw data is almost equal to the virtual size (IMAGE_SECTION_HEADER .text) then it is not a packed binary
- A packed binary is a normal Windows PE executable (.exe, .dll, .sys, etc.) that has been compressed or encrypted by a special tool called a packer (or crypter/protector)
What Happens When You Run a Packed Binary
- The packed file is very small or looks like random/garbage data
- At runtime, a small piece of code (the stub or unpacking stub) executes first
- This stub decompresses or decrypts the real original program in memory
- The stub then jumps to the real program’s original entry point (OEP) and the malware runs normally
Packing Detection Checklist
[ ] Virtual Size >> Raw Size for .text section? -> PACKED
[ ] Entry point in unusual section (not .text)? -> PACKED
[ ] Very few imports (only LoadLibrary/GetProcAddress)? -> PACKED
[ ] Section names match known packers? -> PACKED
[ ] High entropy (>7.0) across sections? -> PACKED
[ ] Few/no meaningful strings? -> PACKED
[ ] Detect It Easy / PEiD identifies a packer? -> PACKED
Common Packers & Their Signatures
| Packer | Section Names | Other Indicators |
|---|---|---|
| UPX | .UPX0, .UPX1 | UPX! magic at end of file |
| ASPack | .aspack, .adata | ASPack string in overlay |
| Themida / WinLicense | .themida | Virtualized code |
| VMProtect | .vmp0, .vmp1 | Code virtualization |
| PECompact | .pec, PECompact header | PECompact2 string |
| MPRESS | .MPRESS1, .MPRESS2 | Similar to UPX |
| Enigma Protector | .enigma1, .enigma2 | Anti-debug, anti-dump |
8. Import Address Table (IAT) Analysis
The IAT lists all DLL functions the binary imports:
What to Check
PE-bear -> Imports tab
-> Which DLLs are imported?
-> Which functions from each DLL?
-> Do the imports match the claimed functionality?
Red-Flag Import Patterns
| Pattern | Interpretation |
|---|---|
Only kernel32.dll with LoadLibrary + GetProcAddress | Dynamic resolution — hiding real imports |
ws2_32.dll + wininet.dll imports | Network communication |
crypt32.dll imports | Encryption/decryption |
VirtualAllocEx + WriteProcessMemory | Process injection |
| No imports at all | Heavily packed or uses syscalls |
ntdll.dll Nt* functions | Direct syscalls, EDR evasion |
9. Resources Section (.rsrc)
Resources can contain:
- Icons — Social engineering (mimicking legitimate software)
- Version info — Fake publisher, product name
- Embedded binaries — Payloads hidden in resources
- Configuration data — Encrypted C2 config
- Dialogs — Ransom notes, fake error messages
Tools for Resource Analysis
| Tool | Use |
|---|---|
| Resource Hacker | View/extract/edit all resources |
| PE-bear | Resources tab shows resource tree |
| 7-Zip | Can open PE resources as archive |
| binwalk | Find embedded files in resources |
10. Data Directories
| Index | Name | Malware Relevance |
|---|---|---|
| 0 | Export Table | DLL exports (check for suspicious function names) |
| 1 | Import Table | IAT — critical for behavior analysis |
| 2 | Resource Table | Embedded payloads, configs |
| 5 | Base Relocation | Needed for ASLR |
| 6 | Debug | PDB path -> developer machine info |
| 11 | Bound Import | Rarely used — if present, suspicious |
| 12 | IAT | Runtime import resolution |
| 14 | CLR Runtime Header | .NET binary indicator |
Debug Directory — Developer Info Leak
The PDB (Program Database) path can leak:
- Developer username
- Project folder structure
- Development machine OS
- Build environment
Example: C:\Users\attackerName\Desktop\malware_project\Release\payload.pdb
11. Quick PE Analysis Checklist
[ ] 1. Verify MZ header (is it actually a PE file?)
[ ] 2. Check architecture (x86 vs x64)
[ ] 3. Read timestamp (when compiled?)
[ ] 4. Check entry point location (in .text? -> normal)
[ ] 5. Examine sections (names, sizes, entropy, permissions)
[ ] 6. Detect packing (VirtualSize vs RawSize, entropy, DiE)
[ ] 7. Analyze imports (which APIs? -> predict behavior)
[ ] 8. Check resources (embedded files? fake version info?)
[ ] 9. Look for debug info (PDB path leak?)
[ ] 10. Check DLL characteristics (security flags)
[ ] 11. Calculate hashes (MD5/SHA256) -> VirusTotal lookup
[ ] 12. Run through pestudio for automated indicators
Pro Tips
Use pestudio for automated first-pass — It highlights suspicious imports, strings, and sections with color-coded indicators. Best initial triage tool.
Entropy is your packing detector — Normal
.textsection: ~6.0 entropy. Packed/encrypted: ~7.5+. Use DiE for visual entropy graphs.
Fake timestamps are common — Malware authors often set timestamps to 0, far in the past, or match legitimate software timestamps. Never trust timestamps alone.
Resources hide payloads — Many malware families (Emotet, QakBot) embed encrypted payloads in the PE resource section, decoded at runtime.