This post is about the basis of binary cracking; the input is a toy program asking for a password string and behaving accordingly. The goal is to change the binary so that the password check is always successful.
We use radare2 which is a console-based powerful hexadecimal editor under steroids. Among its numerous features:
- disassemble/assemble binaries
- conversion among base 16,2 and 10 numbers and c structures
- program debugging
We crack the toy programs available online at a basis of other radare related posts.
radare2 is available on *buntu repositories as well on github
#> apt install radare2
Picking the executable called crackme0x00a, we launch radare2
and we enter the console. The help can be shown with the command ‘?’, all the other commands start with a meaningful character
- ‘a’: stands for analyse
- ‘o’: stands for open
- ’s’: stands for seek (change to binary address)
- ‘p’: stands for print
The majority of command supports the postposition of the character ‘?’ for printing the related information.
We launch the command
which performs a complete symbol analysis (analyse all).
If we now launch
[0x08048430]> pdf @ sym.main
We have a print of the disassembled code pointing at the function (pdf print, disassemble at function ..) main() of the program, something similar to the following:
0x0804852f 85c0 test eax, eax 0x08048531 7521 jnz 0x8048554 0x08048533 c7042454860. mov dword [esp], str.Congrats 0x0804853a e8b1feffff call 0x1080483f0 ; (sym.imp.puts) sym.imp.puts() 0x0804853f 90 nop 0x08048540 b800000000 mov eax, 0x0 0x08048545 8b54242c mov edx, [esp+0x2c] 0x08048549 65331514000. xor edx, [gs:0x14] 0x08048550 7415 jz 0x8048567 ; CODE (CALL) XREF from 0x08048562 (fcn.080484e3) 0x08048552 eb0e jmp loc.08048562 0x08048554 c704245e860. mov dword [esp], str.Wrong
As we can see, at address 0x0804852f there is a test for which we have a conditional jump at 0x08048531, meaning that, if the test is successful, we deal with the string str.Congrats, while if it fails we jump to the code related to str.Wrong.
Changing the course of events
We could try to infer the correct password, given it is hardcoded but I prefer to just rewrite few bytes and solve the problem definitely.
By default, files are open in read-only mode, to make it writable:
We now move to the conditional jump address with:
[0x08048430]> s 0x08048531
The jump instruction comprises of the code 0x7521 which we can override with a couple of innocent no-operation instructions (0x9090)
[0x08048531]> wx 9090
As we overrided the jump instructions with the nops, now the binary execution flow goes directly to the correct password part, completely ignoring the check result (which is still performed) and we can successfully exit