# 22.2.1 Level 0x00 - strings, change a jump

Let's run the crackme:

     $ ./crackme0x00
     IOLI Crackme Level 0x00
     Password: foo
     Invalid Password!

As we can see, the goal is to patch the binary file to accept any password.

We're now going to inspect the strings on the binary, normally you would use the unix strings command to do such task, but we can also use radare:

     $ rabin -z crackme0x00
     0x00000154 A /lib/ld-linux.so.2
     0x00000249 A __gmon_start__
     0x00000258 A libc.so.6
     0x00000262 A printf
     0x00000269 A strcmp
     0x00000270 A scanf
     0x00000276 A _IO_stdin_used
     0x00000285 A __libc_start_main
     0x00000297 A GLIBC_2.0
     0x00000568 A IOLI Crackme Level 0x00
     0x00000581 A Password:
     0x0000058f A 250382
     0x00000596 A Invalid Password!
     0x000005a9 A Password OK :)
     [...]

With -S[len] radare prints sequences of characters that are at least len characters long, in the example we used 5. As you can see, radare prints the offset within the file before each string, and an A or U indicating whether it is either a Ascii or Unicode string.

At offset 0x0000058f we can see an ascii string which looks suspicious, let's try it as password -- this is level 0 by the way, so it should be that easy ;)

     $ ./crackme0x00
     IOLI Crackme Level 0x00
     Password: 250382
     Password OK :)

Yay! we found it, it was really that easy, but now we want to patch the binary to accept any password, so let's disassemble it with radare:

     $ radare crackme0x00
     open ro crackme0x00
     Adding strings & symbol flags for crackme0x00
     7 strings added.
     15 symbols added.
     [0x08048360]>

As you can see, the strings and symbols have been flagged automatically for us, also the seek has been changed to the entry point (0x08048360). The prompt always shows the current seek (position on the file, rebased to virtual memory address).

We can dump the flags, to see what has been flagged:

     [0x08048360]> flag
     000 0x00000360 512 entrypoint
     002 0x000002f8 512 sym._init
     003 0x00000320 512 sym.__libc_start_main
     004 0x00000330 512 sym.scanf
     005 0x00000340 512 sym.printf
     006 0x00000350 512 sym.strcmp
     007 0x00000360 512 sym._start
     008 0x000003b0 512 sym.__do_global_dtors_aux
     009 0x000003e0 512 sym.frame_dummy
     010 0x00000414 512 sym.main
     011 0x000004a0 512 sym.__libc_csu_init
     012 0x00000510 512 sym.__libc_csu_fini
     013 0x00000515 512 sym.__i686.get_pc_thunk.bx
     014 0x00000520 512 sym.__do_global_ctors_aux
     015 0x00000544 512 sym._fini
     016 0x08048368 512 "PTRh"
     017 0x08048568 512 "IOLI.Crackme.Level.0x00"
     018 0x08048581 512 "Password:."
     019 0x0804858f 512 "250382"
     020 0x08048596 512 "Invalid.Password!"
     021 0x080485a9 512 "Password.OK.:)"
     022 0x0804858c 512 "%
     [0x08048360]>

Now we can print a disassembly of the main() function, to do this we will change the seek to the position of sym.main and use the "pD" command to print disassembly:

     [0x08048360]> s sym.main
     [0x08048414]> pd

TODO: http://radare.nopcode.org/img/wk/crackme0x00_pD_sym.main.png

For example, to print a disassembly of 126 bytes starting at position sym.main, we would do:

If we just type pd, it will print the disassembly from the current seek until the end of the block.

Now let's print a code graph of the main() function, as our current seek is sym.main, we just type "ag":

TODO: Add graph in ascii art here TODO: http://radare.nopcode.org/img/wk/crackme0x00-sym.main.png

Now let's do the real work here...

If we look at the disassembly we can see, it calls printf() and scanf() to ask for the password, then it calls strcmp() to compare the string we've entered with the hardcoded string "250382". Now look at the graph, you can see it branches into two blocks of code, depending on the result of the string comparison.

If the password is correct the code will follow the green line, and the program will print "Password OK :)", otherwise the code will follow the red line and print "Invalid Password!". We have to patch the "jz" (jump if zero) to make the code always jump to the right block. To do this, we just change "jz" for "jmp". We will now patch the binary using radare:

First we change the current seek to the position of the instruction we want to patch:

     [0x08048414]> s 0x8048470
     [0x08048470]>

Now we can print the instruction in this position, for example we will print 15 bytes at the current seek:

     [0x08048470]> pD 15
     0x08048470 740e                    v jz 0x480   ; sym.main+0x6c
     ; ------------------------------------
     0x08048472 c7042496850408            dword [esp] = 0x8048596 ; "Invalid.Password!"
     0x08048479 e8c2feffff              ^ call 0x340  ; sym.printf
     ; ------------------------------------
     0x0804847E eb0c                    v goto 0x48C   ; sym.main+0x78
     ; ------------------------------------
     [0x08048470]>

Here, the instruction 'jz 0x480' corresponds to the bytes '740e', if we change the '74' for an 'eb' we will change the 'jz' for 'goto' (or jmp). You can see the 'eb' is used for goto in the last instruction of the disassembly we've just printed.

To write 'eb' in the current seek we must open the file in write mode (by default radare opens everything in read-only mode). To switch to write mode we can type:

     [0x08048470]> eval cfg.write=true
     warning: Opening file in read-write mode
     open rw crackme0x00
     [0x08048470]>

And now we're ready to patch, just use the 'wx' command to write hex values and 'px' to print the result:

     [0x08048470]> wx eb
     [0x08048470]> px 20
        offset   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0 1  2 3  4 5 0123456789ABCDEF012345
     .--------+-------------------------------------------------------+-----------------------
     0x08048470 eb0e c704 2496 8504 08e8 c2fe ffff eb0c c704 24a9      ....$.............$.
     [0x08048470]>

Now let's see the disassembly again, to see everything was patched as we expected:

     [0x08048470]> pD 15
     0x08048470 eb0e                    v goto 0x480   ; sym.main+0x6c
     ; ------------------------------------
     0x08048472 c7042496850408            dword [esp] = 0x8048596 ; "Invalid.Password!"
     0x08048479 e8c2feffff              ^ call 0x340  ; sym.printf
     ; ------------------------------------
     0x0804847E eb0c                    v goto 0x48C   ; sym.main+0x78
     ; ------------------------------------
     [0x08048470]>

And let's graph it again using the PG command, to see the code will flow only through the "Password OK" branch:

     [0x08048470]> s sym.main
     [0x08048414]> ag

TODO: Add ascii-art disassembly here

Finally just press 'q' to quit radare, and try the cracked program:

     $ ./crackme0x00
     IOLI Crackme Level 0x00
     Password: foo
     Password OK :)

Done! :D