Skip to content

Static Analysis

Static analysis examines a binary without running it: you disassemble and decompile the code to read its logic, inspect the strings, imports, structure, and data. It’s the basis of reversing because it gives you the full program map safely (you don’t run malware) and reproducibly. The star tool is the decompiler, which reconstructs readable pseudo-C from machine code.

# general binary info
file / rabin2 -I architecture, format, stripped, protections
checksec mitigations (ELF)
# readable content
strings messages, paths, URLs, keys, hints
# symbols and imports
nm / readelf -s functions (if not stripped)
objdump -T / rabin2 -i imports (which library functions it uses -> behavior hints)
# disassemble/decompile
Ghidra / IDA / r2 the code in assembly + pseudo-C

Imports are very revealing: if a binary imports socket/connect, it does networking; CreateFile/RegSetValue, touches files/registry; VirtualAlloc/WriteProcessMemory, probably injects code (malware).

1. Import the binary -> auto-analysis
2. Symbol Tree / Functions -> locate main (or entry)
3. Decompiler window -> read each function's pseudo-C
4. rename variables/functions as you understand (key to not getting lost)
5. follow cross-references (xrefs): who calls what, who uses a variable/string
6. annotate and reconstruct the logic until you answer the question (how does it validate? what does it do?)

The decompiler doesn’t give perfect code, but understandable code: renaming and commenting as you go is what turns a confusing dump into clear logic.

# cross-references (xrefs): locate where a string/function is used
# -> find the validation function by searching xrefs to the "Wrong password!" message
# follow the chain from an interesting string to the logic that uses it
# identify known algorithms (crypto constants: AES S-box, MD5, etc.)
# -> tools like FindCrypt / signsrch recognize cryptographic constants
# recognize structures/classes (C++), vtables
# diff binaries (bindiff) to find what changed between versions (patches -> 1-day)
# obfuscated code: control flow flattening, encrypted strings, packing
# -> the pseudo-C is unreadable; combine with dynamic (rev-dynamic)
# packers: the executable is compressed/encrypted; the real code exists only at runtime
# -> unpack (dynamic) then statically analyze the dump
# stripped binaries: no function names -> more reconstruction work

Static analysis is safe because you don’t run the code — ideal as a first step with malware. Still, opening the file in tools inside an isolated VM is good practice. For what’s encrypted/packed, you’ll need dynamic analysis, and there isolation must be maximized (see malware).

- symbol stripping, code and string obfuscation (runtime encryption)
- commercial packers/protectors
- integrity checks
# all this raises the cost of static analysis, doesn't prevent it (see rev-antidebug)
  • file/checksec/strings/imports as first mapping
  • Locate main/entry and relevant logic in Ghidra
  • Read the pseudo-C and rename variables/functions
  • Use xrefs to follow strings/functions to the logic
  • Recognize algorithms/constants (crypto: FindCrypt)
  • Identify obfuscation/packing (switch to dynamic?)
  • Reconstruct the logic and answer the challenge question
  • Combine with dynamic if static stalls