Still Learning to Use Tools: Radare2

This post is going to continue with learning how to use Radare2 via the IOLI crackmes.  Last time was more about one of the included tools, Rabin2.  Again this is all from the Radare2 book, I’m just trying to fill in some gaps that I felt could be more pedantic for those new to reverse engineering and get the hang of r2 myself.

Lets Get Started:

 $ rabin2 -I crackme0x01
havecode true
pic      false
canary   false
nx       true
crypto   false
va       true
intrp    /lib/
bintype  elf
class    ELF32
lang     c
arch     x86
bits     32
machine  Intel 80386
os       linux
minopsz  1
maxopsz  16
pcalign  0
subsys   linux
endian   little
stripped false
static   false
linenum  true
lsyms    true
relocs   true
rpath    NONE
binsz    7499

Getting the information about the crackme0x01 from rabin2 we learn the following about it:

The code is included with the file again and it’s written in C and it’s a 32-bit ELF executable.

Lets see what the imports tell us about this file:

 $ rabin2 -i crackme0x01
ordinal=001 plt=0xffffffff bind=UNKNOWN type=NOTYPE name=__gmon_start__
ordinal=002 plt=0x080482fc bind=GLOBAL type=FUNC name=__libc_start_main
ordinal=003 plt=0x0804830c bind=GLOBAL type=FUNC name=scanf
ordinal=004 plt=0x0804831c bind=GLOBAL type=FUNC name=printf

4 imports

This time scanf and printf functions are imported but conspicuously missing is the strcmp function from crackme0x00.  That doesn’t look good for being able to determine the password just by looking at the strings.

Lets take a look at the strings:

 $ rabin2 -z crackme0x01
vaddr=0x08048528 paddr=0x00000528 ordinal=000 sz=25 len=24 section=.rodata type=ascii 
string=IOLI Crackme Level 0x01\n
vaddr=0x08048541 paddr=0x00000541 ordinal=001 sz=11 len=10 section=.rodata type=ascii 
vaddr=0x0804854f paddr=0x0000054f ordinal=002 sz=19 len=18 section=.rodata type=ascii 
string=Invalid Password!\n
vaddr=0x08048562 paddr=0x00000562 ordinal=003 sz=16 len=15 section=.rodata type=ascii 
string=Password OK :)\n

There unfortunately isn’t a string standing out as a password to attempt.  But we see that the functionality is just requesting a password and telling us if it’s correct or not.  Running the program has the expected output.

 $ ./crackme0x01
IOLI Crackme Level 0x01
Password: test
Invalid Password!

No surprises there.  Note that if you’re running a 64-bit system you need to make it so 32-bit executables con run before you can run any of the crackmes.

Lets Do Some Disassembly (Disassembling?):

First things first we are looking for some way of comparing a password.  Since we are moving to disassembly we are looking for some way of comparing things in disassembly.  That means we are going to be looking for some kind of comparison instruction.

There’s a few ways of comparing things in assembly.  We coul have a subtraction and check if the value is zero executing a jump instruction on the result.  Or we could use an explicite compare instruction.  An indicator of what we want should be a jump after the instruction to the correct print string instruction.

 [0x08048330]> pdf@main
            ;-- main:
/ (fcn) sym.main 113
|   sym.main ();
|           ; var int local_4h @ ebp-0x4
|           ; var int local_4h_2 @ esp+0x4
|           ; JMP XREF from 0x08048347 (entry0)
|           ; DATA XREF from 0x08048347 (entry0)
|           0x080483e4      55             push ebp
|           0x080483e5      89e5           mov ebp, esp
|           0x080483e7      83ec18         sub esp, 0x18
|           0x080483ea      83e4f0         and esp, 0xfffffff0
|           0x080483ed      b800000000     mov eax, 0
|           0x080483f2      83c00f         add eax, 0xf
|           0x080483f5      83c00f         add eax, 0xf
|           0x080483f8      c1e804         shr eax, 4
|           0x080483fb      c1e004         shl eax, 4
|           0x080483fe      29c4           sub esp, eax
|           0x08048400      c70424288504.  mov dword [esp], str.IOLI_Crackme_Level_0x01_n ; [0x8048528:4]=0x494c4f49 LEA str.IOLI_Crackme_Level_0x01_n ; "IOLI Crackme Level 0x01." @ 0x8048528
|           0x08048407      e810ffffff     call sym.imp.printf        ; int printf(const char *format);
|           0x0804840c      c70424418504.  mov dword [esp], str.Password: ; [0x8048541:4]=0x73736150 LEA str.Password: ; "Password: " @ 0x8048541
|           0x08048413      e804ffffff     call sym.imp.printf        ; int printf(const char *format);
|           0x08048418      8d45fc         lea eax, dword [ebp - local_4h]
|           0x0804841b      89442404       mov dword [esp + local_4h_2], eax
|           0x0804841f      c704244c8504.  mov dword [esp], 0x804854c  ; [0x804854c:4]=0x49006425 ; "%d"
|           0x08048426      e8e1feffff     call sym.imp.scanf         ; int scanf(const char *format);
|           0x0804842b      817dfc9a1400.  cmp dword [ebp - local_4h], 0x149a ; [0x149a:4]=0x2ec0804
|       ,=< 0x08048432      740e           je 0x8048442
|       |   0x08048434      c704244f8504.  mov dword [esp], str.Invalid_Password__n ; [0x804854f:4]=0x61766e49 LEA str.Invalid_Password__n ; "Invalid Password!." @ 0x804854f
|       |   0x0804843b      e8dcfeffff     call sym.imp.printf        ; int printf(const char *format);
|      ,==< 0x08048440      eb0c           jmp 0x804844e |      |`-> 0x08048442      c70424628504.  mov dword [esp], str.Password_OK_:__n ; [0x8048562:4]=0x73736150 LEA str.Password_OK_:__n ; "Password OK :)." @ 0x8048562
|      |    0x08048449      e8cefeffff     call sym.imp.printf        ; int printf(const char *format);
|      |    ; JMP XREF from 0x08048440 (sym.main)
|      `--> 0x0804844e      b800000000     mov eax, 0
|           0x08048453      c9             leave
\           0x08048454      c3             ret
[0x08048330]> ? 0x149a
5274 0x149a 012232 5.2K 0000:049a 5274 "\x9a\x14" 0001010010011010 5274.0 5274.000000f 

Unfortunately the output doesn’t fit nicely on the screen, but I’m going to leave it in that format.  If I change the format it’s harder to see where the instructions lead.

The bold instructions are the one’s that are interesting.  The cmp instruction compares two things, in this case a value in memory located at esp – local_4h and the hex value 0x149a.  The next instruction jumps to the instruction at 0x8048442 if the values are equal for cmp.  The instruction at 0x8048442 is to load the string Password_OK and print it.  So we want to make this compare instruction take the following jump.

We can try to just input the value 0x149a  and see what happens.

 $ ./crackme0x01
IOLI Crackme Level 0x01
Password: 0x149a
Invalid Password!

No luck.  The next thing to try is to convert the number to a binary representation.  We can do that with the r2 functionality as well.

 ? 0x149a
5274 0x149a 012232 5.2K 0000:049a 5274 "\x9a\x14" 0001010010011010 5274.0 5274.000000f 

The decimal version is 5274.  So we can try that and see what happens.

 $ ./crackme0x01
IOLI Crackme Level 0x01
Password: 5274
Password OK :)

That’s the answer.


That was a nice intro to using some basic disassembler functionality.  We also got a nice peek at some assembly code to figure out the password from.  This was a pretty simplistic example but we need to start looking at a lot of assembly code and determining functionality.  There will be a lot of that coming in the future.  Possibly some assembly programs as well.



Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s