radare2 static analysis cheatsheet

recently i started getting more comfortable with using radare2 for analyzing malware samples.

so i decided to share some of my cheatsheets :)

hopefully this will help you get comfortable with r2 as well.

this post will cover static analysis, later on i plan to post about dynamic analysis as well :)

r2 command structure

to learn the commands while going through this post, i suggest you pick a binary to your liking and practice on it.

even something “simple” like /bin/ls should get you started!

general format for r2 commands
[.][times][cmd][~grep][@[@iter]addr!size][|>pipe] ;

some example commands:

aaa # perform automatic program analysis
px200@rsp # print 200 bytes as hex from rsp
pdf@main # print disassembly of the main function
afl # list all functions

and so on.

to get help about any command, append ? after it.


? # show toplevel commands
a? # shows help for analysis commands
af? # shows help of function analysis commands
p? # help for 'print' commands

every subcommand has this. feel free to explore more on your own!

starting static analysis

open ./mybin:

$ r2 ./mybin

open ./mybin with initial automatic analysis:

$ r2 -A ./mybin

automatically runs the following commands:

aa (analyze all flags starting with sym. and entry0)
aac (analyze function calls
aar (analyze len bytes of instructions for references)
aaft (type matching analysis for all functions)

open with write permissions (useful if patching the disassembly)

$ r2 -w ./mybin

perform deep automatic analysis (might take a long time depending on binary size):

aaaa # analyze function preludes and enable constraint type analysis for variables

in my experience usually aa or aaa are sufficient for initial analysis.

useful radare2 utilities

$ rabin2 -I ./mybin # get info about binary

$ rafind2 -s <string> ./mybin # search bytestrings in binary

there are others like rarun2 which can be used for running binaries in specific environments and configurations (useful for exploitation or dynamic malware analysis), however i will cover dynamic analysis in a later post.

manual analysis

get info about file

the information commands are very very useful:

i # basic information about opened file
ia # show all information, imports/exports

some important information for security or malware related binaries can be the following variables:

  • arch
  • bintype
  • bits
  • canary (stack canary)
  • pic (position independent code)
ic # list classes, methods, fields
id # debug information (DWARF source lines)
ie # entry points
iee # entry and exit points
iE # exports
ii # imports
ih # headers
il # linked libraries
it # file hashes
iM # show main address
ir # show relocations
is # symbols
iS # binary file sections
iS~text # get text section
iS. # current section
iS= # show sections in ascii art
iV # version information (libc version etc.)
iz # search for strings at current location
izz # search for strings (whole binary)
izz~[7] # list all strings
izz~[6,7] # list all strings (with sections)

mapping and opening files

o [addr]# open file at optional address
o= # list opened files (ascii art)

o /usr/bin/zsh 0x499999 # map file
o # list mapped files

ob= # list opened binaries (ascii art)
om #  create, list, remove IO maps
pd # print disassembly at seek
pdj~{} # print disassembly as pretty json
pd@0x0101 # print disassembly at address 0x0101
pd@sym.of.interest # print disassembly at sym.of.interest
pdf@sym.of.interest # print disassembly function @ sym.of.interest
pdf@main~.. # paged disassembly
pdc@sym.of.interest # pseudo disassembly output in C-like syntax
pdf~call # grep for calls in disassembled function
pdf@main~call # grep for calls in main function

pxw #  hex words dump
pxq # hex quadwords dump

pf?? # list print formats
pf??? # get examples

pxb # hexdump form
pxA # op analysis color map

you’ll need to run r2 like so:

$ r2 -nn ./mybin # load the rbin structures (elf, mach0, ...)

pf?? # list all format definitions
pf.elf_header @ elf_header # show formatted elf header
pfS@rbp-8 # print function String @ addr/offset

analysis commands

ab@sym.of.interest # analyze block

afl # list functions
afl~printf # search for printf in function list
afll # list functions (verbose and color)
aflt # list functions in table format (useful information)
afvd # show local variables in function
afn somename 0x00016cf0 # rename function at address to 'somename'
afn somename old_func_name # rename function 'old_func_name' to 'somename'
ax # manage refs/xrefs
axt [addr] # find data/code refs to this address
axf [addr] # refs from this address
ax. [addr] # refs from and to this addr
axff # refs from this function

afx # list function references


radare2 has graphing abilities!

ag<graphtype><format> [addr]

agf@sym.of.interest # basic blocks function graph
agr@sym.of.interest # references graph

graph mode:

VV # start graph mode
pP # toggle between views
x # show xrefs (can be followed by pressing numerical id)
+/-/0 # adjust zoom
c # cursor toggle (can move graph nodes around)
q # quit


?@? # cool internal commands for doing basically everything

?$? # list available flags

? $$ # current seek

_ # print last output

~ # grep in command

~.. # add to the end of command to pipe output to less-like pager

~[n] # get nth column of output
~:n # get nth row of output
~:n[m] # get nth row of mth column 

/ # search stuff

! # history
!~.. # paged history
  • pseudo asm (useful if analyzing obscure architectures)

:> e asm.pseudo = true

will transform

│           0x080483ff      e832000000     call 0x8048436
│           0x08048404      31c0           xor eax, eax
│           0x08048406      0205849a0408   add al, byte [0x8049a84]
│           0x0804840c      83f800         cmp eax, 0
│           0x0804840f      7405           je 0x8048416


│           0x080483ff      e832000000     0x8048436 ()
│           0x08048404      31c0           eax = 0
│           0x08048406      0205849a0408   al += byte [0x8049a84]
│           0x0804840c      83f800         var = eax - 0
│           0x0804840f      7405           if (!var) goto 0x8048416

this is a slightly higher-level representation of the assembly code, which can be useful if it’s an unfamiliar architecture.

evaluate math expressions

?v? # get help

? 1337 # get all different representations of 1337

?vd 0x539 # eval decimal of 0x539

?vx 1337 # show 8 digit padding in hex

?vi 0x539 # eval int of 0x539

?vi 0x15 + 0x15 # calculate

supported operations:

    + : addition
    - : subtraction
    * : multiplication
    / : division
    % : modulus
    > : shift right
    < : shift left
?vi $s # get filesize
?v $$ # get current seek


/? # help
/ foo # search for foo
/ foo\x00 # search for foo (null-terminated)
/a # search for asm instrunctions matching given properties
/ad <instruction> # search for certain instructions
/ad cmp # search for cmp instruction
/ad xor ~ rax # search for xor, grep for rax

visual mode

V # enter visual mode
p # switch to next view
P # switch to previous view
q # quit

very similar to vim bindings,
use j/k to move up/down
: to issue any r2 commands

visual mode commands

v # view management screen (useful for navigation and analyzing/renaming functions or variables)
V # view graph (follow calls using the keybinds in comments like [oa] or [oc] etc.)

g [addr/sym] # go to address/sym
gg # go to beginning of file
gG # go to end of file
s main # seek to main, press enter twice to update visual
s <addr> # seek to address
s* # show seek history (useful)
<Enter> # jump to call at seek
<Space> # show graph of function
[0-9] # follow call/jmp number indicated in asm comment like [1] or [3]
u # go back
U # go forward
x # show xrefs
X # go back in xrefs

c # toggle cursor mode (use hjkl to move, hold shift to highligh
; # comment
A # edit assembly code (patching binary)
i # edit hexcode (patching binary)

visual mode with panels

this is more useful for dynamic analysis when debugging, so you can set up your panes to look like any other debugger you’re already used to.

however there’s nothing stopping you from using it for static analysis as well.

V! # start visual mode with panels
Tab # switch panel
| # split vertical
- # split horizontal
" # change panel type
X # close panel
v= mylayout # save layout as 'mylayout'
v mylayout # load mylayout
B # set breakpoint
F7 # step into
F8 # step over
F9 # continue
[1-9] # follow jmp/call

the end

and this is it for now. i hope this helps someone getting started with radare2!

make sure to check out the official r2 book

some other resources that i recommend checking out: