A Comprehensive Technical Reference from Object Files to Windows Process Execution
Introduction: Why the PE Format Matters
Chapter 1: Origins of Executable Formats
- Early Unix Executables and the a.out Lineage
- The Rise of COFF at AT&T and Its Spread to IBM and DEC
- Microsoft’s Adoption of COFF and the DOS/Windows Transition
- From COFF to PE: Design Goals and Architectural Requirements
- The PE Family Tree: Object Files, Images, DLLs and Drivers
Chapter 2: The Compilation and Linking Lifecycle
- From Source to COFF Object: Assembly Generation and Object Creation
- The COFF Object File Structure in Brief
- Symbol Tables and String Tables in Object Files
- Static Linking: Combining Objects into an Image
- Section Merging, Relocation and Address Assignment
- The Linker’s View of PE: What Gets Built and Why
Chapter 3: The DOS Header and Stub
- The MZ Signature: History and Purpose
- DOS Header Fields and Their Meanings
- The DOS Stub: Compatibility Code and Execution
- The e_lfanew Pointer: Bridging DOS and PE
- DOS Header in Practice: Real Examples and Variations
- Edge Cases: When the DOS Header is Absent or Minimal
Chapter 4: The COFF File Header
- The PE Signature and COFF File Header Layout
- Machine Type and Architecture Identification
- Time Date Stamp, Symbol Table and Section Count
- Characteristics Flags and Their Combinations
- COFF File Header in Executables versus DLLs versus Drivers
- Parsing the COFF File Header Safely in Code
Chapter 5: The Optional Header Overview
- Why “Optional” and Why Mandatory for Images
- Standard Fields: Magic, Linker Version and Code/Data Sizes
- The Subsystem Field and Application Types
- DllCharacteristics and Modern Security Flags
- Address Layout: ImageBase, Entry Point and Image Size
- Differences Between PE32 and PE32+ Optional Headers
Chapter 6: Section Headers and Section Layout
- Section Header Structure and Required Fields
- Section Names: Standard, Extended and Custom
- Virtual Size versus Raw Size and the Meaning of Each
- Virtual Address and Pointer to Raw Data
- Section Characteristics: Code, Data, Read, Write, Execute, etc.
- Alignment Constraints: File Alignment versus Section Alignment
Chapter 7: RVA to File Offset and Address Translation
- Understanding RVA, VA and File Offset Distinctly
- The Section Table as a Translation Map
- RVA to File Offset: The Core Algorithm
- File Offset to RVA: Reverse Translation and Ambiguities
- VA to RVA in the Loaded Process Context
- Edge Cases: Gaps, Overlaps and Malformed Sections
Chapter 8: The Data Directories
- Data Directory Structure and Its Position in the Optional Header
- The Export Table Directory
- The Import Table Directory
- The Resource Directory and Its Hierarchy
- The Exception Directory and Unwind Information
- The Certificate Table Directory
- The Base Relocation Table Directory
- The Debug Directory and Its Contents
- The TLS Table Directory
- The Load Configuration Table Directory
- The Bound Import and IAT Directories
- The Delay Import Descriptor Directory
- The CLR Runtime Header Directory
- The Remaining Directories
Chapter 9: Imports and Export Tables
- The Export Directory Table: EAT Structure and Usage
- Name Table, Ordinal Table and Address Table Interplay
- The Import Descriptor and Its Fields
- Import Lookup Table and Import Address Table
- Bound Imports and Delay-Load Imports
- Imports in DLLs versus EXEs versus Drivers
Chapter 10: Relocations and Base Relocation Tables
- Object File Relocations versus Image Relocations
- The Base Relocation Block Structure
- Relocation Types: High, Low, HighLow and Architecture-Specific Variants
- When and How Relocations Are Applied by the Loader
- ASLR and the Relocation Table’s Role
- Executables Without Relocations: When and Why This Happens
Chapter 11: Resources and the Resource Directory
- Resource Directory Overview: Root, Name and Entry Levels
- Resource Directory Entries and ID-Based versus Name-Based Resources
- Common Resource Types and Their Data Formats
- Icons, Dialogs, Menus and String Tables
- Accessing Resources from Code
- Resource Analysis for Malware and Anti-Forensics
Chapter 12: Debug Information and CodeView
- The Debug Directory and Debug Directory Entry Structure
- CodeView Format Identifiers: RSDS and NB10
- PDB File References and Debug Information Storage
- Other Debug Formats: CV, FPO and Misc
- How Debuggers Locate and Load Debug Symbols
- Stripped Binaries and Forensic Implications
Chapter 13: Exception Handling and Unwind Information
- Exception Directory in PE32 versus PE32+
- x86 Exception Handling: SEH and SEH Chains
- x64 Unwind Information Structure and Unwind Codes
- Guard Sections and CFG Exception Support
- Exception Handling in Managed versus Native Code
- Reading and Interpreting Exception Metadata
Chapter 14: Thread Local Storage
- TLS Callbacks and Their Execution Order
- TLS Directory Structure and Address Fields
- TLS in DLLs versus Main Executables
- TLS Initialization in the Loader
- Practical TLS Usage Patterns
- TLS in Malware and Evasion Techniques
Chapter 15: Load Configuration and Advanced Security
- Load Configuration Directory Structure and Versioning
- Control Flow Guard Metadata and Function Table
- Security Cookie and Stack Buffer Overrun Protection
- Dynamic Base, High Entropy ASLR and Terminal Server Awareness
- Guard Flags and Load Time CFG
Chapter 16: Digital Signatures and Authenticode
- The Certificate Table Data Directory
- PKCS#7 and Authenticode Signature Structure
- Signature Verification in the Windows Loader
- Catalog Files and Driver Signing
- Tampering Detection and Signature Stripping
- Inspecting and Validating Signatures Programmatically
Chapter 17: Manifests and Side-by-Side Assemblies
- The Role of Manifests in Versioning and Isolation
- Embedded Manifests as RT_MANIFEST Resources
- Manifest XML Structure and Key Elements
- Side-by-Side Assembly Loading
- Minimum Version Required and Activation Contexts
- Manifests in Modern Windows and UWP
Chapter 18: CLR Headers and .NET Assemblies
- PE as a Container for .NET Assemblies
- The CLR Header Structure and Runtime Version
- Metadata Directories and the Common Language Runtime
- Native versus Managed versus Mixed-Mode Assemblies
- Entry Point Differences: _CorExeMain versus Native Entry
- Inspecting CLR Headers and .NET Metadata
Chapter 19: The Windows Loader: Image Loading Internals
- The Loader’s View of a PE File
- NtCreateSection and NtMapViewOfSection
- Image Validation and Header Verification
- Import Resolution and Dependency Loading
- Base Relocation Application During Load
- The Initialization Sequence: TLS, DllMain and Entry Point
Chapter 20: Loader Bookkeeping and Process Execution
- The PEB and PEB_LDR_DATA
- LDR_DATA_TABLE_ENTRY Structure and Module Links
- Module Search Paths and DLL Search Order
- Loading Drivers versus User-Mode Images
- The Loader Lock and Synchronization
- Observing Loader State with Debugging Tools
Chapter 21: Kernel-Mode PE: Drivers and the Kernel Loader
- Driver PE Files: Format Differences and Requirements
- Kernel-Mode vs User-Mode Loading Constraints
- Driver Signing and Protected Process Light
- Kernel-Mode Base Relocation and ASLR
- Driver Entry Points and Initialization Routines
- Kernel-Mode Debugging of PE-Loaded Drivers
Chapter 22: Building a PE Parser: Foundation and Core Structures
- Project Design and Architecture
- Safe Binary File Reading in C++
- Parsing the DOS Header and Locating the PE Signature
- Parsing the COFF File Header with Validation
- Parsing the Optional Header for PE32 and PE32+
- Parsing Section Headers and Building a Section Map
Chapter 23: Building a PE Parser: RVA Resolution and Data Directories
- Implementing Safe RVA to File Offset Translation
- Implementing File Offset to RVA Translation
- Parsing and Validating Data Directories
- Safe Bounds Checking and Integer Overflow Protection
- Error Handling and Reporting for Malformed Binaries
- Testing Against Real Executables
Chapter 24: Building a PE Parser: Imports, Exports and Relocations
- Parsing Export Directories and Symbol Resolution
- Parsing Import Descriptors and Building an Import Map
- Handling Bound Imports and Delay-Load Imports
- Parsing Base Relocation Blocks and Entry Types
- Generating Human-Readable Import and Export Lists
- Detecting Anomalies in Import and Export Tables
Chapter 25: Building a PE Parser: Resources, Debug and Security Features
- Traversing the Resource Directory Hierarchy
- Extracting and Categorizing Resource Data
- Parsing Debug Directories and CodeView Information
- Inspecting TLS Callbacks and Load Configuration
- Validating Digital Signatures and Authenticode
- Generating a Complete Analysis Report
Chapter 26: Security Implications and Adversarial Analysis
- PE Parser Vulnerabilities and Implementation Pitfalls
- Malformed and Crafted Binaries for Evasion
- Overlapping Sections and Invalid Layouts
- Packed Executables and Their Detection
- File-Format Ambiguity and Polymorphic Techniques
- Defensive Binary Inspection Best Practices
Chapter 27: Cross-Platform, Cross-Compiler and Evolutionary Perspectives
- MSVC versus Clang/LLVM PE Generation Differences
- Architecture-Specific Variations: x86, x64, ARM, ARM64
- Cross-Compilation and Toolchain Interoperability
- PE/COFF versus ELF: Structural and Philosophical Differences
- Historical Evolution: Windows NT Through Windows 11
- Future Directions and Format Extensions
Chapter 28: Conclusion
- The PE/COFF Format as a Bridge Between Compilation and Execution
- Key Architectural Insights and Design Patterns
- What Makes a Robust PE Implementation
- The Living Format: Ongoing Evolution
- Further Reading and Investigation Paths