Ghidra is where I read one gnarly function; rizin/radare2 is where I live — it's faster to orient, scriptable, and it disassembles, patches, and debugs from one prompt. The command grammar is verb-then-noun and relentlessly chainable, which is intimidating for a day and muscle memory after that. Here's the working set.
The two tools share a command language almost byte for byte. I'll write r2;
rizin is the same session with renamed binaries — see the note at the end.
open and analyse#
Inside, if you didn't pass -A, analyse with aaa (or aaaa for the deep,
slow pass). Analysis is what populates function names, xrefs, and strings.
info before instructions#
Read the binary's metadata first — r2 even gives you checksec for free:
| command | what it lists |
|---|---|
iI |
binary info incl. nx / canary / pic / relro (checksec) |
ii |
imports (the libc surface) |
is |
symbols |
iz / izz |
strings in data sections / in the whole file |
iS |
sections |
ie |
entrypoints |
navigate and disassemble#
|
~ greps, @ runs a command at a temporary address, and they compose:
pdf @ main ~call lists every call inside main. That composition is the whole
reason to use r2 over clicking.
For the visual mode that feels like a TUI:
xrefs — the question you ask most#
"Who calls this, and what does this touch?"
axt sym.imp.system is often the fastest path to the bug: find the dangerous
call, then read backwards to what feeds it.
search — strings, bytes, and gadgets#
/R pop rdi makes r2 a serviceable gadget finder when you don't want to leave for
ROPgadget.
decompile in place#
pdg needs the plugin (r2pm -ci r2ghidra, or rizin's rz-ghidra), but it's the
Ghidra decompiler in your terminal — worth the install.
patch without a hex editor#
Open writable (-w, or oo+ to reopen rw mid-session), then write hex or assembly
straight over an instruction:
This is how you NOP a license check or flip a jz to a jmp and save the binary
in one place.
debug from the same prompt#
r2 -d ./chal drops you in with the process live; the debug commands mirror the
static ones with a d prefix:
| command | does |
|---|---|
db 0x401234 |
set a breakpoint |
dc |
continue |
ds / dso |
step / step-over |
dr |
show registers (dr rax=0 sets one) |
dm / dmm |
memory maps / loaded modules |
dbt |
backtrace |
make it yours#
Drop your defaults in ~/.radare2rc (or ~/.rizinrc) so every session starts right:
the only two help characters you need
Append ? to any command prefix to list its subcommands: i?, p?, d?,
/?. Append ?? for the long form. You navigate the entire command tree by
appending question marks — you don't memorise it, you discover it.
rizin vs radare2 — which one
rizin is a 2020 fork of radare2, aimed at a cleaner, stabler API and a more coordinated release process; the interactive command set is nearly identical, so everything above works in both. The differences you'll touch:
- tools are renamed —
rabin2→rz-bin,radare2→rizin,r2pm→rz-pm. - the Ghidra decompiler is rz-ghidra (built in to the rizin ecosystem) vs r2ghidra (a radare2 plugin).
- Cutter, the GUI, is built on rizin now — so learning rizin commands pays off in the GUI too.
Pick one and commit; the knowledge transfers either direction. I drifted to rizin for the saner plugin manager and never looked back.