4.2 KiB
PE Mutation Engine (tests/loader/pe_mutator.py)
Location: tests/loader/pe_mutator.py
The PE mutation engine applies targeted structural modifications to valid PE files to produce variants that stress-test the reflective loader's parser and loading pipeline. Every mutation is designed to exercise a specific safety boundary or parsing assumption.
Mutation Categories
Mutations are divided into two strict categories:
Benign Edge-Cases
These produce PE files that are unusual or hyper-optimized but structurally valid — Windows can still load and run them. The reflective loader must adapt and succeed.
| Mutation | Description | What It Tests |
|---|---|---|
unaligned_sections |
Forces SectionAlignment and FileAlignment to 0x200 |
Loaders that hardcode 0x1000 page alignment assumptions |
strip_relocs_from_exe |
Strips the .reloc directory and sets IMAGE_FILE_RELOCS_STRIPPED |
Loaders that aggressively demand relocations for EXEs |
garbage_dos_stub |
Overwrites the DOS stub (bytes 2–e_lfanew) with deterministic garbage |
Parsers that read linearly through the DOS stub instead of seeking via e_lfanew |
append_overlay |
Appends 4 KB of junk data after the last section | Loaders that map beyond declared section boundaries |
null_section_names |
Zeroes out every section name string | Loaders that match section names unsafely or log via unchecked printf |
Breaking Stressors
These produce structurally corrupted PE files. The parser must detect the violation and reject the input gracefully — never crash.
| Mutation | Description | What It Tests |
|---|---|---|
corrupt_reloc_block_size |
Sets first reloc block's SizeOfBlock to 0xFFFFFFFF |
Unbounded while loops in relocation parsing |
massive_size_of_headers |
Sets SizeOfHeaders to 0xFFFFFFFF |
Unchecked memcpy using header-sourced sizes |
section_truncated_raw_data |
Inflates a section's SizeOfRawData beyond the physical file |
Blind section mapping without file bounds checks |
section_integer_overflow |
Sets VirtualSize and SizeOfRawData to 0xFFFFFFFF |
Integer overflow in allocation arithmetic (VA + ALIGN(VirtualSize)) |
section_overlap_corruption |
Collapses all section file offsets to zero | File alignment normalization bugs |
corrupt_pe_signature |
Replaces PE\0\0 with 0xDEADBEEF |
NT signature validation |
invalid_e_lfanew |
Points e_lfanew 1 MB past EOF |
Offset bounds checking before NT headers access |
zero_size_of_image |
Sets SizeOfImage to 0 |
Allocation size validation |
corrupt_import_rva |
Points import directory to 0xDEAD0000 |
RVA bounds checking before import traversal |
corrupt_export_rva |
Points export directory to 0xDEAD0000 |
RVA bounds checking before export parsing |
huge_sections_count |
Sets NumberOfSections to 0xFFFF |
Section table overflow protection |
unterminated_imports |
Overwrites the null-terminating import descriptor with 0xFF |
Import loop termination without boundary checks |
massive_export_count |
Sets NumberOfFunctions and NumberOfNames to 0xFFFFFFFF |
Export iteration bounds checking |
oob_entry_point |
Points AddressOfEntryPoint past SizeOfImage |
Entry point RVA validation before execution transfer |
API
Mutation Dataclass
| Field | Type | Description |
|---|---|---|
name |
str |
Short string identifier (used in output filenames) |
description |
str |
Human-readable label |
apply |
Callable |
The mutation function ((src, dst) -> None) |
expect_loadable |
bool |
True = loader must succeed; False = loader must reject gracefully |
applies_to |
str |
"both", "exe", or "dll" |
mutate_pe(src_path, mutation, output_dir) -> str
Applies the specified mutation to the source PE file and writes the mutated output to output_dir. Returns the path to the generated file. Raises MutationError on failure.
Dependency
Requires the pefile Python package for structured PE modifications:
pip install pefile
Raw byte-level mutations (garbage_dos_stub, corrupt_pe_signature, invalid_e_lfanew, huge_sections_count) operate directly on the byte buffer without pefile.