Cracking 101

November 01, 2017

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.

Installation

radare2 is available on *buntu repositories as well on github

#> apt install radare2

Observing

Picking the executable called crackme0x00a, we launch radare2

$>r2 crackme0x00a

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

[0x08048430]> aa

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:

[0x08048430]> oo+

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

[0x08048531]> q