blog: Dipping toes into radare2

While procrastinating, I recently stumbled upon an article about a simple crackme challenge. The challenge was to create a program that would generate semi-random password strings that would pass the program's "checksum" function. I see the educational purpose in this challenge, but I asked myself "why not just change the program to accept any password?", which would probably be a more common use case.

Radare2 had surfaced a few times in my twitter feed, so this seemed like the right time to do my first itty-bitty steps with it. And surely enough, this was dead simple:

Open the file in r2 and analyze all flags

% r2 101-crackme
[0x00400470]> aa
[x] Analyze all flags starting with sym. and entry0 (aa)

Print the disassembly of the main function

[0x00400470]> pdf @ main
            ;-- main:
/ (fcn) sym.main 120
|   sym.main ();
|           ; var int local_20h @ rbp-0x20
|           ; var int local_14h @ rbp-0x14
|           ; var int local_8h @ rbp-0x8
|           ; DATA XREF from 0x0040048d (entry0)
|           0x0040059d      55             push rbp
|           0x0040059e      4889e5         mov rbp, rsp
|           0x004005a1      4883ec20       sub rsp, 0x20
|           0x004005a5      897dec         mov dword [rbp - local_14h], edi
|           0x004005a8      488975e0       mov qword [rbp - local_20h], rsi
|           0x004005ac      837dec02       cmp dword [rbp - local_14h], 2 ; [0x2:4]=0x102464c
|       ,=< 0x004005b0      7420           je 0x4005d2
|       |   0x004005b2      488b45e0       mov rax, qword [rbp - local_20h]
|       |   0x004005b6      488b00         mov rax, qword [rax]
|       |   0x004005b9      4889c6         mov rsi, rax
|       |   0x004005bc      bfa4064000     mov edi, str.Usage:__s_password_n ; "Usage: %s password." @ 0x4006a4
|       |   0x004005c1      b800000000     mov eax, 0
|       |   0x004005c6      e875feffff     call sym.imp.printf        ; int printf(const char *format);
|       |   0x004005cb      b801000000     mov eax, 1
|      ,==< 0x004005d0      eb41           jmp 0x400613
|      |`-> 0x004005d2      488b45e0       mov rax, qword [rbp - local_20h]
|      |    0x004005d6      4883c008       add rax, 8
|      |    0x004005da      488b00         mov rax, qword [rax]
|      |    0x004005dd      4889c7         mov rdi, rax
|      |    0x004005e0      e881ffffff     call sym.checksum
|      |    0x004005e5      488945f8       mov qword [rbp - local_8h], rax
|      |    0x004005e9      48817df8d40a.  cmp qword [rbp - local_8h], 0xad4 ; [0xad4:8]=0
|      |,=< 0x004005f1      7411           je 0x400604
|      ||   0x004005f3      bfb8064000     mov edi, str.Wrong_password ; "Wrong password" @ 0x4006b8
|      ||   0x004005f8      e833feffff     call sym.imp.puts          ; int puts(const char *s);
|      ||   0x004005fd      b801000000     mov eax, 1
|     ,===< 0x00400602      eb0f           jmp 0x400613
|     ||`-> 0x00400604      bfc7064000     mov edi, str._a_a_aTada__Congrats ; str._a_a_aTada__Congrats
|     ||    0x00400609      e822feffff     call sym.imp.puts          ; int puts(const char *s);
|     ||    0x0040060e      b800000000     mov eax, 0
|     ||    ; JMP XREF from 0x00400602 (sym.main)
|     ||    ; JMP XREF from 0x004005d0 (sym.main)
|     ``--> 0x00400613      c9             leave
\           0x00400614      c3             ret
[0x00400470]>

We can see the suspicious je instruction at 0x004005f1 - if the comparison in the previous line yields an equal, it would jump ahead to 0x400604, otherwise it would print "Wrong password". So we if we just replace the je with an unconditional jmp, we are done.

So we go to (seek) 0x004005f1

[0x00400470]> s 0x004005f1
[0x004005f1]>

... reopen the file in read-write mode and write our desired jmp instruction to the file.

[0x004005f1]> oo+
File 101-crackme reopened in read-write mode
[0x004005f1]> wa jmp 0x400604
Written 2 bytes (jmp 0x400604) = wx eb11
[0x004005f1]>

And double check

[0x004005f1]> pdf
            ;-- main:
/ (fcn) sym.main 120
|   sym.main ();
|           ; var int local_20h @ rbp-0x20
|           ; var int local_14h @ rbp-0x14
|           ; var int local_8h @ rbp-0x8
|           ; DATA XREF from 0x0040048d (entry0)
|           0x0040059d      55             push rbp
|           0x0040059e      4889e5         mov rbp, rsp
|           0x004005a1      4883ec20       sub rsp, 0x20
|           0x004005a5      897dec         mov dword [rbp - local_14h], edi
|           0x004005a8      488975e0       mov qword [rbp - local_20h], rsi
|           0x004005ac      837dec02       cmp dword [rbp - local_14h], 2 ; [0x2:4]=0x102464c
|       ,=< 0x004005b0      7420           je 0x4005d2
|       |   0x004005b2      488b45e0       mov rax, qword [rbp - local_20h]
|       |   0x004005b6      488b00         mov rax, qword [rax]
|       |   0x004005b9      4889c6         mov rsi, rax
|       |   0x004005bc      bfa4064000     mov edi, str.Usage:__s_password_n ; "Usage: %s password." @ 0x4006a4
|       |   0x004005c1      b800000000     mov eax, 0
|       |   0x004005c6      e875feffff     call sym.imp.printf        ; int printf(const char *format);
|       |   0x004005cb      b801000000     mov eax, 1
|      ,==< 0x004005d0      eb41           jmp 0x400613
|      |`-> 0x004005d2      488b45e0       mov rax, qword [rbp - local_20h]
|      |    0x004005d6      4883c008       add rax, 8
|      |    0x004005da      488b00         mov rax, qword [rax]
|      |    0x004005dd      4889c7         mov rdi, rax
|      |    0x004005e0      e881ffffff     call sym.checksum
|      |    0x004005e5      488945f8       mov qword [rbp - local_8h], rax
|      |    0x004005e9      48817df8d40a.  cmp qword [rbp - local_8h], 0xad4 ; [0xad4:8]=0
|      |,=< 0x004005f1      eb11           jmp 0x400604
|      ||   0x004005f3      bfb8064000     mov edi, str.Wrong_password ; "Wrong password" @ 0x4006b8
|      ||   0x004005f8      e833feffff     call sym.imp.puts          ; int puts(const char *s);
|      ||   0x004005fd      b801000000     mov eax, 1
|     ,===< 0x00400602      eb0f           jmp 0x400613
|     ||`-> 0x00400604      bfc7064000     mov edi, str._a_a_aTada__Congrats ; str._a_a_aTada__Congrats
|     ||    0x00400609      e822feffff     call sym.imp.puts          ; int puts(const char *s);
|     ||    0x0040060e      b800000000     mov eax, 0
|     ||    ; JMP XREF from 0x00400602 (sym.main)
|     ||    ; JMP XREF from 0x004005d0 (sym.main)
|     ``--> 0x00400613      c9             leave
\           0x00400614      c3             ret

So we leave r2 with q and check:

[0x004005f1]> q
% ./101-crackme somethingrandom
Tada! Congrats

And we're done.

Posted in reversing
2016-11-19 16:16