Reverse Engineering With Radare2 – Intro

As some of you may know, there is a “new” reverse engineering toolkit out there which tries to compete with IDA Pro in terms of reverse engineering. I’m talking about radare2, a framework for reversing, patching, debugging and exploiting.

It has large scripting capabilities, runs on all major plattforms (Android, GNU/Linux, [Net|Free|Open]BSD, iOS, OSX, QNX, w32, w64, Solaris, Haiku, FirefoxOS and even on your pebble smartwatch 😉 ) and is free.

Sadly, I had some problems finding good tutorials on how to use it, as the interface is currently a bit cumbersome. After fiddling around, I’ve decided to create a little tutorial series where we can learn together ;).

I will publish one binary per post and you will have time to reverse it till the next blog post is published (most of the time you have to find which data you have to enter to make the binary happy).

So let’s start 🙂


The most advisable way is to use the most current version from the github repository:

(As taken from the README:)

The easiest way to install radare2 from git is by running the following command:

$ sys/

If you want to install radare2 in the home directory without using root privileges and sudo, simply run:

$ sys/


If everything goes well, you’ll find multiple tools in your path:

  • r2 – the “main” binary
  • rabin2 – binary to analyze files (list imports, exports, strings, …)
  • rax2 – binary to convert between data formats
  • radiff2 – binary to do some diffing
  • rahash2 – creates hashes from file blocks (and whole file)
  • rasm2 – helps to play with assembler instructions

The default interface for radare2 is the command line. Just type

r2 your_binary

to start it. Radare has a very shortened command syntax (it is always logical, but in my opinion a few more characters wouldn’t hurt). So to start the analysis of your file, type aa (for analyze all; use aaa or aaaa to run even more analysis algorithms). Did you already get the idea behind the commands? Radare uses a tree structure like name of the commands so all commands which corresponds to analyzing something start with a. If you want to print something you have to use…. p. For example disassemble the current function: pdf (print disassembly function).

As no human could remember all available commands in radare (there are many of them), the ? character is used to display context sensitive help text. A single ? shows you which command categories are available and some general help about specifying addresses and data. A p? shows you the help about the different print commands, pd? which commands are available for printing disassemblies of different sources, etc.

An important command to walk through your targets is the seek command. By using

s sym.main

you’ll jumping into the main function (as long as you’d analyzed the binary in the first step and symbols are available). The following shows you the output of the pdf command after seeking to the main function of the /bin/true binary.

            ;-- section_end..plt:
            ;-- section..text:
/ (fcn) main 160
|           ; DATA XREF from 0x0040142d (main)
|           0x00401370      83ff02         cmp edi, 2                  ; [12] va=0x00401370 pa=0x00001370 sz=11465 vsz=11465 rwx=--r-x .text
|       ,=< 0x00401373      7403           je 0x401378                
|       |   0x00401375      31c0           xor eax, eax
|       |   0x00401377      c3             ret
|       `-> 0x00401378      53             push rbx
|           0x00401379      488b3e         mov rdi, qword [rsi]
|           0x0040137c      4889f3         mov rbx, rsi
|           0x0040137f      e84c050000     call fcn.004018d0
|           0x00401384      be6d404000     mov esi, 0x40406d
|           0x00401389      bf06000000     mov edi, 6
|           0x0040138e      e81dffffff     call sym.imp.setlocale
|           0x00401393      bef6404000     mov esi, str._usr_share_locale ; "/usr/share/locale" @ 0x4040f6
|           0x00401398      bfe8404000     mov edi, 0x4040e8           ; "coreutils" @ 0x4040e8
|           0x0040139d      e86efdffff     call sym.imp.bindtextdomain
|           0x004013a2      bfe8404000     mov edi, 0x4040e8           ; "coreutils" @ 0x4040e8
|           0x004013a7      e844fdffff     call sym.imp.textdomain
|           0x004013ac      bf20184000     mov edi, 0x401820
|           0x004013b1      e85a2c0000     call fcn.00404010
|           0x004013b6      488b5b08       mov rbx, qword [rbx + 8]    ; [0x8:8]=0
|           0x004013ba      be08414000     mov esi, str.__help         ; "--help" @ 0x404108
|           0x004013bf      4889df         mov rdi, rbx
|           0x004013c2      e839feffff     call sym.imp.strcmp
|           0x004013c7      85c0           test eax, eax
|       ,=< 0x004013c9      743b           je 0x401406                
|       |   0x004013cb      be0f414000     mov esi, str.__version      ; "--version" @ 0x40410f
|       |   0x004013d0      4889df         mov rdi, rbx
|       |   0x004013d3      e828feffff     call sym.imp.strcmp
|       |   0x004013d8      85c0           test eax, eax
|      ,==< 0x004013da      7526           jne 0x401402               
|      ||   0x004013dc      488b0dcd4d20.  mov rcx, qword [rip + 0x204dcd] ; [0x6061b0:8]=0x404383 str.8.25
|      ||   0x004013e3      488b3d3e4e20.  mov rdi, qword [rip + 0x204e3e] ; [0x606228:8]=0x2029554e4728203a  LEA obj.stdout ; ": (GNU) 5.3.0" @ 0x606228
|      ||   0x004013ea      4531c9         xor r9d, r9d
|      ||   0x004013ed      41b819414000   mov r8d, str.Jim_Meyering   ; "Jim Meyering" @ 0x404119
|      ||   0x004013f3      bae4404000     mov edx, str.GNU_coreutils  ; "GNU coreutils" @ 0x4040e4
|      ||   0x004013f8      be64404000     mov esi, str.true           ; "true" @ 0x404064
|      ||   0x004013fd      e86e220000     call fcn.00403670
|      `--> 0x00401402      31c0           xor eax, eax
|       |   0x00401404      5b             pop rbx
|       |   0x00401405      c3             ret
|       `-> 0x00401406      31ff           xor edi, edi
|           0x00401408      e803010000     call fcn.00401510
\           0x0040140d      0f1f00         nop dword [rax]

Nearly all radare commands which operates on addresses (like disassmble) allow to use an argument to specify a different position instead of the current one by using an @. Therefore a

pdf @sym.main

produces the same result. You like the tree view of IDA? Enter the visual mode of radare by entering V. Now you see an hexeditor were you can navigate through. By typing ?, you’ll get a list of possible keyshortcuts for this mode. Press V (capital v) to get this:

Graph view of /bin/true
Graph view of /bin/true

Awesome, isn’t it? Now let’s rename the function fcn.00401510 in our disassembly to a more meaningful name. This could either be done by

s fcn.00401510

afn better_name

Or by using

afn better_name fcn.00401510


afn better_name 0x00401510


afn better_name @fcn.00401510


afn better_name @0x00401510


If you’re a little afraid of this huge amount of command line fu, you could also try the webinterface:

r2 -c=H your_binary

Which gets you this:

Radare 2 Web interface

Challenge 0x01

You will find the first challenge here (linux64 dynamically linked, linux64 statically linked, win64):

MD5 (challenge01) = b6449993d4278f9884f45018fc128d15
MD5 (challenge01.exe) = 1d78ad3807163cfb7b5194c1c22308c4
MD5 (challenge01-static) = 833cdfe2b105dfda82d3d4a28bab04bd
SHA1 (challenge01) = 55d7755be8ea872601e2c22172c8beccefca37cc
SHA1 (challenge01.exe) = 108837eeffb6635aa08e0d5607ba4d502d556f32
SHA1 (challenge01-static) = 2ad83f289e94c3326d3729fc2c04f32582aba8a3
SHA256 (challenge01) = 56f239d74bdafd8c2d27c07dff9c66dc92780a4742882b9b8724bce7cc6fb0d1
SHA256 (challenge01.exe) = 9ef57cbd343489317bef66de436ebe7544760b48414ca2247ced1ce462b4591d
SHA256 (challenge01-static) = 99f15536cc8a4a68e6211c3af6a0b327c875373659bf7100363319e168c0deb7


Your goal is to find the correct password for the login in the binary (hint: hardcoded passwords are bad) . Next time I’ll give you a walkthrough for the challenge and challenge #2.

Happy reversing!





Comments are closed.