Preamble
The topic plan called for a reverse-engineering pass. This month is deliberately small: a trivial C++ binary—maybe with a hard-coded string or obvious strcmp—imported into NSA GHIDRA, free and scriptable. The goal is literacy, not a CTF trophy.
GHIDRA step by step (first session)
These steps assume a small ELF or PE you built yourself or are allowed to analyze.
-
Create a project
File → New Project → pick a folder. GHIDRA stores analysis metadata here, not a copy of every binary (you still point at the file on disk). -
Import the binary
File → Import File → select the executable. Accept sensible defaults for format and loader options unless you know you need something special (packed malware, odd segments). Double-click it in the project window to open the CodeBrowser. -
Run analysis
When prompted, run auto-analysis with the default analyzers. Wait until the status bar quiets down. Skipping this leaves missing functions, weak xref graphs, and a decompiler that invents less structure than it could. -
Orient in the UI
- Listing: linear disassembly.
- Decompile: C-like output for the function under the cursor (Window → Decompile if it is hidden).
- Symbol Tree → Functions: browse recovered symbols;
mainor_start/entryis a usual anchor. - Defined Strings: literal pool for C++ (
"usage:", error messages) and RTTI-ish noise.
-
Navigate
Double-click a call target or jump to enter a function. G (Go To) jumps to an address or symbol. X on an instruction or data item shows cross-references (who calls this, who reads this string). -
Annotate as you read
Rename functions (L), variables, and data (Label from context menu). Drop comments (;) on blocks you understand. The decompiler picks up renames; your future self will too. -
Optional exports
When scripting or diffing, you may export listings or use the Script Manager (Python/Java). That is optional for the literacy pass.
The old shorthand still holds: import → let analysis finish → find main (or entry) → follow xrefs from strings → rename and comment as you go.
Tracing an if / else from a C++ binary
Compilers lower conditionals to compare + conditional jump (sometimes cmov or SETcc for small branches, but jumps are the teaching case). Your job is to connect decompiler if to Listing instructions and not confuse C++ structure with what is actually on disk.
Steps
-
Start in the decompiler
Inmain(or the function you care about), find anif (…)block. Note the predicate (what is being compared) and whether there is anelse. -
Sync to disassembly
Click inside theifline or the opening brace; GHIDRA usually moves the cursor in the Listing to the corresponding address. If it does not, click in the Listing on the same function and step through until the graph/decompile highlight aligns. -
Identify the compare
Look forCMP,TEST(oftentest reg, regfor null/zero), orSUBused as a compare. For C++ objects you may see calls (strcmp,operator==, virtual dispatch) followed by a test of the return value and a jump. -
Read the branch
After the compare, find the conditional jump:JZ/JNZ,JE/JNE,JL/JGE, etc. (Intel mnemonics vary; ARM usesCMP+B.cond.) One successor is the fall-through path; the other is the taken branch. Map mentally: fall-through = then or else?—it depends on how the compiler inverted the condition. Trust labels and the decompiler, then verify by reading both sides. -
Follow both edges
Step into the not-taken path (fall-through) and the taken path (jump target). Each should match one arm ofif/else. If the optimizer merged arms or duplicated tails, the decompiler may showgotoor shared merge blocks; the graph view (Show Function Graph) makes that obvious. -
Find the merge point
Both arms often reconverge at a label. That is where theifstatement ends in the high-level sense. Loops add back-edges; anifinside a loop shows as a conditional that does not dominate the function exit.
What to look out for
- Signed vs unsigned compares use different jump families (
JLvsJB). Misreading that inverts your mental model of edge cases. - Short-circuit
&&/||is multiple compares and jumps, not one bigif. - Inlined code can make “the
if” disappear into a sea of straight-line instructions until you spot theCMP/TEST+ Jcc pattern again. - Exceptions and STL wrap logic in outlined helpers; you may land in
std::-ish symbols. Follow one level, rename, return to the caller. - Decompiler lies: odd types, fused compares, or hand-written assembly can produce plausible-looking C that is wrong. When something feels off, anchor on the Listing and treat the decompiler as a hypothesis.
- No symbols:
ifstill exists as jumps; use strings, constant pools, and call patterns to orient.
GHIDRA vs IDA Pro vs another decompiler (Binary Ninja)
All three are professional-grade; the differences are mostly workflow, cost, and how much you live in the decompiler pane.
| Aspect | GHIDRA | IDA Pro (+ Hex-Rays) | Binary Ninja |
|---|---|---|---|
| Cost / license | Free, open source | Paid; decompiler is an add-on (Hex-Rays) | Paid; personal licenses exist |
| Decompiler | Built-in (P-code based) | Hex-Rays is the industry reference for readability | Built-in HLIL; strong IL story |
| Project model | Project folder + imported files | Database (.idb / .i64) per binary |
Database with good undo |
| Scripting | Java + Python | IDC + Python (IDA 7+); huge third-party corpus | Python API; clean and consistent |
| Learning curve | Busy UI, but one download gets everything | Familiar to many analysts; power features are deep | Smaller surface area; graph and IL are first-class |
IDA Pro (with Hex-Rays) often wins on maturity of signatures, team habits, and “I need this exact plugin” ecosystems. The decompiler output is what many people mentally compare others against. GHIDRA gives a full pipeline at zero cost: disassembly, decompiler, decent type editor, scripting—excellent for learning and many production workflows. Binary Ninja sits in the middle for many users: polished UX, HLIL that is pleasant to read, and an intermediate language that rewards people who like lifting and programmatic analysis.
For tracing an if/else, the procedure is the same idea everywhere: compare → conditional branch → two subgraphs → merge. GHIDRA’s Listing ↔ Decompile sync is strong; IDA’s F5 decompiler and graph are the classic pairing; Binary Ninja’s HLIL and graph side-by-side are similarly effective. Pick based on budget, team standard, and whether you care more about plugin ecosystem (IDA), all-in-one free stack (GHIDRA), or API/IL ergonomics (Binary Ninja).
Ethics and scope
This is reconnaissance on binaries you are allowed to analyze—your own builds, CTF artifacts, or licensed samples. It is not a license to poke production systems.
Conclusion
Comfort with disassembly pays dividends when debugging native crashes, JNI boundaries, or supply-chain questions. sqlmap Basics with a Defensive Mindset moves to sqlmap with a defensive lens.