PE Structure: Complete Visual Guide
Table of Contents
PE Structure: Complete Visual Guide
Table of Contents
- High-Level PE Architecture
- Component Flow Diagram
- File Layout with Offsets
- Memory Layout (RVA and VA)
- Offset Conversion Examples
- Interactive Component Map
High-Level PE Architecture
The Big Picture: How PE Components Work Together
┌─────────────────────────────────────────────────────────────────────────┐
│ PORTABLE EXECUTABLE (PE) │
│ │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ 1. DOS HEADER (64 bytes) │ │
│ │ ┌──────────────────────────────────────────────────────────┐ │ │
│ │ │ e_magic: "MZ" (0x5A4D) │ │ │
│ │ │ ... (other DOS fields - mostly obsolete) │ │ │
│ │ │ e_lfanew: 0x000000F0 ──────────────────┐ │ │ │
│ │ └──────────────────────────────────────────│────────────────┘ │ │
│ └────────────────────────────────────────────│───────────────────┘ │
│ │ │
│ ┌────────────────────────────────────────────│───────────────────┐ │
│ │ 2. DOS STUB (176 bytes) │ │ │
│ │ ┌──────────────────────────────────────┐ │ │ │
│ │ │ 16-bit DOS Program Code │ │ │ │
│ │ │ "This program cannot be run in │ │ │ │
│ │ │ DOS mode." │ │ │ │
│ │ │ │ │ │ │
│ │ │ May also contain: │ │ │ │
│ │ │ - Rich Header (compiler metadata) │ │ │ │
│ │ │ - Custom code │ │ │ │
│ │ └──────────────────────────────────────┘ │ │ │
│ └─────────────────────────────────────────────┘ │ │
│ │ │
│ ┌─────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ 3. PE SIGNATURE (4 bytes) │ │
│ │ "PE\0\0" (0x00004550) │ │
│ └────────────────────────────────────────────────────────────────┘ │
│ ▼ │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ 4. COFF FILE HEADER (20 bytes) │ │
│ │ ┌──────────────────────────────────────────────────────────┐ │ │
│ │ │ Machine: 0x8664 (x64) │ │ │
│ │ │ NumberOfSections: 6 │ │ │
│ │ │ TimeDateStamp: 0x12345678 │ │ │
│ │ │ SizeOfOptionalHeader: 240 (0xF0) │ │ │
│ │ │ Characteristics: 0x0022 (EXECUTABLE_IMAGE | LARGE_ADDR) │ │ │
│ │ └──────────────────────────────────────────────────────────┘ │ │
│ └────────────────────────────────────────────────────────────────┘ │
│ ▼ │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ 5. OPTIONAL HEADER (240 bytes for PE32+) │ │
│ │ ┌──────────────────────────────────────────────────────────┐ │ │
│ │ │ Magic: 0x020B (PE32+) / 0x010B (PE32) │ │ │
│ │ │ AddressOfEntryPoint: 0x00001000 ────┐ │ │ │
│ │ │ ImageBase: 0x0000000140000000 │ │ │ │
│ │ │ SectionAlignment: 0x1000 (4KB) │ │ │ │
│ │ │ FileAlignment: 0x200 (512 bytes) │ │ │ │
│ │ │ SizeOfImage: 0x00008000 │ │ │ │
│ │ │ SizeOfHeaders: 0x00000400 │ │ │ │
│ │ │ Subsystem: 3 (CUI - Console) │ │ │ │
│ │ │ DllCharacteristics: 0x4160 │ │ │ │
│ │ │ (ASLR | DEP | NO_SEH | CFG) │ │ │ │
│ │ │ ───────────────────────────────── │ │ │ │
│ │ │ NumberOfRvaAndSizes: 16 │ │ │ │
│ │ │ │ │ │ │
│ │ │ DATA DIRECTORIES [16]: │ │ │ │
│ │ │ ┌────────────────────────────────┐ │ │ │ │
│ │ │ │ [0] Export Table │ RVA/Sz │ │ │ │ │
│ │ │ │ [1] Import Table ────┼────────┼──┼───────┐ │ │ │
│ │ │ │ [2] Resource Table │ RVA/Sz │ │ │ │ │ │
│ │ │ │ [3] Exception Table │ RVA/Sz │ │ │ │ │ │
│ │ │ │ [4] Certificate Table │ RVA/Sz │ │ │ │ │ │
│ │ │ │ [5] Base Reloc Table │ RVA/Sz │ │ │ │ │ │
│ │ │ │ [6] Debug Directory │ RVA/Sz │ │ │ │ │ │
│ │ │ │ [7] Architecture │ 0/0 │ │ │ │ │ │
│ │ │ │ [8] Global Ptr │ RVA/Sz │ │ │ │ │ │
│ │ │ │ [9] TLS Table │ RVA/Sz │ │ │ │ │ │
│ │ │ │ [10] Load Config │ RVA/Sz │ │ │ │ │ │
│ │ │ │ [11] Bound Import │ RVA/Sz │ │ │ │ │ │
│ │ │ │ [12] IAT ────┼────────┼──┼───┐ │ │ │ │
│ │ │ │ [13] Delay Import │ RVA/Sz │ │ │ │ │ │ │
│ │ │ │ [14] CLR Header │ RVA/Sz │ │ │ │ │ │ │
│ │ │ │ [15] Reserved │ 0/0 │ │ │ │ │ │ │
│ │ │ └────────────────────────────────┘ │ │ │ │ │ │
│ │ └──────────────────────────────────────┘ │ │ │ │ │
│ └───────────────────────────────────────────┘ │ │ │ │ │
│ ▼ │ │ │ │ │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ 6. SECTION HEADERS (40 bytes each × 6) │ │
│ │ ┌──────────────────────────────────────────────────────────┐ │ │
│ │ │ .text Section Header: │ │ │
│ │ │ Name: ".text\0\0\0" │ │ │
│ │ │ VirtualSize: 0x2C48 │ │ │
│ │ │ VirtualAddress: 0x1000 ◄───────────────────────────────┼──┼────┤Entry
│ │ │ SizeOfRawData: 0x3000 │ │ │Point
│ │ │ PointerToRawData: 0x400 │ │ │
│ │ │ Characteristics: 0x60000020 (CODE | EXECUTE | READ) │ │ │
│ │ ├──────────────────────────────────────────────────────────┤ │ │
│ │ │ .rdata Section Header: │ │ │
│ │ │ VirtualAddress: 0x4000 ◄─────────────────────────┐ │ │ │
│ │ │ PointerToRawData: 0x3400 │ │ │ │
│ │ │ Contains: Import Table, IAT ◄──────────┐ ◄──────┼─────┼──┼────┤Import
│ │ ├────────────────────────────────────────────┼────────┼─────┤ │ │& IAT
│ │ │ .data Section Header: │ │ │ │ │
│ │ │ VirtualAddress: 0x6000 │ │ │ │ │
│ │ │ Characteristics: 0xC0000040 (INIT_DATA│ WRITE) │ │ │ │
│ │ ├──────────────────────────────────────────────────────┤ │ │ │
│ │ │ .pdata Section Header (x64 exception data): │ │ │ │
│ │ │ VirtualAddress: 0x7000 │ │ │ │
│ │ ├──────────────────────────────────────────────────────┤ │ │ │
│ │ │ .rsrc Section Header: │ │ │ │
│ │ │ VirtualAddress: 0x8000 │ │ │ │
│ │ │ Contains: Resources (icons, version info, etc) │ │ │ │
│ │ ├──────────────────────────────────────────────────────┤ │ │ │
│ │ │ .reloc Section Header: │ │ │ │
│ │ │ VirtualAddress: 0x9000 │ │ │ │
│ │ │ Contains: Base relocation table │ │ │ │
│ │ └──────────────────────────────────────────────────────┘ │ │ │
│ └─────────────────────────────────────────────────────────┘ │ │ │
│ ▼ │ │ │
│ ┌────────────────────────────────────────────────────────────────┐ │ │
│ │ 7. SECTION DATA │ │ │
│ │ ┌──────────────────────────────────────────────────────────┐ │ │ │
│ │ │ .text Section (Executable Code) │ │ │ │
│ │ │ Offset: 0x400, Size: 0x3000 (on disk) │ │ │ │
│ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ │
│ │ │ │ 55 8B EC 83 EC 20 48 8B 45 10 ... │ │ │ │ │
│ │ │ │ (Machine code instructions) │ │ │ │ │
│ │ │ │ - Function prologues │ │ │ │ │
│ │ │ │ - API calls │ │ │ │ │
│ │ │ │ - Business logic │ │ │ │ │
│ │ │ └────────────────────────────────────────────────────┘ │ │ │ │
│ │ ├──────────────────────────────────────────────────────────┤ │ │ │
│ │ │ .rdata Section (Read-only Data) │ │ │ │
│ │ │ Offset: 0x3400, Size: 0x2000 │ │ │ │
│ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ │
│ │ │ │ IMPORT DIRECTORY TABLE ◄────────────────────────────┼──┼──┘ │
│ │ │ │ ┌──────────────────────────────────────────────┐ │ │ │ │
│ │ │ │ │ Descriptor for kernel32.dll: │ │ │ │ │
│ │ │ │ │ OriginalFirstThunk: 0x4100 (ILT) │ │ │ │ │
│ │ │ │ │ Name: 0x4200 → "kernel32.dll" │ │ │ │ │
│ │ │ │ │ FirstThunk: 0x4300 (IAT) ◄─────────────────┼──┼──┼──┘ │
│ │ │ │ ├──────────────────────────────────────────────┤ │ │ │ │
│ │ │ │ │ Descriptor for user32.dll: │ │ │ │ │
│ │ │ │ │ OriginalFirstThunk: 0x4150 │ │ │ │ │
│ │ │ │ │ Name: 0x4210 → "user32.dll" │ │ │ │ │
│ │ │ │ │ FirstThunk: 0x4350 (IAT) │ │ │ │ │
│ │ │ │ └──────────────────────────────────────────────┘ │ │ │ │
│ │ │ │ │ │ │ │
│ │ │ │ IMPORT LOOKUP TABLE (ILT): │ │ │ │
│ │ │ │ ┌──────────────────────────────────────────────┐ │ │ │ │
│ │ │ │ │ 0x4100: Hint/Name RVA → "GetProcAddress" │ │ │ │ │
│ │ │ │ │ 0x4108: Hint/Name RVA → "LoadLibraryA" │ │ │ │ │
│ │ │ │ │ 0x4110: NULL (terminator) │ │ │ │ │
│ │ │ │ └──────────────────────────────────────────────┘ │ │ │ │
│ │ │ │ │ │ │ │
│ │ │ │ IMPORT ADDRESS TABLE (IAT): │ │ │ │
│ │ │ │ ┌──────────────────────────────────────────────┐ │ │ │ │
│ │ │ │ │ Before Loading: │ │ │ │ │
│ │ │ │ │ 0x4300: RVA to "GetProcAddress" │ │ │ │ │
│ │ │ │ │ 0x4308: RVA to "LoadLibraryA" │ │ │ │ │
│ │ │ │ │ │ │ │ │ │
│ │ │ │ │ After Loading (by Windows loader): │ │ │ │ │
│ │ │ │ │ 0x4300: 0x00007FF8A2B41000 (actual addr) │ │ │ │ │
│ │ │ │ │ 0x4308: 0x00007FF8A2B41050 (actual addr) │ │ │ │ │
│ │ │ │ └──────────────────────────────────────────────┘ │ │ │ │
│ │ │ │ │ │ │ │
│ │ │ │ String literals, const data, vtables... │ │ │ │
│ │ │ └────────────────────────────────────────────────────┘ │ │ │
│ │ ├──────────────────────────────────────────────────────────┤ │ │
│ │ │ .data Section (Initialized Data) │ │ │
│ │ │ Offset: 0x5400, Size: 0x1000 │ │ │
│ │ │ ┌────────────────────────────────────────────────────┐ │ │ │
│ │ │ │ Global variables, static data │ │ │ │
│ │ │ └────────────────────────────────────────────────────┘ │ │ │
│ │ ├──────────────────────────────────────────────────────────┤ │ │
│ │ │ .pdata Section (Exception Handling - x64) │ │ │
│ │ │ Runtime function entries for stack unwinding │ │ │
│ │ ├──────────────────────────────────────────────────────────┤ │ │
│ │ │ .rsrc Section (Resources) │ │ │
│ │ │ Icons, bitmaps, dialogs, version info │ │ │
│ │ ├──────────────────────────────────────────────────────────┤ │ │
│ │ │ .reloc Section (Base Relocations) │ │ │
│ │ │ Fixup information for ASLR │ │ │
│ │ └──────────────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────┘ │ │
└────────────────────────────────────────────────────────────────────┘ │
Component Flow Diagram
How PE Loading Works: Step by Step
┌─────────────────────────────┐
│ User Double-Clicks EXE │
│ or CreateProcess() called │
└──────────────┬──────────────┘
▼
┌─────────────────────────────┐
│ Windows Kernel (ntdll) │
│ PE Loader Begins │
└──────────────┬──────────────┘
▼
╔══════════════════════════════════════════════════════╗
║ STEP 1: VALIDATE DOS HEADER ║
╚══════════════════════════════════════════════════════╝
│
┌──────────────▼──────────────┐
│ Read first 2 bytes │
│ Check: e_magic == 0x5A4D? │
└──────────────┬──────────────┘
│
┌─────────┴─────────┐
│ Yes │ No
▼ ▼
┌──────────────────┐ ┌─────────────────┐
│ Valid DOS Header │ │ ERROR: │
│ Continue... │ │ Not a valid exe │
└─────────┬────────┘ └─────────────────┘
│
╔═══════════════▼════════════════════════════════════╗
║ STEP 2: LOCATE PE HEADER ║
╚════════════════════════════════════════════════════╝
│
┌──────────────▼──────────────┐
│ Read e_lfanew (offset 0x3C)│
│ e_lfanew = 0x000000F0 │
└──────────────┬──────────────┘
│
┌──────────────▼──────────────┐
│ Seek to offset 0xF0 │
│ Read 4 bytes │
│ Check: == "PE\0\0"? │
└──────────────┬──────────────┘
│
┌─────────┴─────────┐
│ Yes │ No
▼ ▼
┌──────────────────┐ ┌─────────────────┐
│ Valid PE Sig │ │ ERROR: │
│ Continue... │ │ Invalid PE file │
└─────────┬────────┘ └─────────────────┘
│
╔════▼═══════════════════════════════════════════════╗
║ STEP 3: READ COFF FILE HEADER ║
╚════════════════════════════════════════════════════╝
│
┌────────────▼────────────┐
│ Parse COFF Header: │
│ - Machine type (x64?) │
│ - Number of sections │
│ - Characteristics │
└────────────┬────────────┘
│
╔════▼═══════════════════════════════════════════════╗
║ STEP 4: READ OPTIONAL HEADER ║
╚════════════════════════════════════════════════════╝
│
┌────────────▼────────────────┐
│ Parse Optional Header: │
│ - ImageBase (0x140000000) │
│ - AddressOfEntryPoint │
│ - SectionAlignment (0x1000)│
│ - FileAlignment (0x200) │
│ - SizeOfImage │
│ - Data Directories [16] │
└────────────┬────────────────┘
│
╔════▼═══════════════════════════════════════════════╗
║ STEP 5: ALLOCATE VIRTUAL MEMORY ║
╚════════════════════════════════════════════════════╝
│
┌────────────▼────────────────┐
│ NtAllocateVirtualMemory() │
│ │
│ Try to allocate at: │
│ ImageBase = 0x140000000 │
│ Size = SizeOfImage │
└────────────┬────────────────┘
│
┌─────────┴──────────┐
│ Success │ Fail (address taken)
▼ ▼
┌──────────┐ ┌─────────────────────┐
│ Use │ │ Allocate elsewhere │
│ImageBase │ │ Will need relocation│
└────┬─────┘ └──────────┬──────────┘
│ │
└───────────┬───────────┘
│
╔════════▼═══════════════════════════════════════════╗
║ STEP 6: MAP SECTIONS INTO MEMORY ║
╚════════════════════════════════════════════════════╝
│
┌────────────────▼───────────────┐
│ For each section header: │
│ │
│ Read from file offset: │
│ PointerToRawData │
│ │
│ Copy SizeOfRawData bytes to: │
│ Base + VirtualAddress │
│ │
│ Zero-fill remaining: │
│ VirtualSize - SizeOfRawData │
│ │
│ Set memory permissions: │
│ Based on Characteristics │
└────────────────┬───────────────┘
│
Example: .text section
│
┌────────────▼────────────┐
│ File Offset: 0x400 │
│ Read 0x3000 bytes ────┐ │
│ │ │
│ Memory: Base + 0x1000 │ │
│ Write 0x3000 bytes ◄──┘ │
│ Permissions: RX │
└────────────┬────────────┘
│
╔════════▼═══════════════════════════════════════════╗
║ STEP 7: PROCESS BASE RELOCATIONS ║
╚════════════════════════════════════════════════════╝
│
┌────────────▼────────────┐
│ If loaded at ImageBase: │
│ Skip relocations │
│ Else: │
│ delta = Actual - Base │
│ Process .reloc section│
│ Fix all addresses │
└────────────┬────────────┘
│
╔════════▼═══════════════════════════════════════════╗
║ STEP 8: RESOLVE IMPORTS ║
╚════════════════════════════════════════════════════╝
│
┌────────────▼─────────────────┐
│ For each DLL in Import Table:│
│ │
│ 1. LoadLibrary(DLL name) │
│ e.g., kernel32.dll │
│ │
│ 2. For each function: │
│ GetProcAddress(func name) │
│ e.g., "CreateFileW" │
│ │
│ 3. Write actual address to │
│ Import Address Table (IAT)│
└────────────┬─────────────────┘
│
Example flow:
│
┌────────────▼────────────────┐
│ Import Entry: │
│ DLL: kernel32.dll │
│ Function: CreateFileW │
│ │
│ IAT Entry (before): │
│ 0x00004300: RVA to name │
│ │
│ Loader calls: │
│ hDll = LoadLibrary( │
│ "kernel32.dll") │
│ pFunc = GetProcAddress( │
│ hDll, "CreateFileW") │
│ │
│ IAT Entry (after): │
│ 0x00004300: │
│ 0x7FF8A2B41234 │
│ (actual function addr) │
└────────────┬────────────────┘
│
╔════════▼═══════════════════════════════════════════╗
║ STEP 9: EXECUTE TLS CALLBACKS ║
╚════════════════════════════════════════════════════╝
│
┌────────────▼────────────────┐
│ If TLS Directory exists: │
│ │
│ For each TLS callback: │
│ Call callback( │
│ DLL_PROCESS_ATTACH) │
│ │
│ ⚠️ Executes BEFORE entry pt │
└────────────┬────────────────┘
│
╔════════▼═══════════════════════════════════════════╗
║ STEP 10: TRANSFER CONTROL TO ENTRY POINT ║
╚════════════════════════════════════════════════════╝
│
┌────────────▼────────────────┐
│ Calculate entry address: │
│ Base + AddressOfEntryPoint│
│ │
│ e.g., │
│ 0x140000000 + 0x1000 │
│ = 0x140001000 │
│ │
│ Set instruction pointer: │
│ RIP = 0x140001000 │
│ │
│ Jump to entry point! │
└────────────┬────────────────┘
│
▼
╔═════════════════════════════════════════════════╗
║ PROGRAM EXECUTION BEGINS ║
║ ║
║ Entry point typically calls: ║
║ - CRT initialization (__scrt_common_main) ║
║ - Global constructors ║
║ - main() or WinMain() ║
╚═════════════════════════════════════════════════╝
File Layout with Offsets
Complete PE File Structure with Byte Offsets
FILE OFFSET SIZE COMPONENT CONTENTS
═══════════════════════════════════════════════════════════════════════════════
0x00000000 64 bytes ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ DOS HEADER ┃
┃ ┃
┃ 0x00: 4D 5A (MZ) ┃
┃ 0x02: e_cblp = 0x0090 ┃
┃ 0x04: e_cp = 0x0003 ┃
┃ ... ┃
┃ 0x3C: e_lfanew = 0x00F0 ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
0x00000040 176 bytes ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ DOS STUB ┃
┃ ┃
┃ 0E 1F BA 0E 00 B4 09... ┃
┃ "This program cannot be ┃
┃ run in DOS mode." ┃
┃ ┃
┃ May contain Rich Header: ┃
┃ DanS ... Rich [XOR key] ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
0x000000F0 4 bytes ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ PE SIGNATURE ┃
┃ 50 45 00 00 (PE\0\0) ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
0x000000F4 20 bytes ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ COFF FILE HEADER ┃
┃ ┃
┃ Machine: 64 86 (x64) ┃
┃ NumberOfSections: 06 00 ┃
┃ TimeDateStamp: ... ┃
┃ SizeOfOptionalHdr: F0 00 ┃
┃ Characteristics: 22 00 ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
0x00000108 240 bytes ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
(PE32+) ┃ OPTIONAL HEADER ┃
┃ ┃
┃ Magic: 0B 02 (PE32+) ┃
┃ ... ┃
┃ AddressOfEntryPoint: ┃
┃ 00 10 00 00 ┃
┃ ImageBase: ┃
┃ 00 00 00 40 01 00 00 00 ┃
┃ SectionAlignment: ┃
┃ 00 10 00 00 (4096) ┃
┃ FileAlignment: ┃
┃ 00 02 00 00 (512) ┃
┃ SizeOfImage: ┃
┃ 00 80 00 00 ┃
┃ SizeOfHeaders: ┃
┃ 00 04 00 00 ┃
┃ Subsystem: 03 00 (CUI) ┃
┃ DllCharacteristics: ┃
┃ 60 41 ┃
┃ ... ┃
┃ NumberOfRvaAndSizes: ┃
┃ 10 00 00 00 ┃
┃ ┃
┃ DATA DIRECTORIES: ┃
┃ [0] Export: 00/00 ┃
┃ [1] Import: 4100/00A0 ┃
┃ [2] Resource:8000/1000 ┃
┃ [3] Exception:7000/0300 ┃
┃ [4] Security: 00/00 ┃
┃ [5] BaseReloc:9000/0500 ┃
┃ [6] Debug: 00/00 ┃
┃ [7-11]: ... ┃
┃ [12] IAT: 4300/0100 ┃
┃ [13-15]: ... ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
0x000001F8 240 bytes ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
(6×40) ┃ SECTION HEADERS ┃
┃ ┃
┃ ┌───────────────────────┐ ┃
┃ │ .text │ ┃
┃ │ VirtualSize: 2C480000 │ ┃
┃ │ VirtualAddr: 10000000 │ ┃
┃ │ SizeOfRaw: 30000000 │ ┃
┃ │ PtrToRaw: 04000000 │ ┃
┃ │ Chars: 20000060 │ ┃
┃ └───────────────────────┘ ┃
┃ ┌───────────────────────┐ ┃
┃ │ .rdata │ ┃
┃ │ VirtualSize: 1A420000 │ ┃
┃ │ VirtualAddr: 40000000 │ ┃
┃ │ SizeOfRaw: 20000000 │ ┃
┃ │ PtrToRaw: 04340000 │ ┃
┃ │ Chars: 40000040 │ ┃
┃ └───────────────────────┘ ┃
┃ ┌───────────────────────┐ ┃
┃ │ .data │ ┃
┃ │ VirtualAddr: 60000000 │ ┃
┃ │ PtrToRaw: 04540000 │ ┃
┃ └───────────────────────┘ ┃
┃ ┌───────────────────────┐ ┃
┃ │ .pdata (x64) │ ┃
┃ │ VirtualAddr: 70000000 │ ┃
┃ │ PtrToRaw: 04640000 │ ┃
┃ └───────────────────────┘ ┃
┃ ┌───────────────────────┐ ┃
┃ │ .rsrc │ ┃
┃ │ VirtualAddr: 80000000 │ ┃
┃ │ PtrToRaw: 04740000 │ ┃
┃ └───────────────────────┘ ┃
┃ ┌───────────────────────┐ ┃
┃ │ .reloc │ ┃
┃ │ VirtualAddr: 90000000 │ ┃
┃ │ PtrToRaw: 04840000 │ ┃
┃ └───────────────────────┘ ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
0x000002E8 280 bytes ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ PADDING TO FILE ALIGN ┃
┃ (00 00 00 00 ...) ┃
┃ ┃
┃ Headers must align to ┃
┃ FileAlignment (0x200) ┃
┃ ┃
┃ Next section starts at: ┃
┃ 0x400 (1024) ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
════════════════════ SECTION DATA BEGINS ════════════════════
0x00000400 12,288 bytes ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
(0x3000) ┃ .text SECTION ┃
┃ (Executable Code) ┃
┃ ┃
┃ 55 8B EC 83 EC 20 ... ┃
┃ ┃
┃ Contains: ┃
┃ - Entry point code ┃
┃ - All functions ┃
┃ - Main logic ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
0x00003400 8,192 bytes ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
(0x2000) ┃ .rdata SECTION ┃
┃ (Read-Only Data) ┃
┃ ┃
┃ ┌─ Import Directory ───┐ ┃
┃ │ │ ┃
┃ │ Descriptor entries: │ ┃
┃ │ │ ┃
┃ │ [kernel32.dll] │ ┃
┃ │ OrigFirstThunk:4100 │ ┃
┃ │ Name RVA: 4200 │ ┃
┃ │ FirstThunk: 4300 │ ┃
┃ │ │ ┃
┃ │ [user32.dll] │ ┃
┃ │ OrigFirstThunk:4150 │ ┃
┃ │ Name RVA: 4210 │ ┃
┃ │ FirstThunk: 4350 │ ┃
┃ │ │ ┃
┃ │ NULL (terminator) │ ┃
┃ └───────────────────────┘ ┃
┃ ┃
┃ ┌─ Import Lookup Table ┐ ┃
┃ │ (OriginalFirstThunk) │ ┃
┃ │ │ ┃
┃ │ RVA to "CreateFileW" │ ┃
┃ │ RVA to "ReadFile" │ ┃
┃ │ RVA to "WriteFile" │ ┃
┃ │ NULL │ ┃
┃ └───────────────────────┘ ┃
┃ ┃
┃ ┌─ DLL Names ──────────┐ ┃
┃ │ "kernel32.dll\0" │ ┃
┃ │ "user32.dll\0" │ ┃
┃ └───────────────────────┘ ┃
┃ ┃
┃ ┌─ Function Names ─────┐ ┃
┃ │ Hint: 0x0123 │ ┃
┃ │ "CreateFileW\0" │ ┃
┃ │ Hint: 0x0456 │ ┃
┃ │ "ReadFile\0" │ ┃
┃ └───────────────────────┘ ┃
┃ ┃
┃ ┌─ Import Addr Table ──┐ ┃
┃ │ (FirstThunk / IAT) │ ┃
┃ │ │ ┃
┃ │ Before load: │ ┃
┃ │ Copy of ILT │ ┃
┃ │ │ ┃
┃ │ After load: │ ┃
┃ │ 7FF8A2B41000 │ ┃
┃ │ 7FF8A2B41050 │ ┃
┃ │ 7FF8A2B410A0 │ ┃
┃ │ (actual addresses) │ ┃
┃ └───────────────────────┘ ┃
┃ ┃
┃ String literals ┃
┃ Const data ┃
┃ Virtual tables ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
0x00005400 4,096 bytes ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
(0x1000) ┃ .data SECTION ┃
┃ (Initialized Data) ┃
┃ ┃
┃ Global variables ┃
┃ Static data ┃
┃ Writable constants ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
0x00006400 512 bytes ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
(0x200) ┃ .pdata SECTION ┃
┃ (Exception Info - x64) ┃
┃ ┃
┃ Runtime function entries: ┃
┃ BeginAddress ┃
┃ EndAddress ┃
┃ UnwindInfoAddress ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
0x00006600 4,096 bytes ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
(0x1000) ┃ .rsrc SECTION ┃
┃ (Resources) ┃
┃ ┃
┃ Resource Directory Tree: ┃
┃ Type Level ┃
┃ ├─ Icons (Type 3) ┃
┃ ├─ Bitmaps (Type 2) ┃
┃ ├─ Dialogs (Type 5) ┃
┃ └─ Version (Type 16) ┃
┃ ┃
┃ Resource Data: ┃
┃ Icon images ┃
┃ Version strings ┃
┃ Manifest ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
0x00007600 1,280 bytes ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
(0x500) ┃ .reloc SECTION ┃
┃ (Base Relocations) ┃
┃ ┃
┃ Relocation Blocks: ┃
┃ ┃
┃ Block 1: ┃
┃ PageRVA: 0x1000 ┃
┃ BlockSize: 20 ┃
┃ Entries: ┃
┃ Type:10 Offset:0x023 ┃
┃ Type:10 Offset:0x045 ┃
┃ Type:10 Offset:0x089 ┃
┃ ┃
┃ Block 2: ┃
┃ PageRVA: 0x2000 ┃
┃ ... ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
0x00007B00 ??? ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ OVERLAY DATA (Optional) ┃
┃ ┃
┃ Data beyond last section ┃
┃ Not mapped into memory ┃
┃ ┃
┃ May contain: ┃
┃ - Digital signature ┃
┃ - Packer data ┃
┃ - Extra resources ┃
┃ - Steganographic data ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
Memory Layout (RVA and VA)
File → Memory Transformation
┌──────────────────────────────────────────────────────────────────────────┐
│ ON DISK (FILE OFFSETS) │
└──────────────────────────────────────────────────────────────────────────┘
File Offset Component Size Raw Data
───────────────────────────────────────────────────────────────────────────
0x00000000 DOS Header 64 4D 5A 90 00 03 00 ...
0x00000040 DOS Stub 176 0E 1F BA 0E 00 B4 ...
0x000000F0 PE Signature 4 50 45 00 00
0x000000F4 COFF Header 20 64 86 06 00 ...
0x00000108 Optional Header 240 0B 02 0E 00 ...
0x000001F8 Section Headers 240 2E 74 65 78 74 ...
(padding to 0x400)
0x00000400 .text section 12,288 55 8B EC 83 EC 20 ...
0x00003400 .rdata section 8,192 ...
0x00005400 .data section 4,096 ...
0x00006400 .pdata section 512 ...
0x00006600 .rsrc section 4,096 ...
0x00007600 .reloc section 1,280 ...
▼▼▼ WINDOWS LOADER ▼▼▼
┌──────────────────────────────────────────────────────────────────────────┐
│ IN MEMORY (VIRTUAL ADDRESSES) │
│ │
│ ImageBase (x64): 0x0000000140000000 │
│ SizeOfImage: 0x0000000000008000 (32KB) │
└──────────────────────────────────────────────────────────────────────────┘
Virtual Addr Component Size Memory Protection
───────────────────────────────────────────────────────────────────────────
0x0000000140000000 DOS Header 64 PAGE_READONLY
(Base + 0x0000) PE Headers 960 (Headers)
Section Headers
(All headers) 1024 total
─────────────────────────────────────────────────
0x0000000140001000 .text section 11,336 PAGE_EXECUTE_READ
(Base + 0x1000) (VirtualSize) (RX - Code)
RVA: 0x00001000
Rounded to: 16,384
(SectionAlign) (0x4000)
─────────────────────────────────────────────────
0x0000000140004000 .rdata section 6,722 PAGE_READONLY
(Base + 0x4000) Contains: (R - Read-only)
RVA: 0x00004000 - Import tables
- String literals
- Const data
Rounded to: 8,192
(SectionAlign) (0x2000)
─────────────────────────────────────────────────
0x0000000140006000 .data section 1,024 PAGE_READWRITE
(Base + 0x6000) Global variables (RW - Data)
RVA: 0x00006000
Rounded to: 4,096
(SectionAlign) (0x1000)
─────────────────────────────────────────────────
0x0000000140007000 .pdata section 384 PAGE_READONLY
(Base + 0x7000) Exception tables (R - Read-only)
RVA: 0x00007000
Rounded to: 4,096
(SectionAlign) (0x1000)
─────────────────────────────────────────────────
0x0000000140008000 .rsrc section 2,048 PAGE_READONLY
(Base + 0x8000) Resources (R - Resources)
RVA: 0x00008000
Rounded to: 4,096
(SectionAlign) (0x1000)
─────────────────────────────────────────────────
0x0000000140009000 .reloc section 1,152 PAGE_READONLY
(Base + 0x9000) Relocations (R - Can discard)
RVA: 0x00009000
Rounded to: 4,096
(SectionAlign) (0x1000)
───────────────────────────────────────────────────────────────────────────
0x000000014000A000 END OF IMAGE
(Base + SizeOfImage)
KEY CONCEPTS ILLUSTRATED:
┌─────────────────────────────────────────────────────────────────┐
│ FILE OFFSET → RVA → VIRTUAL ADDRESS │
├─────────────────────────────────────────────────────────────────┤
│ │
│ File Offset: Raw position in file (disk) │
│ 0x00000400 = byte 1024 in file │
│ │
│ RVA: Relative Virtual Address │
│ (offset from ImageBase in memory) │
│ 0x00001000 = 4096 bytes from base │
│ │
│ VA: Virtual Address (absolute in process memory) │
│ ImageBase + RVA │
│ 0x140000000 + 0x1000 = 0x140001000 │
│ │
└─────────────────────────────────────────────────────────────────┘
ALIGNMENT DIFFERENCES:
┌─────────────────────────────────────────────────────────────────┐
│ FileAlignment: 0x200 (512 bytes) - Disk efficiency │
│ SectionAlignment: 0x1000 (4096 bytes) - Memory page size │
│ │
│ On Disk: Sections aligned to 512-byte boundaries │
│ In Memory: Sections aligned to 4KB page boundaries │
│ │
│ Example: .text section │
│ File: Offset 0x400, Size 0x3000 (12,288 bytes) │
│ Memory: RVA 0x1000, Size 0x4000 (16,384 bytes) │
│ │
│ Extra 4,096 bytes in memory = zero-filled padding │
└─────────────────────────────────────────────────────────────────┘
Offset Conversion Examples
Converting Between File Offset ↔ RVA ↔ Virtual Address
┌──────────────────────────────────────────────────────────────────────┐
│ CONVERSION FORMULAS │
├──────────────────────────────────────────────────────────────────────┤
│ │
│ RVA → VA: │
│ VA = ImageBase + RVA │
│ │
│ VA → RVA: │
│ RVA = VA - ImageBase │
│ │
│ RVA → File Offset: │
│ 1. Find section containing RVA │
│ 2. FileOffset = PointerToRawData + (RVA - VirtualAddress) │
│ │
│ File Offset → RVA: │
│ 1. Find section containing FileOffset │
│ 2. RVA = VirtualAddress + (FileOffset - PointerToRawData) │
│ │
└──────────────────────────────────────────────────────────────────────┘
EXAMPLE 1: Entry Point Address Conversion
═══════════════════════════════════════════════════════════════════
Given:
AddressOfEntryPoint (RVA): 0x00001000
ImageBase: 0x0000000140000000
Convert RVA to VA:
VA = ImageBase + RVA
= 0x0000000140000000 + 0x00001000
= 0x0000000140001000
Find File Offset:
RVA 0x1000 is in .text section:
VirtualAddress: 0x00001000
PointerToRawData: 0x00000400
FileOffset = PointerToRawData + (RVA - VirtualAddress)
= 0x400 + (0x1000 - 0x1000)
= 0x400
Summary:
Entry point code is located at:
File Offset: 0x00000400 (byte 1024 in file)
RVA: 0x00001000 (4096 bytes from image base)
VA: 0x0000000140001000 (absolute memory address)
EXAMPLE 2: Import Table Conversion
═══════════════════════════════════════════════════════════════════
Given:
Import Table RVA: 0x00004100 (from Data Directory[1])
ImageBase: 0x0000000140000000
Convert RVA to VA:
VA = 0x0000000140000000 + 0x00004100
= 0x0000000140004100
Find File Offset:
RVA 0x4100 is in .rdata section:
VirtualAddress: 0x00004000
PointerToRawData: 0x00003400
FileOffset = 0x3400 + (0x4100 - 0x4000)
= 0x3400 + 0x100
= 0x3500
Summary:
Import table is located at:
File Offset: 0x00003500
RVA: 0x00004100
VA: 0x0000000140004100
EXAMPLE 3: Code Address from Disassembler
═══════════════════════════════════════════════════════════════════
Disassembler shows instruction at VA: 0x0000000140001234
Convert VA to RVA:
RVA = VA - ImageBase
= 0x0000000140001234 - 0x0000000140000000
= 0x00001234
Find File Offset:
RVA 0x1234 is in .text section:
VirtualAddress: 0x00001000
PointerToRawData: 0x00000400
FileOffset = 0x400 + (0x1234 - 0x1000)
= 0x400 + 0x234
= 0x634
Summary:
Instruction bytes are at file offset 0x634
VISUAL CONVERSION EXAMPLE
═══════════════════════════════════════════════════════════════════
Section: .text
VirtualAddress: 0x00001000
VirtualSize: 0x00002C48
PointerToRawData: 0x00000400
SizeOfRawData: 0x00003000
┌────────────────────────────────────────────────────────────────┐
│ ON DISK │
├────────────────────────────────────────────────────────────────┤
│ │
│ File Offset 0x00000400 ─┐ │
│ │ │
│ ├──→ Start of .text │
│ │ │
│ File Offset 0x00001234 ─┤ │
│ │ Instruction bytes │
│ │ (at offset 0xE34 into section) │
│ │ │
│ File Offset 0x000033FF ─┘ End of .text on disk │
│ │
└────────────────────────────────────────────────────────────────┘
▼
LOADED INTO MEMORY
▼
┌────────────────────────────────────────────────────────────────┐
│ IN MEMORY │
├────────────────────────────────────────────────────────────────┤
│ │
│ ImageBase + 0x1000 │
│ = 0x140001000 ─────┐ │
│ │ │
│ ├──→ Start of .text in memory │
│ │ │
│ 0x140001234 ───────┤ Instruction in memory │
│ │ (RVA: 0x1234) │
│ │ (File offset was: 0x634) │
│ │ │
│ ImageBase + 0x4C48 │ End of .text actual data │
│ (VirtualSize end) │ │
│ │ │
│ ImageBase + 0x4FFF ─┘ End of .text memory region │
│ (Aligned to 0x5000) (padding to SectionAlignment) │
│ │
└────────────────────────────────────────────────────────────────┘
CONVERSION FOR 0x140001234:
VA → RVA:
0x140001234 - 0x140000000 = 0x1234
RVA → Section:
0x1234 is in range [0x1000, 0x4C48]
→ .text section
RVA → File Offset:
Section offset = 0x1234 - 0x1000 = 0x234
File offset = 0x400 + 0x234 = 0x634
File Offset → Byte in File:
Read byte at position 1588 (0x634) in file
Interactive Component Map
Complete PE Component Relationship Diagram
┌─────────────────────────────────────┐
│ EXECUTABLE FILE.EXE │
│ (On Disk) │
└──────────────┬──────────────────────┘
│
┌──────────────────┴──────────────────┐
│ │
┌─────────▼────────┐ ┌────────────▼──────────┐
│ DOS HEADER │ │ SECTION DATA │
│ e_lfanew ──────┼──┐ │ │
└──────────────────┘ │ │ .text .rdata .data│
│ │ .pdata .rsrc .reloc │
┌────────────────────┐│ └───────────────────────┘
│ DOS STUB ││ │
│ (optional code) ││ │
└────────────────────┘│ │
│ │
┌────────────────────┐│ │
│ PE SIGNATURE ││ │
│ "PE\0\0" ││ │
└────────────────────┘│ │
│ │
┌─────────────────────▼───────┐ │
│ COFF FILE HEADER │ │
│ - Machine type │ │
│ - NumberOfSections ───────┼─────┐ │
│ - Characteristics │ │ │
└─────────────────────────────┘ │ │
│ │
┌─────────────────────────────────┐ │ │
│ OPTIONAL HEADER │ │ │
│ ┌───────────────────────────┐ │ │ │
│ │ Standard Fields: │ │ │ │
│ │ - Magic (PE32/PE32+) │ │ │ │
│ │ - AddressOfEntryPoint ───┼─┼─┼───────┼──┐
│ │ - ImageBase │ │ │ │ │
│ │ - SectionAlignment │ │ │ │ │
│ │ - FileAlignment │ │ │ │ │
│ │ - SizeOfImage │ │ │ │ │
│ │ - DllCharacteristics │ │ │ │ │
│ └───────────────────────────┘ │ │ │ │
│ ┌───────────────────────────┐ │ │ │ │
│ │ Data Directories [16]: │ │ │ │ │
│ │ [0] Export Table │ │ │ │ │
│ │ [1] Import Table ────────┼─┼─┼───────┼──┼─┐
│ │ [2] Resource Table │ │ │ │ │ │
│ │ [3] Exception Table │ │ │ │ │ │
│ │ [4] Certificate Table │ │ │ │ │ │
│ │ [5] Base Reloc Table ────┼─┼─┼───────┼──┼─┼─┐
│ │ ... │ │ │ │ │ │ │
│ │ [12] IAT ────────────────┼─┼─┼───────┼──┼─┼─┼─┐
│ └───────────────────────────┘ │ │ │ │ │ │ │
└─────────────────────────────────┘ │ │ │ │ │ │
│ │ │ │ │ │
┌─────────────────────────────────┐ │ │ │ │ │ │
│ SECTION HEADERS [N] │◄┘ │ │ │ │ │
│ ┌───────────────────────────┐ │ │ │ │ │ │
│ │ .text Header: │ │ │ │ │ │ │
│ │ Name: ".text" │ │ │ │ │ │ │
│ │ VirtualAddress: 0x1000 ◄─┼─┼─────────┼──┘ │ │ │
│ │ VirtualSize: 0x2C48 │ │ │ │ │ │
│ │ PointerToRawData: 0x400 ─┼─┼─────────┤ │ │ │
│ │ SizeOfRawData: 0x3000 │ │ │ │ │ │
│ │ Characteristics: RX │ │ │ │ │ │
│ └───────────────────────────┘ │ │ │ │ │
│ ┌───────────────────────────┐ │ │ │ │ │
│ │ .rdata Header: │ │ │ │ │ │
│ │ VirtualAddress: 0x4000 │ │ │ │ │ │
│ │ PointerToRawData: 0x3400 ┼─┼─────────┼────┼─┼─┼─┐
│ │ Characteristics: R │ │ │ │ │ │ │
│ └───────────────────────────┘ │ │ │ │ │ │
│ ┌───────────────────────────┐ │ │ │ │ │ │
│ │ .data, .pdata, .rsrc, │ │ │ │ │ │ │
│ │ .reloc Headers... │ │ │ │ │ │ │
│ └───────────────────────────┘ │ │ │ │ │ │
└─────────────────────────────────┘ │ │ │ │ │
│ │ │ │ │
┌───────────────────────────────────────────┘ │ │ │ │
│ │ │ │ │
▼ │ │ │ │
┌─────────────────────────────────────┐ │ │ │ │
│ .text SECTION (Code) │ │ │ │ │
│ ┌───────────────────────────────┐ │ │ │ │ │
│ │ Machine Instructions: │ │ │ │ │ │
│ │ │ │ │ │ │ │
│ │ 0x400: 55 8B EC push rbp│ │ │ │ │ │
│ │ 0x403: 48 89 E5 mov rbp │ │ │ │ │ │
│ │ ... │ │ │ │ │ │
│ │ │ │ │ │ │ │
│ │ Function calls to IAT: ───────┼──┼───────────────┼─┼─┼─┘
│ │ CALL [0x4300] ; GetProcAddr│ │ │ │ │
│ │ CALL [0x4308] ; LoadLibrary│ │ │ │ │
│ └───────────────────────────────┘ │ │ │ │
└─────────────────────────────────────┘ │ │ │
│ │ │
┌─────────────────────────────────────────────────────┘ │ │
│ │ │
▼ │ │
┌──────────────────────────────────────────┐ │ │
│ .rdata SECTION (Read-only Data) │ │ │
│ ┌────────────────────────────────────┐ │ │ │
│ │ IMPORT DIRECTORY TABLE: │ │◄────────────────┘ │
│ │ ┌──────────────────────────────┐ │ │ │
│ │ │ Descriptor: kernel32.dll │ │ │ │
│ │ │ OriginalFirstThunk: 0x4100 │ │ │ │
│ │ │ Name: 0x4200 ───────────┐ │ │ │ │
│ │ │ FirstThunk: 0x4300 │ │ │ │ │
│ │ └──────────────────────────│──┘ │ │ │
│ │ │ │ │ │
│ │ DLL NAMES: │ │ │ │
│ │ 0x4200: "kernel32.dll\0" ◄─┘ │ │ │
│ │ 0x4210: "user32.dll\0" │ │ │
│ │ │ │ │
│ │ IMPORT LOOKUP TABLE (ILT): │ │ │
│ │ 0x4100: RVA to hint/name │ │ │
│ │ "GetProcAddress" │ │ │
│ │ 0x4108: RVA to hint/name │ │ │
│ │ "LoadLibraryA" │ │ │
│ │ 0x4110: NULL │ │ │
│ │ │ │ │
│ │ IMPORT ADDRESS TABLE (IAT): ──────┼──┼───────────────────┘
│ │ 0x4300: Initially: RVA to name │ │
│ │ After Load: 7FF8A2B41000 │ │ ← Windows fills
│ │ 0x4308: Initially: RVA to name │ │ with actual
│ │ After Load: 7FF8A2B41050 │ │ addresses
│ │ │ │
│ │ String literals, const data... │ │
│ └────────────────────────────────────┘ │
└──────────────────────────────────────────┘
┌──────────────────────────────────────────┐
│ .data SECTION (Writable Data) │
│ - Global variables │
│ - Static data │
└──────────────────────────────────────────┘
┌──────────────────────────────────────────┐
│ .reloc SECTION (Relocations) │◄──────────────┐
│ ┌────────────────────────────────────┐ │ │
│ │ Base Relocation Blocks: │ │ │
│ │ │ │ │
│ │ Block for page 0x1000: │ │ │
│ │ PageRVA: 0x1000 │ │ │
│ │ BlockSize: 20 bytes │ │ │
│ │ Entries: │ │ │
│ │ Type: 10 (DIR64) Offset: 023 │ │ │
│ │ Type: 10 (DIR64) Offset: 045 │ │ │
│ │ ... │ │ │
│ │ │ │ │
│ │ Used when ImageBase changes ───────┼──┤ │
│ │ (ASLR randomization) │ │ │
│ └────────────────────────────────────┘ │ │
└──────────────────────────────────────────┘ │
│
│
MEMORY LAYOUT │
═══════════ │
│
0x140000000 ┌──────────────────────┐ │
(ImageBase) │ Headers (all) │ │
├──────────────────────┤ │
+ 0x1000 │ .text (RX) ◄───────┼──────────────┤
│ Executable code │ │
├──────────────────────┤ │
+ 0x4000 │ .rdata (R) │ │
│ Imports, strings │ │
├──────────────────────┤ │
+ 0x6000 │ .data (RW) │ │
│ Global data │ │
├──────────────────────┤ │
+ 0x7000 │ .pdata (R) │ │
├──────────────────────┤ │
+ 0x8000 │ .rsrc (R) │ │
├──────────────────────┤ │
+ 0x9000 │ .reloc (R) │ │
└──────────────────────┘ │
│
WINDOWS LOADER FIXES ADDRESSES ───────────┘
USING RELOCATION TABLE
Key Takeaways
Understanding PE Structure Flow
- DOS Header → Points to PE header via
e_lfanew - PE Signature → Validates file as PE format
- COFF Header → Basic file information (architecture, sections)
- Optional Header → Critical loading info (entry point, image base, data directories)
- Data Directories → Pointers to import/export/resource tables
- Section Headers → Map file offsets to memory addresses
- Section Data → Actual code, data, resources
Address Translation
- File Offset = Position in file on disk
- RVA = Relative Virtual Address (offset from ImageBase)
- VA = Virtual Address (absolute address in memory)
Memory vs Disk
- Disk: Aligned to FileAlignment (512 bytes)
- Memory: Aligned to SectionAlignment (4096 bytes)
- Difference: Zero-padding in memory
Import Resolution
- Import Directory lists DLLs and functions
- Windows loads DLLs
- Windows resolves function addresses
- Windows writes addresses to IAT
- Code calls functions via IAT
This visual guide provides a complete map of how PE components interact and transform from file to memory!
메타데이터
- post_id
- 1f97cc48de4d
- slug
- pe-structure-complete-visual-guide-1f97cc48de4d
- url
- https://medium.com/@trmz/pe-structure-complete-visual-guide-1f97cc48de4d
- canonical_url
- https://medium.com/@trmz/pe-structure-complete-visual-guide-1f97cc48de4d
- author_url
- https://medium.com/@trmz
- status
- ok
- fetched_at
- 2026-08-09 03:06:14