The internal structure of Windows executables — DOS header, PE signature, File Header, Optional Header, Data Directories, section table, and the anomalies that signal malware.
⚡ Quick Bite · 60s
The PE format blueprint for every Windows binary — DOS Header to Sections, on-disk vs in-memory layout, critical headers (EntryPoint, ImageBase, RVAs), and anomaly detection for packed binaries.
Watch this 60-second summary before diving into the full article. Sign in to earn 5 leaderboard points.
The Portable Executable format is used by multiple Windows file types — not just .exe files:
| Extension | Type | Macro Support |
|---|---|---|
.exe | Executable | No (runs directly) |
.dll | Dynamic Library | No (hosted by executable) |
.sys | Kernel Driver | No |
.scr | Screensaver | No |
.cpl | Control Panel | No |
.ocx | ActiveX Control | No |
.drv | Device Driver | No |
.efi | UEFI Application | No |
Files that are not PE format: .bat, .ps1, .jar, .py, .msi.
Think of a PE file as a well-organised book:
The PE format is a data structure roadmap — a series of headers and tables that tell the Windows loader exactly how to map the file from disk into a process's virtual address space.
On-disk file layout ≠ In-memory layout
Sections are aligned differently on disk (typically 512-byte boundaries) versus in memory (typically 4096-byte page boundaries). The PE header contains both sets of values, and the Windows loader performs the translation during execution.
Refer to REMA eBook 2026, Figure 2.7 for the full PE structure diagram.
┌─────────────────────────┐
│ DOS MZ Header │ Magic bytes: 4D 5A ("MZ")
│ DOS Stub │ "This program cannot be run in DOS mode"
├─────────────────────────┤
│ PE Signature │ 50 45 00 00 ("PE\0\0")
│ File Header │ Machine type, section count, timestamp
│ Optional Header │ Entry point, image base, section alignment
│ Data Directories (16) │ Pointers to IAT, exports, resources, TLS...
├─────────────────────────┤
│ Section Table │ Array of section headers
├─────────────────────────┤
│ .text │ Executable code (R-X)
│ .rdata │ Read-only data, IAT, export tables (R--)
│ .data │ Initialised global variables (RW-)
│ .rsrc │ Resources: icons, dialogs, embedded files (R--)
│ .reloc │ Relocation data for ASLR (R--)
└─────────────────────────┘
4D 5A (ASCII "MZ") — the magic bytes confirming a PE filee_lfanew at offset 0x3C — pointer to the PE signature. Malware sometimes manipulates this to confuse parsers.0x014C = x86, 0x8664 = x64Despite the name, mandatory for executables.
0x00400000 for 32-bit EXEs. ASLR may relocate this.| Index | Directory | Malware Relevance |
|---|---|---|
| 0 | Export Table | Malicious DLLs export hooks |
| 1 | Import Table | Reveals capabilities via imported functions |
| 2 | Resource Table | Payloads hidden in resources |
| 9 | TLS Table | Callbacks execute before entry point — anti-debug |
| 5 | Base Relocation | Absence indicates position-dependent code |
Each section has a characteristics bitmask encoding permissions:
| Section | Permissions | Rationale |
|---|---|---|
.text | R-X | Code: readable and executable |
.data | RW- | Variables: readable and writable |
.rdata | R-- | Constants: read-only |
Red flag: a section marked both Writable and Executable (RWX). Legitimate compilers rarely produce RWX sections. Malware uses VirtualProtect to change section permissions at runtime, converting a data region into executable memory for injected shellcode.
PE headers store addresses as Relative Virtual Addresses — offsets from the image base, not absolute addresses.
Virtual Address (VA) = ImageBase + RVA
When ASLR is active, the ImageBase changes on every load, but all RVAs remain correct relative to wherever the image is loaded.
| Anomaly | Interpretation |
|---|---|
Entry point outside .text section | Packed or injected code |
| RWX section permissions | Self-modifying code, runtime unpacking |
| Section entropy > 7.0 | Encrypted or compressed content |
Non-standard section names (.UPX0, .aspack) | Known packer signatures |
Minimal IAT (only LoadLibraryA + GetProcAddress) | Dynamic import resolution hiding real imports |
| TLS callbacks present | Pre-entry-point code execution (anti-debug) |
| VirtualSize >> SizeOfRawData | Data populated at runtime (unpacking target) |
| Future or ancient timestamp | Spoofed compilation time |
The Corkami PE101 poster by Ange Albertini provides an exhaustive visual reference mapping every PE field to its hex offset. Search "corkami PE101" — available free under Creative Commons.
Sign in to mark this article as read and track your progress.