radare2
Scriptable command-line reverse-engineering framework. Opens any blob at any base address to analyse, debug, and patch firmware, with a visual graph and the Cutter GUI.
radare2 is a scriptable command-line reverse-engineering framework for disassembling, analysing, debugging and patching binaries and raw firmware, all from one keyboard-driven prompt.
What it is
radare2 (often just r2) opens any file, or a live process, or a raw flash dump, at any base address, runs its analysis, and gives you a terse but very fast interactive shell over the code. Everything is a short command: a analyses, p prints, s seeks, w writes. It has a visual mode, a graph view, a built-in debugger, and an assembler, so a single tool covers the whole loop from static reading to live debugging to patching. Its sister GUI Cutter wraps the same engine (and the Rizin fork it grew into) for those who prefer windows over the prompt.
Why it matters
Ghidra is the heavyweight decompiler; radare2 is the scalpel. For triage, for scripting a repetitive extraction across many binaries, for patching a byte in place and re-flashing, or for debugging on a constrained box where a full GUI will not run, r2 is faster and lighter. Because it is entirely command-driven it scripts cleanly (r2 -q -c 'commands' file), which makes it the natural choice inside an automated firmware pipeline.
Typical workflow
r2 -a arm -b 32 -m 0x8000000 firmware.bin # arch, bits, map address up front
[0x08000000]> aaa # analyse all (functions, xrefs, strings)
[0x08000000]> afl # list discovered functions
[0x08000000]> iz # list strings in the data section
[0x08000000]> pdf @ main # disassemble a function
[0x08000000]> axt @ sym.check_password # who calls this?
[0x08000000]> VV @ main # interactive visual graph (q to exit)
Patch in place and write it back:
[0x08000000]> s 0x08001234 # seek to the branch you want to kill
[0x08000000]> wa nop # assemble a NOP over it
[0x08000000]> wx 9090 @ 0x08001240 # or write raw bytes
# open with -w to persist edits to the file, then re-flash with esptool/flashrom
Tips
- For a headless flash dump, set the architecture (
-a), bit width (-b) and map/base address (-m) at launch. Get the base wrong and every cross-reference is meaningless, exactly as in Ghidra. / passwordbyte-searches,iz/izzlist strings; both are the quick path to hardcoded credentials and endpoint URLs.aaais the standard analysis; if it is too slow on a huge image, useaafor a lighter pass and analyse individual functions withafon demand.r2 -d ./prog(or attach overgdb:///OpenOCD) turns it into a debugger:dbsets breakpoints,dccontinues,drreads registers.
Pitfalls
- The command language is dense and unforgiving;
?after any prefix (a?,p?,w?) lists that family. Keep a cheat sheet until it sticks. - radare2 has no decompiler by default. Install the
r2ghidraplugin (pdgcommand) or pivot to Ghidra when you need pseudocode rather than disassembly. - Patches only persist if the file was opened writable (
-w); forgetting it silently discards yourwx/waedits. - The project split into radare2 and the Rizin/Cutter fork; commands are near-identical but a few flags differ between them.
What it pairs with
r2 slots into the same reversing stage as ghidra, and many workflows use both: r2 to script and patch, Ghidra to read decompiled C. binwalk supplies the carved binaries; a jtag-swd-probe driving OpenOCD gives r2 a live target to debug over gdb://, so a static finding can be confirmed on real silicon.