The Substrate Gap
What the loader reads is not what the tools parse. The gap between them is attack surface.
I built a tool that asks a simple question: which bytes does Windows actually need to execute this binary? By tracing file reads during image loading, I recorded every offset the Windows loader touched.
The answer is uncomfortable.
For cmd.exe, a 340KB system binary, the Windows loader touches about 99% of the file. But security tools also parse that same 99%. The overlap is nearly total.
The interesting part is the other 1%.
3,752 bytes that analysis tools read, parse, validate, and make security decisions about. Bytes the loader never touches. They have no effect on execution. They exist only for parsers.
The execution substrate is not the analysis substrate.
The Taxonomy
Every byte in a binary falls into one of four categories:
LOADER_CRITICAL: Bytes the loader requires for execution but which are not typically interpreted semantically by analysis tools. Rare in well-formed binaries. An example: certain section alignment bytes that the loader needs for memory mapping but that most analysis tools skip during parsing.
PARSER_BAIT: Bytes that tools parse but the loader ignores. This is attack surface. Vulnerabilities here affect analysis, not execution.
UNUSED_SUBSTRATE: Bytes neither loader nor tools read. Free real estate for payload staging, data hiding, or polyglot construction.
HYBRID: Bytes both loader and tools access. Most of a typical PE falls here.
The goal isn't to find dead space. It's to find the differential. Where tools and loaders disagree about what matters.
What Lives in PARSER_BAIT
In a typical PE, the parser-bait regions include:
The DOS header fields after the MZ signature. The loader consults exactly two things: the magic bytes at offset 0, and e_lfanew at offset 0x3C. Everything else? e_cblp, e_cp, e_crlc, the entire DOS stub. Ignored.
But analysis tools read all of it. AV engines scan the DOS stub for shellcode. Disassemblers parse every header field. Forensic tools extract timestamps and linker versions. They're trying to reconstruct intent: who compiled this, when, with what. The loader only cares about mechanics.
The Rich header. Microsoft's undocumented build metadata, encoded with a simple XOR. The loader doesn't know it exists. But security tools decode and analyze it for attribution.
The TimeDateStamp in the COFF header. PE-bear displays it. IDA references it. VirusTotal indexes it. The Windows loader? Ignores it completely.
These aren't obscure edge cases. They're standard PE structures that every analysis tool processes and every loader skips.
The Proof
I generated a mutant of cmd.exe with the DOS header fields overwritten. 56 bytes the loader never reads, filled with 0xFF.
Original hash: 64AFC6DB3AAD...
Mutant hash: 44C6577CBA3F...
Different binaries. Different signatures. Different hashes.
I ran the mutant:
.\test_cmd.exe /c echo "mutant works"
"mutant works"
Identical execution. The loader didn't notice because it never looked at those bytes.
I uploaded both to VirusTotal. Original: 0/71 detections. Mutant: 0/71 detections. Both identified as "Cmd.Exe", despite having completely different hashes. The mutations were invisible to signature-based detection across every engine.
A caveat: some EDRs use header anomalies as heuristics. Corrupted DOS headers or missing Rich headers might trigger scrutiny even if the code is clean. The mutations are invisible to signature matching, not necessarily to behavioral analysis.
Similarly, signed binaries constrain the mutation surface. The digital signature covers most of the file, so changes to parser-bait regions will invalidate it. Unsigned binaries have more room to play.
It isn't obfuscation or packing. The executable code and control flow are unchanged. Only bytes the loader never reads are modified.
The measurements reflect documented Windows loader behavior and represent a lower bound on execution-critical bytes.
You can generate infinite hash-unique variants of any PE that all execute identically.
Why This Matters
Hash-based detection assumes the file is the program. It isn't. The loader's interpretation is the program. Everything else is metadata, convention, or noise.
If you're a defender: your tools are parsing bytes that don't affect execution. Vulnerabilities in those parsers are exploitable without changing behavior. An attacker can crash your AV by corrupting fields it reads but the OS ignores.
If you're a researcher: this is a systematic methodology for finding parser bugs. Identify PARSER_BAIT regions, fuzz them specifically, watch tools fail while the binary runs fine.
If you're a red teamer: 1% of cmd.exe is free camouflage. Mutate it. Generate variants. Every hash is unique. Every execution is identical.
The Broader Pattern
This is the same insight as Veriduct, approached from the opposite direction. Veriduct demonstrated that execution can survive total format destruction—relocations resolved manually, headers discarded, the PE reduced to raw intent.
Veriduct asks: what if we destroy the format entirely? Can you still reconstruct execution?
substrate_differ asks: which parts of the format actually matter for execution?
Both arrive at the same conclusion: the boundary between "format" and "program" is porous. The spec describes a file. The loader interprets a subset. The gap between them is where assumptions break down.
Security tools live in that gap. They parse what the spec says should be there. They trust fields because the documentation describes them. But the loader has its own opinion, and it's the only opinion that matters for execution.
The interpreter defines meaning. The format is just a suggestion.