Update (2016-11-01): The Radare2 creator has informed me that all of the issues I mention below have been fixed.
Note carefully the date this was published. It’s entirely possible that all of the problems I mention below have long since been fixed.
I’ve spent a fair bit of time reverse engineering firmware using IDA. I have never been completely happy with IDA. It improved dramatically with the new UI and Python bindings, but I think it has been hampered by early design decisions. (To name but one, it’s impossible for a segment to be not 16-byte aligned which is a hold-over from the Intel 8086. The 34 year old Intel 80286 introduced protected mode which supports arbitrary segment alignment and IDA just cannot handle it.) Still, I’ve been moderately successful reverse engineering firmware for a wide variety of processor architectures using IDA. Unfortunately, IDA is expensive. Like, really, really expensive.
Several competing tools have recently become popular. Yesterday, I gave radare2 a spin for the first time. I started by reading through the Radare2 Book. Almost immediately, I noticed some odd design choices. For example, the rax2
tool has a very unintuitive (to me) interface.
But any new tool is going to take some time to learn, so I pressed on. I compiled and installed the main radare2 binaries. As a first test, I ran r2 /usr/bin/true
and entered visual mode with the V
command.
So far so good! Since radare2 uses vim-esque movement key bindings (hjkl), I scrolled around a little bit but almost immediately noticed something odd. After scrolling down once (j) and then back up once (k), I’d expect to see the same thing as before, but instead, I get this.
So it scrolled a little too far, but wait, what’s that call qword [rbp + 0x48]
? Apparently, it decided to move the ff
byte that preceded main
into main, thus changing the disassembly! In fact, scrolling right or left, changes the offset of the start of the disassembly. As near as I can tell, left decrements the offset by one, right increments it by one, up decrements it by four, and down increments it by the size of the instruction. I can imagine why one might want similar functionality, but it’s surprising for it to be the default.
After performing some code analysis (command aa
), this behavior disappears and up and down scroll by an instruction. Left and right keep their behavior.
Next up: visual panel mode (command !
in visual mode). This seems neat (although the arrows don’t seem to respect the UTF-8 setting.) Unfortunately, this mode seems very buggy. For example, immediately after opening the visual panel mode, opening the File
menu and selecting Close
twice causes r2
to segfault. I’ve managed other segfaults in this mode, but I’m not entirely sure what caused them. This reminds me a lot of GDB’s Text User Interface (TUI) mode which crashes essentially every time I use it.
After performing analyses which can take some time, renaming functions, or adding comments, it’d be great to be able to save my work and come back to it. Radare2 has a notion of a project. The P
command can open and save projects.
[0x100000f33]> P?
|Usage: P[?osi] [file]Project management
| Pc [file] show project script to console
| Pd [file] delete project
| Pi [file] show project information
| Pl list all projects
| Pn[j] show project notes (Pnj for json)
| Pn [base64] set notes text
| Pn - edit notes with cfg.editor
| Po [file] open project
| Ps [file] save project
| PS [file] save script file
| NOTE: See 'e??prj.'
| NOTE: project are stored in ~/.config/radare2/projects
So let’s give that a shot. First, I’ll run r2 /usr/bin/true
again, run aa
, and then save the project.
[0x100000f33]> aa
[x] Analyze all flags starting with sym. and entry0 (aa)
[0x100000f33]> Ps true
true
This creates a ~/.config/radare2/projects/true
directory containing two files.
$ ls -l ~/.config/radare2/projects/true
total 68
-rw-r--r-- 1 steve staff 64653 Oct 29 14:26 rc
-rw-r--r-- 1 steve staff 1393 Oct 29 14:26 xrefs
So far so good. Now that I’ve saved a project, I should be able to see it in the list of projects using the Pl
command.
[0x100000f33]> Pl
[0x100000f33]> Pl?
[0x100000f33]>
I guess not? Okay, I’ll try seeking one byte forward, just to change the state a little and then reopen the project.
[0x100000f33]> s +1
[0x100000f34]> Po true
Close current session? (Y/n)
[0x100000f33]>
Okay, that seems good. Since I performed the aa
before saving the project, surely, that information has been saved, right? No, no it wasn’t. I have no idea why. That seems like pretty essential information to save.
Using the -p
command line flag, we can open a project. That seems handy. As a final project management test, I’ll open a project with -p
, ask for a list of projects and then quit and save.
$ r2 -p true
[0x100000f31]> Pl
[0x100000f31]> q
Do you want to save the 'true' project? (Y/n)
r_sys_mkdirp: fail '/Users/steve/.config/radare2/projects/true/rc/rop' of '/Users/steve/.config/radare2/projects/true/rc/rop'
sdb: Cannot open '/Users/steve/.config/radare2/projects/true/rc/rop/nop.tmp' for writing.
r_sys_mkdirp: fail '/Users/steve/.config/radare2/projects/true/rc/rop' of '/Users/steve/.config/radare2/projects/true/rc/rop'
sdb: Cannot open '/Users/steve/.config/radare2/projects/true/rc/rop/mov.tmp' for writing.
r_sys_mkdirp: fail '/Users/steve/.config/radare2/projects/true/rc/rop' of '/Users/steve/.config/radare2/projects/true/rc/rop'
sdb: Cannot open '/Users/steve/.config/radare2/projects/true/rc/rop/const.tmp' for writing.
r_sys_mkdirp: fail '/Users/steve/.config/radare2/projects/true/rc/rop' of '/Users/steve/.config/radare2/projects/true/rc/rop'
sdb: Cannot open '/Users/steve/.config/radare2/projects/true/rc/rop/arithm.tmp' for writing.
r_sys_mkdirp: fail '/Users/steve/.config/radare2/projects/true/rc/rop' of '/Users/steve/.config/radare2/projects/true/rc/rop'
sdb: Cannot open '/Users/steve/.config/radare2/projects/true/rc/rop/arithm_ct.tmp' for writing.
Since rc
is a file, not a directory, saving is failing. I have no idea why. Opening a project using Po
and then saving has the same behavior. I guess projects aren’t usable.
Finally, I took a look at a little bit of the broader radare2 ecosystem. Radare2 comes with a package manager r2pm
which can install packages. First up, the webui packages. Following the directions, I tried to install www-m
.
$ r2pm -i www-m
Processing www-m ...
Already up-to-date.
Install Done For www-m
make -C www/m build
...
/Users/steve/.config/radare2/r2pm/db/www-m: line 11: cd: dist/m: No such file or directory
So that didn’t work. What about the Python-GTK UI, Bokken?
$ r2pm -i bokken
Processing bokken ...
...
Install Done For bokken
abort: error: Connection refused
sys/bokken.sh: line 14: cd: bokken: No such file or directory
So r2pm installed it, but then failed twice. Since r2pm -l
claims Bokken is installed, but the installation clearly failed, let’s try removing it.
$ r2pm -u bokken
Processing bokken ...
Already up-to-date.
Uninstall Done For bokken
Sorry. This package cannot be uninstalled
Maybe the package manager isn’t up to date.
$ r2pm update
Already up-to-date.
r2pm database initialized. Use 'r2pm update' to update
Why does the update command tell me to run update?
Okay, final thing. IDA can decompile binaries for several architectures into C (assuming you’ve shelled out even more money for the decompiler). Radare2 has a package that can do that, although I understand it’s still a work in progress. Still, this could be a nice, free alternative.
I’ll spare you the hundreds of lines of errors that result from running r2pm -i radeco
.
In summary, I had a pretty frustrating day playing with radare2. It seems like it could be a nice alternative to spending thousands of dollars on IDA, but as far as I can tell, it’s currently buggy and unusable.