Security
Reverse engineering a file format with no documentation, patiently
Without a spec, the file itself is the spec. The process is slower and more methodical than it sounds from the outside.
Last updated September 17, 2026
When a file format has no public specification — an old proprietary format, an internal tool's save file, a device's undocumented config format — the file itself is the only specification that exists. Reverse engineering it is less about a clever insight and more about a slow, methodical process of forming a hypothesis, testing it, and being willing to be wrong.
Start small, and start with a hex editor
The first useful move isn't analyzing a large, complex real-world file — it's generating or finding the smallest, simplest possible file the format supports, and looking at it byte by byte in a hex editor. A minimal file has minimal structure, which is far easier to reason about than a production file full of real data obscuring the underlying layout. If the tool that produces the format lets you create an empty or near-empty file, that's the first file to look at, before anything more complex.
Finding the structure
Most binary formats share recognizable patterns once you know to look for them: a magic number at the very start of the file (a fixed byte sequence that identifies the format, often visible as ASCII text like PNG or %PDF if you're lucky), fixed-size header fields at predictable offsets, and length-prefixed sections, where a field near the start of a chunk holds a number that tells you exactly how many bytes that chunk occupies. Spotting a length-prefixed section is one of the more satisfying discoveries in this process — a 2 or 4-byte integer that, when interpreted as a number, exactly matches the byte count of the data that follows it. That's rarely a coincidence.
Differential analysis: change one thing, diff the output
The single most productive technique isn't staring harder at one file — it's generating two files that differ in exactly one known way (through whatever tool produces the format, changing one setting or one value) and diffing them byte by byte. If changing a color setting from red to blue changes exactly four bytes at the same offset in both files, those four bytes are very likely the color field, and now there's a testable hypothesis: construct a new file with those four bytes set to a different value and see whether the color changes as predicted when the file is opened again.
This loop — hypothesis, controlled change, diff, verify — is slower than it sounds and it's also the part that actually works, because it replaces guessing with falsifiable predictions. A hypothesis that survives several rounds of "change X, confirm Y follows" is a hypothesis worth trusting; one that gets contradicted on the first test just saved you from building on a wrong assumption.
The parser is the actual proof
Understanding a format well enough to describe it isn't the same as understanding it well enough to parse it programmatically — writing an actual parser, even a partial one that only handles the fields understood so far, is what surfaces the parts of the mental model that were wrong. A field that seemed well understood in isolation often turns out to have an edge case only visible once code has to handle every file thrown at it, not just the one well-behaved sample that was being manually inspected. The parser doesn't just document the reverse-engineering work — writing it is part of how the format actually gets understood, not something that happens only after understanding is complete.
Tags
Related posts