Lesson 1 of 9 · 20m
What the Compiler Actually Throws Away
A binary is the fossil record of a program — mechanism survives, intent is erased. Learn which artifacts are still legible before you try to read them.
Every binary you open is the fossil record of a program. The compiler took source — intent, names, structure — and kept only the mechanism: instructions, data layouts, and whatever strings and symbols happened to survive. New reversers think the job is reading assembly. It isn't. The job is reconstructing intent from mechanism, and knowing exactly which parts of the fossil are still legible.
What survives compilation
- Instructions and control flow — the mechanism, faithfully preserved, though rearranged and optimized past recognition of the source text.
- Constants and string literals — format strings, error messages, magic numbers, crypto tables. Often the most legible artifact in the whole file.
- Imported function names — calls into libc or WinAPI keep their names because the dynamic linker needs them at load time.
- Sometimes, symbols — function names in
.symtab, if nobody ranstrip. Check before assuming the worst.
What gets erased
- Variable names, type declarations, comments — gone entirely.
- Function boundaries become conventions, not facts: a "function" is just a call target with a prologue-like shape.
if,while,for, andswitchall collapse into the same primitive — compare, set flags, conditional jump.- Data structures dissolve into pointer arithmetic.
user->namebecomesmov rax, [rdi+0x18]and nothing tells you that offset 0x18 was calledname.
The ELF, at rest
$ file crackme
crackme: ELF 64-bit LSB pie executable, x86-64, dynamically linked, stripped
$ readelf -S crackme | grep -E "text|rodata|data"
[13] .text PROGBITS 0000000000001060 001060 0001a3
[15] .rodata PROGBITS 0000000000002000 002000 000048
[23] .data PROGBITS 0000000000004010 003010 000010.text is code, .rodata is constants and strings, .data is initialized globals, .bss is zero-initialized globals that take no file space. A stripped, PIE, dynamically-linked binary is the default posture — assume it until proven otherwise.
Field notes
- Run
fileandstringsbefore anything else — thirty seconds of triage tells you architecture, packing, and whether symbols exist. - Unstripped symbols are a gift, not the norm.
nm -Con a C++ binary even demangles the names for you. - A
-gdebug build embeds DWARF: full line numbers, types, struct layouts. If you find one, the job just changed category — load it into the debugger, not just the disassembler.