Wiki / Software

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.
  • / password byte-searches, iz/izz list strings; both are the quick path to hardcoded credentials and endpoint URLs.
  • aaa is the standard analysis; if it is too slow on a huge image, use aa for a lighter pass and analyse individual functions with af on demand.
  • r2 -d ./prog (or attach over gdb:///OpenOCD) turns it into a debugger: db sets breakpoints, dc continues, dr reads 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 r2ghidra plugin (pdg command) 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 your wx/wa edits.
  • 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.

Further reading