$ cat recompilation-vs-decompilation.md
Recompilation vs. decompilation: what they are and how they differ
When you start digging into how compiled software actually works, two terms show up constantly: decompilation and recompilation. They sound almost the same, and people mix them up all the time — but they solve very different problems. Here’s how I keep them apart.
I write this as a learner: I study how software is built and taken apart in a safe home lab, on things I’m allowed to touch (my own builds, open preservation projects, CTF challenges). The goal isn’t to break things — it’s to understand systems deeply enough to build and defend them better.
First: what compilation throws away
A compiler takes human-readable source code and turns it into machine code — the raw instructions a CPU executes.
int add(int a, int b) {
return a + b; // readable, named, commented
}
After compilation you’re left with bytes like 55 48 89 e5 …. The variable
names, comments, types and structure are gone. The program still behaves the
same, but it’s no longer meant for humans to read. Both techniques below are
about dealing with that gap — from opposite directions.
Decompilation — making a binary readable again
Decompilation goes backwards: it takes the machine code and reconstructs a higher-level, human-readable approximation of it — usually something that looks like C.
Tools like Ghidra, IDA or Binary Ninja produce “pseudo-code” from a binary:
// what a decompiler might recover from the bytes above
int FUN_00401126(int param_1, int param_2) {
return param_2 + param_1;
}
Notice what’s different: the function and parameter names are guessed
(FUN_…, param_1), types are inferred, and comments are gone forever. A
decompiler gives you something readable, not the original source. The point
is understanding.
What it’s good for: understanding closed-source software, analysing malware, security research (finding and then fixing weaknesses), checking what a program really does, interoperability, and plain learning.
Recompilation — making a binary run again
Recompilation is about producing something runnable, not just readable. In practice the word is used in two different ways:
1. “Matching” decompilation projects
Here people decompile a program and then hand-write source code that, when compiled, produces a byte-for-byte identical binary. If your rebuilt binary matches the original exactly, you’ve proven you understood it correctly.
This is how a lot of game and software preservation works: the community reconstructs source for an old title so it can be studied, fixed, and ported to new platforms — legally, from scratch.
2. Static recompilation
This takes a binary built for one CPU or platform and automatically translates it into code that runs natively somewhere else — for example turning an old console game into a native PC program.
It’s easy to confuse with emulation, so the key difference:
| How it runs | When the translation happens | |
|---|---|---|
| Emulation | Interprets the original instructions at runtime | Live, every time |
| Static recompilation | Produces a new native program ahead of time | Once, up front |
An emulator pretends to be the original machine. A static recompiler rewrites the program into a new one that no longer needs that machine at all.
The one-line difference
The simplest way to remember it:
- Decompilation → turn a binary into something you can read and understand.
- Recompilation → turn a binary into something that runs again (either as matching source, or as a native port).
One is about comprehension, the other about execution. In reverse engineering you often use both: decompile to understand how something works, then — where it’s legal and legitimate — recompile to preserve, port, or verify that understanding.
A note on staying on the right side of it
These techniques are powerful and completely legitimate for the right targets: your own software, intentionally vulnerable practice binaries, CTFs, and open preservation projects. They’re not an excuse to bypass protections on software you don’t have the rights to. For me the whole exercise is defensive — the more precisely you understand how software is built and taken apart, the better you can secure it.