Radare (RawDataRecovery) was started as a forensic hex editor. Over the years it has evolved into a reverse-engineering and binary analysis framework. Radare2 is a complete rewrite.
It is (somewhat unfairly) known for its difficulty curve, but once you get used to how it does things, it's hard to go back.
- installation
- the basics
r2
- usage examples
- scripting with
r2pipe
- configuration
- GUIs
- sources and further reading
You are strongly encouraged to always use the absolute latest version of Radare2
(it is a requirement to get any support).
As such, the best way to install it is directly from the git repository ([r2repo]):
git clone https://github.com/radareorg/radare2.git
radare2/sys/install.sh # also used to update.
You might want to compare your version (r2 -v
) to the latest commit.
See [r2b].
Radare2 follows the Unix philosophy of minimalist, modular programs. The provided command line utilities are:
tool name | function |
---|---|
radare2 |
the main tool (CLI/TUI), aliased to r2 |
r2pm |
the r2 package manager |
rabin2 |
extracts info about a binary (ELF, PE, etc.) |
radiff2 |
binary diffing, a more powerful cmp |
rafind2 |
finds byte patterns |
ragg2 |
compiler that creates tiny binaries for injection |
rahash2 |
block based hashing (great to compare large files) |
rarun2 |
run programs in different environments |
rasm2 |
CLI assembler/disassembler (x86, x64, Java, etc.) |
rax2 |
base/radix/ASCII/string converter |
Radare2 can open many input/output sources as if they were files. Among others:
disks, files, kernel drivers, network connections, partitions, processes.
r2
supports different modes of operation. You can think of it a
bit like the Vim of reverse engineering tools.
You start in command mode (CLI). Execute the ?
command to get help.
From command mode you can switch to visual mode (TUI) with
the V
command. In visual mode you can cycle through various
print modes with the shortcuts p
(next) and P
(previous).
mode | function |
---|---|
command mode | default mode, all commands available |
visual mode: hex | hex editor view (similar to xxd ) |
visual mode: disas | disassembly view |
visual mode: debug | disassembly view with registers and stack |
visual mode: word | |
visual mode: buf | |
visual-panels mode | advanced, panel based TUI |
visual graph mode | control flow diagrams akin to IDA pro |
You will have noticed that in visual mode you use keyboard shortcuts.
Press ??
to get the full list.
You can still execute commands with :
though, just like in Vim.
You can continue to execute commands or close the prompt with ctrl-d
or by sending an empty line.
The shortcut q
gets you back to command mode.
The command q
exits Radare2. You can also use ctrl-d
both times.
r2-command-mode.jpg
- note the following:
- in command mode the prompt shows the current position in the file
- this position is the currently
seek
ed-to line (not the instruction pointer) - most commands operate on this address
- this position is the currently
- in command mode the prompt shows the current position in the file
r2-visual-mode-hex.jpg
- note the following:
- in visual mode you can see the current position in the top line (far left)
- it is also the top line in the hex-dump
- the instruction pointer is declared via a comment (
; rip
)
- in visual mode you can see the current position in the top line (far left)
To open a file for analysis run r2 /path/to/bin
. If you plan on modifying it add the
-w
flag, if you would like to open the file in debug mode (to step through it) add -d
.
Modes are not the only similarity to Vim. Just like it, Radare2 uses the chaining of single characters to create commands.
Each command starts with a single mnemonic character.
For instance: every command that is related to some kind of analysis starts with a
.
You can use the single character as a command directly or append more characters and symbols
to get access to more functionality in the corresponding category. A single a
, for example,
is aliased to aai
, which stands for 'analysis all info' which shows info of all analysis paramters.
Here's a visual example of the d
command, which groups commands related to the debugger:
r2-command-flowchart.jpg
The full list can be seen with the ?
command, here is a short excerpt:
first character | mnemonic | as direct command |
---|---|---|
a |
analysis | aliased to aai |
d |
debugger | aliased to d? |
i |
info | show info of current file |
o |
open | list open file/open file (with parameter) |
p |
aliased to p? |
|
s |
seek | print current address/seek to address (with parameter) |
w |
write | aliased to w? |
V |
Visual | start visual mode |
To learn more about the direct command and sub commands
you can append a ?
to get detailed help.
Numbers can also be used to modify how certain commands behave:
px
prints a hexdump of a couple of Bytes2px
executes it twicepx2
prints exactly 2 Bytes
Most commands are targeted at the position you are currently seeked to.
It can be inconvenient to seek to a new address just because you need to run a
single command there. This is were temporary seeking with @
comes into play.
As an example:
- you are seeked to somewhere in the middle of a file
- you would like to print 512 Bytes from the start of that file
You can simply run px512@0x0
which allows you to get the result and not change your current position.
A postfix worth mentioning is j
that formats output as JSON.
i
produces information for the currently open file, such as
the binary format. Using ij
you get the same information as
a JSON array.
By appending a format modifier you can even pretty print it ij~{}
:
r2-json.jpg
To learn more about format modifiers (and the built-in grep
that powers them) take a look at ~?
.
Finally, output can be piped directly to another program!
Using the JSON example from above let's open the output in Vim: ij~{}|vim - +"set ft=json"
.
These should get you started.
?
, get helpaa
, analyze all flags starting withsym.
andentry0
(you can add morea
s for additional analysis)- coming from other tools it might seem strange that this is not done by default, for the reason see: [r2default]
afl
, list all functionsafvd
, list local vars/args (analyse function variable: display)ie
, info about entrypointsii
, info about importsil
, info about librariesiS
, info about sectionsiz
strings in data sections main
, seek tomain()
db main
, set breakpoint atmain()
dc
, continue executiondr eax=0x0
zero outeax
registerood
, reopen binary in debug mode (restart it)oo+
, reopen with write privilegespdf
, print disassembly of current (seeked-to) functionVpp
, enter visual mode in hex viewV!
, enter visual-panels modeVV
, enter graph modeq!
, force quit without questions
Shortcuts are executed immediately and don't require an enter. Here's a selection:
?
get helph
,j
,k
,l
, seek left/down/up/right (Vim-like navigation)c
toggle cursor, navigate as aboven
andN
, seek to next/previous function.
seek to instruction pointers
andS
, step into or step overg
goto (seek) to flag/offset/register, tab completion!p
andP
, switch trough print modes (next and previous)!
, toggle visual-panels mode$
set instruction poiner to current location- careful: this does not update any memory or the stack
V
, switch through graph modesq
, quit
ESIL stands for Evaluable Strings Intermediate Language. Like Forth it is a stack-based, imperative programming language that uses reverse Polish (postfix) notation. You can use ESIL to create representations of different CPU architectures.
Assembly, for any architecture that has been represented with ESIL, can be emulated in Radare2.
This has a couple of advantages:
- you can debug code you don't have the hardware/software for
- registers are aliased to familiar names
- you can chose exactly where to start emulation, where to stop it, and which operations to skip (e.g. function calls to external libraries)
The ESIL family of commands are prefixed with ae
. For a list of commands use ae?
.
If you are interested in examples of the ESIL syntax you can use ae??
.
Here are some ESIL emulation commands to get you started:
aeim
, init memory: set up ESIL VM stack and set instruction pointer to seeked-to addressaeim-
, tears it down again
aes
, step one instruction (s
in visual mode)aesu <address>
, step until <address>aeso
, step over one instruction (emulate but don't go into function)aess
, step skip one instruction or call (does not emulate, use it to save time)
aer
, show registers (or just useVpp
)
All binaries that will be produced by these examples can be found in this folder. The unmodified versions of those binaries can be found in the respective folder of the section that introduced any one binary.
You should get in the habit of only running and debugging them inside of a VM.
Let's patch the check_pin
binary from the exploit-development ↣
section so that it always returns EXIT_SUCCESS
(0
), even if we provide a wrong pin to it.
cp check_pin check_pin_cracked # make a backup.
r2 -w check_pin_cracked # open binary in write mode.
# r2
aa # analyse binary.
afl # get a list of functions.
s main # seek to main().
Vpp # open visual mode (debug view).
# visual mode
# look at main() and see that it calls check_pin().
:s sym.check_pin # seek to it.
/test # look for a test instruction.
# decide how to patch the program.
# see: r2-check_pin-pre-patch.jpg
:s 0x80491c3 # seek to: mov eax, 1 # sets return value to 1 for wrong pins.
:wa mov eax, 0 # change instruction to set eax to 0 -> return success.
# exit r2 and test binary with wrong pin:
./check_pin_cracked < <(123); echo $?
# returns 0 despite wrong pin!
r2-check_pin-pre-patch.jpg
- note the following:
- the line that will be patched by the process above is highlighted (pre-patch state)
The crackme_calc
binary calculates the password at runtime. This makes it
bothersome to get it via static analysis. Even if you have the source
(which you do: crackme_calc.c).
It has been compiled on Linux. Since we're analysing this one on macOS we can not use regular debugging.
r2 -A crackme_calc # open and analyse it.
# the `-A` flag is the same as running `aaa` in Radare2.
# note that we don't pass the `-d` flag!
#r2
!uname # Darwin. We're on macOS.
iq~os # os linux. The binary is compiled for Linux.
Vpp # start disas view.
# visual mode
g # seek menu (try tab completion!)
main # seek to main.
<space> # toggle control flow graph.
# see: r2-control-flow-graph.jpg
r2-control-flow-graph.jpg
# Alright, we have a compare followed by a jump-not-equal.
# The graph shows us the two possible paths. The green "true" path
# will be called if the password is wrong (cmp is not-equal).
# The compare takes two inputs:
# * the user input (var_ch via eax)
# * the calculated password (var_4h)
# Let's emulate all the calculations right up to the compare:
<space> # close command flow graph.
:aeim # initialise ESIL VM stack and set instruction pointer.
s # execute each instruction except calls.
:aess # skip step calls.
# once we reach the cmp:
afvd # look for the value of var_4h, that's the password!
# exit radare2.
./crackme_calc # enter password - find it yourself ;)
Configuration in r2
happens with the e
-family of commands.
Use ev
to learn about all options, their value and what they do.
This is a huge list so you might want to grep it for a keyword,
for instance: ev~utf8
.
Use e? src.color
to only learn about the color mode option.
There is a visual browser for all settings: Ve
, you can navigate it with hjkl
.
From within r2
you can use the ed
command to open the config file (~/.radare2rc
) in your editor.
.radare2rc
# use matrix color scheme:
eco matrix
# use 256 colors:
e src.color = 2
# show descriptions for opcodes,
# great while learning a new architecture:
e dbg.describe = 1
# show pseudocode instead of opcodes:
e dbg.pseudo = 0
You can toggle boolean options with e!
. This will toggle opcode descriptions: e! asm.describe
.
This can be especially useful in combination with ctrl-r
, the reverse-incremental-search for commands.
It is possible to write changes to cache for programs that were opened in read-only mode: e io.cache=1
.
Only the file in memory will be changed. This allows you to play with read-only files (instead of getting the Failed to write
error).
Aliases in Radare 2 all start with a $
. See $?
for the help.
It's easiest to use the ed
command to write them to the configuration file.
You might need to Base64 encode them if your command contains special characters.
Use $myalias=-
to open the editor and write the command unencoded, then $*
to get
the encoded line for ed
.
Here are a couple of ideas:
# pxr 12@r:SP
$$=base64:cHhyIDEyQHI6U1A=
# emulate checksec command:
# $checksec=i~pic,canary,nx,crypto,stripped,static,relocs
$checksec=base64:aX5waWMsY2FuYXJ5LG54LGNyeXB0byxzdHJpcHBlZCxzdGF0aWMscmVsb2Nz
You can run your alias like any regular command, e.g. $$
.
- web interface:
r2 -c=H --
- Cutter (cutter.re)
- about 5 that are abandoned by now
- [r2b] pancake, maijin, et al. (2020). The Official Radare2 Book. https://book.rada.re/
- [r2default] pancake. (2015). Analysis By Default. https://radareorg.github.io/blog/posts/analysis-by-default/
- [r2repo] pancake. (2020). radare2 GitHub repository. https://github.com/radareorg/radare2