The Basics

In this section, we will simply get introduced to radare2 and explore the basics of its commands. It is not centered on any particular aspect of radare2, but will provide you with some vital background needed to more efficiently wrap your head around the overall structure and design of the framework.

Resources

There are plenty of resources scattered around the web from which you can learn more on how you can use radare2 for various tasks.

Most of these resources can be found in this blog post.

What is left out is radare.tv, which is quite a magical place which you should check out from time to time.

There's also the more practical and focused workshop by Maijin.

So, what is radare2?

You would not be wrong if you were to say that radare2 (or r2, in short) is a disassembler. But it is so much more.

r2 can aptly be named a reverse engineering framework, with some extra features on the side.

Here is a (non-exhaustive) list of what r2 can be:

  • Disassembler
  • Assembler
  • Debugger
  • Hex editor
  • Exploit development tool
  • Emulator
  • Binary diffing tool
  • Shellcode compiler
  • Launcher with specific contexts
  • And more...

It can run on all major operating systems and understand any gizmo which has as little as an oscillator in it.

Taking the plunge

Radare2 can be started by typing radare2 or r2 in the console. You will be prompted with the following:

r2
Usage: r2 [-dDwntLqv] [-P patch] [-p prj] [-a arch] [-b bits] [-i file]
          [-s addr] [-B blocksize] [-c cmd] [-e k=v] file|pid|-|--|=

The important argument here is file. A process id (pid) can also be supplied when we want to attach to a process which is already running, but in most cases we will be using files.

Let's try it out on the humble and ubiquitous /bin/ls

r2 /bin/ls
-- Change the UID of the debugged process with child.uid (requires root)
[0x004048c5]>

Notice that the prompt changes. We are now exploring the memory map of /bin/ls. The value between parentheses is the current address position within the current file. This is the entry point of the binary (unless radare is configured differently).

Help!

Now you may want to navigate, disassemble, search, mark and do other operations. How?

[0x004048c5]> help
|ERROR| Invalid command 'help' (0x68)

Radare2 is self-documented. For a full list of commands, a simple question mark (?) will suffice and is much faster than typing help all the time.

[0x004048c5]> ?
Usage: [.][times][cmd][~grep][@[@iter]addr!size][|>pipe] ; ...
Append '?' to any char command to get detailed help
Prefix with number to repeat command N times (f.ex: 3x)
|%var =valueAlias for 'env' command
| *off[=[0x]value]     Pointer read/write data/values (see ?v, wx, wv)
| (macro arg0 arg1)    Manage scripting macros
| .[-|(m)|f|!sh|cmd]   Define macro or load r2, cparse or rlang file
| = [cmd]              Run this command via rap://
| /                    Search for bytes, regexps, patterns, ..
| ! [cmd]              Run given command as in system(3)
| # [algo] [len]       Calculate hash checksum of current block
| #!lang [..]          Hashbang to run an rlang script
| a                    Perform analysis of code
| b                    Get or change block size
| c [arg]              Compare block with given data
| C                    Code metadata management
| d                    Debugger commands
| e [a[=b]]            List/get/set config evaluable vars
| f [name][sz][at]     Set flag at current address
| g [arg]              Go compile shellcodes with r_egg
| i [file]             Get info about opened file
| k [sdb-query]        Run sdb-query. see k? for help, 'k *', 'k **' ...
| m                    Mountpoints commands
| o [file] ([offset])  Open file at optional address
| p [len]              Print current block with format and length
| P                    Project management utilities
| q [ret]              Quit program with a return value
| r [len]              Resize file
| s [addr]             Seek to address (also for '0x', '0x1' == 's 0x1')
| S                    Io section manipulation information
| t                    Cparse types management
| T [-] [num|msg]      Text log utility
| u                    uname/undo seek/write
| V                    Enter visual mode (vcmds=visualvisual  keystrokes)
| w [str]              Multiple write operations
| x [len]              Alias for 'px' (print hexadecimal)
| y [len] [[[@]addr    Yank/paste bytes from/to memory
| z                    Zignatures management
| ?[??][expr]          Help or evaluate math expression
| ?$?                  Show available '$' variables and aliases
| [email protected]?                  Misc help for '@' (seek), '~' (grep) (see ~??)
| ?:?                  List and manage core plugins
[0x004048c5]>

This is understandably a daunting sight to behold, and it will not get any easier from this point on. Thankfully, most of these are self-contained and define a specific category of subcommands. For example, all analysis commands begin with a, all commands related to the debugger begin with d, all printing commands begin with p etc.

Looking through commands

While learning radare2, you will iteratively consult the built-in documentation to find commands which help you accomplish your specific needs, by appending a ? after each combination of interest. For example:

[0x004048c5]> a?
|Usage: a[abdefFghoprxstc] [...]
| ab [hexpairs]     analyze bytes
| aa                analyze all (fcns + bbs) (aa0 to avoid sub renaming)
| ac [cycles]       analyze which op could be executed in [cycles]
| ad                analyze data trampoline (wip)
| ad [from] [to]    analyze data pointers to (from-to)
| ae [expr]         analyze opcode eval expression (see ao)
| af[rnbcsl?+-*]    analyze Functions
| aF                same as above, but using anal.depth=1
| ag[?acgdlf]       output Graphviz code
| ah[?lba-]         analysis hints (force opcode size, ...)
| ai [addr]         address information (show perms, stack, heap, ...)
| ao[e?] [len]      analyze Opcodes (or emulate it)
| an[an-] [...]     manage no-return addresses/symbols/functions
| ar                like 'dr' but for the esil vm. (registers)
| ap                find prelude for current offset
| ax[?ld-*]         manage refs/xrefs (see also afx?)
| as [num]          analyze syscall using dbg.reg
| at[trd+-%*?] [.]  analyze execution traces
Examples:
 f ts @ `S*~text:0[3]`; f t @ section..text
 f ds @ `S*~data:0[3]`; f d @ section..data
 .ad t t+ts @ d:ds

[0x004048c5]> af?
|Usage: af
| af ([name]) ([addr])              analyze functions (start at addr or $$)
| afr ([name]) ([addr])             analyze functions recursively
| af+ addr size name [type] [diff]  hand craft a function (requires afb+)
| af- [addr]                        clean all function analysis data (or function at addr)
| afa[?] [idx] [name] ([type])      add function argument
| af[aAv?][arg]                     manipulate args, fastargs and variables in function
| afb+ fa a sz [j] [f] ([t]( [d]))  add bb to function @ fcnaddr
| afb [addr]                        List basic blocks of given function
| afB 16                            set current function as thumb (change asm.bits)
| [email protected][addr]                        calculate the Cyclomatic Complexity (starting at addr)
| afC[a] type @[addr]               set calling convention for function (afC?=list cc types)
| aff                               re-adjust function boundaries to fit
| afF[1|0|]                         fold/unfold/toggle
| afg                               non-interactive ascii-art basic-block graph (See VV)
| afi [addr|fcn.name]               show function(s) information (verbose afl)
| afl[*] [fcn name]                 list functions (addr, size, bbs, name)
| afo [fcn.name]                    show address for the function named like this
| afn name [addr]                   rename name for function at address (change flag too)
| afna                              suggest automatic name for current offset
| afs [addr] [fcnsign]              get/set function signature at current address
| afx[cCd-] src dst                 add/remove code/Call/data/string reference
| afv[?] [idx] [type] [name]        add local var on current function

[0x004048c5]> afn?
Usage: afn[sa] - analyze function names
 afna       - construct a function name for the current offset
 afns       - list all strings associated with the current function
 afn [name] - rename function

While this "forest" of a documentation does a decent job of what each and every command does, it does not tell you anything about how to use them. This is what the Internet (and subsequently, this book) is for. As mentioned before, radare2 can be used in plenty of scenarios. Not everyone is interested in shellcodes or DNA sequencing, so it makes a bit of sense not to include domain-specific examples within the documentation.

Command philosophy

Usage: [.][times][cmd][~grep][@[@iter]addr!size][|>pipe] ;

This is the command format for radare2. Although this looks cryptic, only the command itself is mandatory, and it will operate using some default values as we will see further on.

If you have some experience working with *nix shell, Vim, sed, awk, then learning radare2's commands will be slightly more intuitive.

Current seek

In general (i.e. default behavior), each command has a point of reference, which is usually the current position in memory, indicated by the prompt. Any printing, writing or analysis commands will be performed at the current offset (address) in the file. For example:

[0x004048c5]> pd 1
    ;-- entry0:
            0x004048c5      31ed           xor ebp, ebp

Disassembles one instruction at address 0x4048c5, which is the entry point for /bin/ls.

Block size

If we do not specify a number of instructions to disassemble, the default block size will be used instead. This can be shown or changed with the command b.

[0x004048c5]> b
0x100
[0x004048c5]> pd
    ;-- entry0:
            0x004048c5      31ed           xor ebp, ebp
            0x004048c7      4989d1         mov r9, rdx
            0x004048ca      5e             pop rsi
            0x004048cb      4889e2         mov rdx, rsp
            0x004048ce      4883e4f0       and rsp, 0xfffffffffffffff0
            0x004048d2      50             push rax
            0x004048d3      54             push rsp
            0x004048d4      49c7c0602541.  mov r8, 0x412560
            0x004048db      48c7c1f02441.  mov rcx, 0x4124f0
            0x004048e2      48c7c7a02840.  mov rdi, 0x4028a0           ; "AWAVAUATUS..H..H...." @ 0x4028a0
            0x004048e9      e802dcffff     call sym.imp.__libc_start_main
            0x004048ee      f4             hlt
            0x004048ef      90             nop
            0x004048f0      b85fc66100     mov eax, 0x61c65f           ; ".interp" @ 0x61c65f
            0x004048f5      55             push rbp
            0x004048f6      482d58c66100   sub rax, 0x61c658
            0x004048fc      4883f80e       cmp rax, 0xe
            0x00404900      4889e5         mov rbp, rsp
        ┌─< 0x00404903      761b           jbe 0x404920
        │   0x00404905      b800000000     mov eax, 0
        │   0x0040490a      4885c0         test rax, rax
       ┌──< 0x0040490d      7411           je 0x404920
       ││   0x0040490f      5d             pop rbp
       ││   0x00404910      bf58c66100     mov edi, 0x61c658           ; "strtab" @ 0x61c658
       ││   0x00404915      ffe0           jmp rax
       ││   0x00404917      660f1f840000.  nop word [rax + rax]
       └└─> 0x00404920      5d             pop rbp
            0x00404921      c3             ret
            0x00404922      66666666662e.  nop word cs:[rax + rax]
        ┌─> 0x00404930      be58c66100     mov esi, 0x61c658           ; "strtab" @ 0x61c658
        │   0x00404935      55             push rbp
        │   0x00404936      4881ee58c661.  sub rsi, 0x61c658
        │   0x0040493d      48c1fe03       sar rsi, 3
        │   0x00404941      4889e5         mov rbp, rsp
        │   0x00404944      4889f0         mov rax, rsi
        │   0x00404947      48c1e83f       shr rax, 0x3f
        │   0x0040494b      4801c6         add rsi, rax
        │   0x0040494e      48d1fe         sar rsi, 1
       ┌──< 0x00404951      7415           je 0x404968
       ││   0x00404953      b800000000     mov eax, 0
       ││   0x00404958      4885c0         test rax, rax
      ┌───< 0x0040495b      740b           je 0x404968
      │││   0x0040495d      5d             pop rbp
      │││   0x0040495e      bf58c66100     mov edi, 0x61c658           ; "strtab" @ 0x61c658
      │││   0x00404963      ffe0           jmp rax
      │││   0x00404965      0f1f00         nop dword [rax]
      └└──> 0x00404968      5d             pop rbp
        │   0x00404969      c3             ret
        │   0x0040496a      660f1f440000   nop word [rax + rax]
        │   0x00404970      803d417d2100.  cmp byte [rip + 0x217d41], 0
       ┌──< 0x00404977      7511           jne 0x40498a
       ││   0x00404979      55             push rbp
       ││   0x0040497a      4889e5         mov rbp, rsp
       ││   0x0040497d      e86effffff     call 0x4048f0
       ││   0x00404982      5d             pop rbp
       ││   0x00404983      c6052e7d2100.  mov byte [rip + 0x217d2e], 1 ; [0x61c6b8:1]=105
       └──> 0x0040498a      f3c3           ret
        │   0x0040498c      0f1f4000       nop dword [rax]
        │   0x00404990      bf00be6100     mov edi, section..jcr       ; section..jcr
        │   0x00404995      48833f00       cmp qword [rdi], 0
       ┌──< 0x00404999      7505           jne 0x4049a0
       │└─< 0x0040499b      eb93           jmp 0x404930
       │    0x0040499d      0f1f00         nop dword [rax]
       └──> 0x004049a0      b800000000     mov eax, 0

@addr - Relative seek

A command can be issued relative to an offset via the use of @, like so:

[0x004048c5]> pd 10 @ main
    ;-- main:
    ;-- section_end..plt:
    ;-- section..text:
            0x004028a0      4157           push r15                    ; [12] va=0x004028a0 pa=0x000028a0 sz=64746 vsz=64746 rwx=--r-x .text
            0x004028a2      4156           push r14
            0x004028a4      4155           push r13
            0x004028a6      4154           push r12
            0x004028a8      55             push rbp
            0x004028a9      53             push rbx
            0x004028aa      89fb           mov ebx, edi
            0x004028ac      4889f5         mov rbp, rsi
            0x004028af      4881ec980300.  sub rsp, 0x398
            0x004028b6      488b3e         mov rdi, qword [rsi]

Addresses, symbolic names and even custom set flags can be used as offsets. This type of operation does not change the current seek.

!size

As we have seen, pd takes an argument specifying the number of instructions to disassemble. This may not be the case with other commands, which will use the default block size for their operation (particularly block writing commands). We may want to fine tune this, but without changing the block size beforehand.

One way to do this is by using !size after the address, as follows:

[0x004048c5]> p8 @ main
4157415641554154555389fb4889f54881ec98030000488b3e64488b042528000000488984248803000031c0e81fb00000be71854100bf06000000e830feffffbe3f514100bf28514100e851faffffbf28514100e807faffffbfc0a14000c705d89c210002000000e863fc000048b80000000000000080c7050fa8210000000000c605a8a821000148890551a921008b05979c210048c70550a921000000000048c7053da92100ffffffffc6059ea821000083f8020f848308000083f803742f83e8017405e8b6f8ffffbf01000000e80cf9ffff85c00f842c0e0000c705caa8210002000000c60563a8210001eb16be0500000031ffc705b0a8210000000000
[0x004048c5]> p8 @ main ! 32
4157415641554154555389fb4889f54881ec98030000488b3e64488b04252800

Notice that the first command will print 256 bytes, while the second one will print 32 bytes.

Times

Like in Vim, commands can be prefixed by a number specifying the number of times you want it to execute. This is very useful when coupled with "repeatable" complex commands.

~grep

Radare2 features an internal grep which is very handy when you want to filter search results or iterate over them in a clever fashion. It can be used by appending a tilde ~ after a command.

For example, i prints out various info about the currently loaded binary.

[0x004048c5]> i
type     EXEC (Executable file)
file     /bin/ls
fd       7
size     0x1ce08
blksz    0x0
mode     -r--
block    0x100
format   elf64
pic      false
canary   true
nx       true
crypto   false
va       true
intrp    /lib64/ld-linux-x86-64.so.2
bintype  elf
class    ELF64
lang     c
arch     x86
bits     64
machine  AMD x86-64 architecture
os       linux
minopsz  1
maxopsz  16
pcalign  0
subsys   linux
endian   little
stripped true
static   false
linenum  false
lsyms    false
relocs   false
rpath    NONE
binsz    119892

But this is a lot to take in. Suppose we want only a few bits of information, such as position independence of code, canary, NX. We can use the internal grep to do this:

[0x004048c5]> i~pic
pic      false
[0x004048c5]> i~canary
canary   true
[0x004048c5]> i~nx
nx       true

:Row/[column] selection

Some commands output their result in table form. Rows and columns can be selected as follows:

[0x004048c5]> drr
   rax 0x0000000000000000  section_end.GNU_STACK
   rbx 0x0000000000000000  section_end.GNU_STACK
   rcx 0x0000000000000000  section_end.GNU_STACK
   rdx 0x0000000000000000  section_end.GNU_STACK
   rsi 0x0000000000000000  section_end.GNU_STACK
   rdi 0x0000000000000000  section_end.GNU_STACK
    r8 0x0000000000000000  section_end.GNU_STACK
    r9 0x0000000000000000  section_end.GNU_STACK
   r10 0x0000000000000000  section_end.GNU_STACK
   r11 0x0000000000000000  section_end.GNU_STACK
   r12 0x0000000000000000  section_end.GNU_STACK
   r13 0x0000000000000000  section_end.GNU_STACK
   r14 0x0000000000000000  section_end.GNU_STACK
   r15 0x0000000000000000  section_end.GNU_STACK
   rip 0x0000000000000000  section_end.GNU_STACK
   rbp 0x0000000000000000  section_end.GNU_STACK
rflags 0x0000000000000000  section_end.GNU_STACK
   rsp 0x0000000000000000  section_end.GNU_STACK

A particular column can be selected by using [NUM]

[0x004048c5]> drr~[0]
rax
rbx
rcx
rdx
rsi
rdi
r8
r9
r10
r11
r12
r13
r14
r15
rip
rbp
rflags
rsp

And a row can be selected by using :NUM

[0x004048c5]> drr~:5
   rdi 0x0000000000000000  section_end.GNU_STACK

The two can also be combined:

[0x004048c5]> drr~:5[0]
rdi

|Pipes and >redirection

Commands can be piped over to external processing tools such as tr, awk, sed, cut, grep and so on.

[0x004048c5]> pd 10 | tr -s ' ' | cut -d ' ' -f 4 | tail -n +2
xor
mov
pop
mov
and
push
push
mov
mov
mov

The output of most commands can be redirected to a file.

[0x004048c5]> pcp > demo.py

@@Iteration

A very powerful feature of radare2 is the ability to run a command over multiple points in a binary. This is useful when you tag a series of points which require the same patch and then patching them all in one swoop.

The simple example below prints the first 4 bytes of every function.

[0x004048c5]> p8 4 @@ fcn.*

Some commands will automatically add flags which can be iterated over. For example:

[0x004048c5]> / err
Searching 3 bytes from 0x00400000 to 0x0061d480: 65 72 72
Searching 3 bytes in [0x400000-0x61d480]
hits: 6
0x00401094 hit0_0 "err"
0x0040117f hit0_1 "err"
0x0040124d hit0_2 "err"
0x00416137 hit0_3 "err"
0x00417470 hit0_4 "err"
0x00417695 hit0_5 "err"
[0x004048c5]> pd 5 @@ hit0_*

We first look through the binary for 'err'. This results in flags being set at every corresponding 'hit' points. We can then iterate over these 'hits' and further process them.

Other commands

Quick conversions can be performed via the use of ?

[0x004048c5]> ? 1234
1234 0x4d2 02322 1.2K 0000:04d2 1234 11010010 1234.0 0.000000f 0.000000

Other useful commands can be found using ???

[0x004048c5]> ???
|Usage: ?[?[?]] expression
| ? eip-0x804800     show hex and dec result for this math expr
| ?:                 list core cmd plugins
| ?! [cmd]           ? != 0
| ?+ [cmd]           ? > 0
| ?- [cmd]           ? < 0
| ?= eip-0x804800    hex and dec result for this math expr
| ??                 show value of operation
| ?? [cmd]           ? == 0 run command when math matches
| ?B [elem]          show range boundaries like 'e?search.in
| ?P paddr           get virtual address for given physical one
| ?S addr            return section name of given address
| ?V                 show library version of r_core
| ?X num|expr        returns the hexadecimal value numeric expr
| ?_ hudfile         load hud menu with given file
| ?b [num]           show binary value of number
| ?b64[-] [str]      encode/decode in base64
| ?d[.] opcode       describe opcode for asm.arch
| ?e string          echo string
| ?f [num] [str]     map each bit of the number as flag string index
| ?h [str]           calculate hash for given string
| ?i[ynmkp] arg      prompt for number or Yes,No,Msg,Key,Path and store in $$?
| ?ik                press any key input dialog
| ?im message        show message centered in screen
| ?in prompt         noyes input prompt
| ?iy prompt         yesno input prompt
| ?l str             returns the length of string
| ?o num             get octal value
| ?p vaddr           get physical address for given virtual address
| ?r [from] [to]     generate random number between from-to
| ?s from to step    sequence of numbers from to by steps
| ?t cmd             returns the time to run a command
| ?u num             get value in human units (KB, MB, GB, TB)
| ?v eip-0x804800    show hex value of math expr
| ?vi rsp-rbp        show decimal value of math expr
| ?x num|str|-hexst  returns the hexpair of number or string
| ?y [str]           show contents of yank buffer, or set with string

results matching ""

    No results matching ""