radare2 on the second attempt
If you bounced off radare2 the first time, you probably tried to learn it the wrong way. A small command set, a clearer mental model of the namespace, and a target binary worth opening.
Almost everyone gives up on radare2 the first time. You install it, type r2 ./binary, get a [0x00400500]> prompt, type help, get back a screen of single-letter commands with no obvious entry point, and quietly close the terminal. A week later you open Ghidra and never come back.
That's a reasonable first response. The tool is terse, the documentation is scattered, the learning curve is genuinely steeper than its competitors. But the design is coherent once you see it, and for some workflows it stays the fastest tool in the box. Here's the second attempt.
The philosophy explains the rough edges
radare2 is modal, terse, and scriptable. Commands live in a hierarchical namespace where each letter narrows the scope. You chain them with ;, pipe with |, redirect with >, and call them from Python via r2pipe. The intent is that you'll script your reverse engineering, not click through it.
That's the trade. Ghidra hands you a polished GUI and a decompiler in exchange for a heavyweight JVM app. radare2 hands you a fast, scriptable shell that runs everywhere (over SSH, on weird embedded targets, on machines with no GUI) in exchange for memorising a command tree.
If the second appeals to you, keep reading. Otherwise, Ghidra. Both are honest answers.
The command namespace, in one diagram
The pattern: pick a top-level letter, then drill down. a is analysis, aa is auto-analyse, aaa is auto-analyse all (more thorough), aaaa is even more (sometimes too much). p is print, pd is print disassembly, pdf is print disassembly of the current function. Append ? to any prefix to see what's under it: a?, p?, s?. That's the whole interactive help system. Once you see the pattern, the help text stops being a wall and starts being a tree you can navigate.
A minimum viable command set
Open a binary:
r2 ./vulnAnalyse it:
[0x00400500]> aaaaaa runs the standard auto-analysis: identifies functions, follows references, finds strings, applies basic type info. Wait for it. On a small binary it's instant; on a large binary it can take seconds to a minute. Don't skip it — most other commands assume the analysis ran.
List functions:
[0x00400500]> afl0x00400440 1 11 sym.entry00x004004c0 4 50 sym._init0x00400500 1 13 -> 19 sym.imp.puts0x00400540 3 23 main...Seek to one:
[0x00400500]> s main[0x00400540]>The prompt updates with the new offset. Print the function as disassembly:
[0x00400540]> pdf ; DATA XREF from entry0 @ 0x40045d┌ 23: int main (int argc, char **argv);│ 0x00400540 55 push rbp│ 0x00400541 4889e5 mov rbp, rsp│ 0x00400544 bf04064000 mov edi, str.hello ; "hello"│ 0x00400549 e8c2feffff call sym.imp.puts│ 0x0040054e b800000000 mov eax, 0│ 0x00400553 5d pop rbp└ 0x00400554 c3 retThat's the eighty percent. Add s sym.foo to navigate by symbol, pd 20 to print twenty instructions from wherever you are, axt to see what calls the current address, iz to list strings in the binary, ii to see imports.
Visual mode is where the daily work happens
Type V and you enter visual mode. Now you have arrow keys, single-letter shortcuts, and several views you can cycle through with p (cycle forward) and P (cycle back): hex view, disassembly view, debugger view, and a few others.
In visual mode:
:drops to a command prompt for one command, then returns to visual.sseeks to an address you type.qexits visual mode back to the regular prompt.
Visual graph mode (VV) is the headline. It renders the function's CFG in ASCII art. Arrow keys move between blocks, Enter follows jumps. It's not as pretty as Ghidra's, but it works over SSH on a 2009 thinkpad, which has its own quality.
[0x00400540]> VV @ mainInside VV, press ? for the keybinding list. The ones you'll use most: J/K jump to true/false branch, t and f similarly, R reseed the layout if it's ugly, : for one-shot commands, q to leave.
Once VV clicks, you stop missing the GUI for most tasks.
Renaming, commenting, and saving your work
Reverse engineering is half analysis and half taking notes on what you found. radare2 stores those notes in projects.
Rename a function:
[0x00400540]> afn newnameAdd a comment at the current address:
[0x00400540]> CC this looks like an XOR loopSave the project:
[0x00400540]> Ps myprojectOpen it next time:
r2 -p myproject ./vulnWithout the project, every renamed function and every comment is gone the moment you q. Save early.
When to use it (and when not to)
radare2 earns its keep over SSH, when you want scriptable output, when the binary is small and you want to be in and out fast, when you're on an architecture Ghidra struggles with, or when you genuinely enjoy living in a terminal.
It earns less when you're a week into a complicated binary and want a decompiler that propagates types as you rename them, when you're collaborating with Ghidra-project users, or when you want a polished UI. The decompiler that ships via the pdc and pdg plugins is improving but still well behind Ghidra's; if you need decompilation as a first-class output, Ghidra is the better tool.
The first attempt at radare2 usually fails because people memorise commands without learning the namespace. The second attempt, with the tree in mind and a real binary to chew on, tends to stick. Pick something small, run aaa, run afl, seek to the largest function, pdf, then VV. Take an hour. The fluency comes faster than the first session suggests.
A small target to start on
If you don't have a candidate, compile this:
#include <stdio.h>#include <string.h>
void win(void) { puts("you win");}
void check(const char *s) { if (strcmp(s, "secret") == 0) { win(); } else { puts("nope"); }}
int main(int argc, char **argv) { if (argc > 1) check(argv[1]); return 0;}Build with gcc -no-pie -o demo demo.c. Open with r2 -A ./demo (-A runs aaa on load). afl lists functions. s main; pdf reads main. VV @ check shows the conditional in graph form. axt @ sym.win shows who references win. Fifteen minutes of this and the workflow stops being mysterious.
Where to take this
The wider art of reverse engineering (what to do with the disassembly once you have it, how to recover types, how to handle obfuscation, how to do all this on something you didn't write) lives in Module 66: Reverse Engineering. radare2 is one tool among several; the underlying skill of reading a stranger's compiled code is what carries between them.