I'm working on a crackme, where the objective is to find the valid password given a program. I'm using radare2 to reverse engineering the program. To do so, I need to enter a password that forces this program to bypass all the conditional jumps (jne
's, jle
's, jg
's throughout).
Thus far, I've only concluded that the password must be 4 characters long, and the lowest 8 bits is 0x79, or ASCII character 'y' (please correct me if I'm wrong). The first N disassembled bytes (until I get stuck) are given below:
root@kali:~/Exploit_Class_NSL/Week1/Exercise4# r2 -AAAA example4
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Constructing a function name for fcn.* and sym.func.* functions (aan)
[x] Enable constraint types analysis for variables
[0x00401080]> pdf @main
;-- main:
/ (fcn) sym.main 201
| sym.main (int argc, char **argv, char **envp);
| ; var int local_20h @ rbp-0x20
| ; var int local_14h @ rbp-0x14
| ; var int local_5h @ rbp-0x5
| ; var int local_4h @ rbp-0x4
| ; var int local_3h @ rbp-0x3
| ; var int local_2h @ rbp-0x2
| ; arg int argc @ rdi
| ; arg char **argv @ rsi
| ; DATA XREF from entry0 (0x40109d)
| 0x00401162 55 push rbp
| 0x00401163 4889e5 mov rbp, rsp
| 0x00401166 4883ec20 sub rsp, 0x20
| 0x0040116a 897dec mov dword [local_14h], edi ; argc
| 0x0040116d 488975e0 mov qword [local_20h], rsi ; argv
| 0x00401171 488d3d8c0e00. lea rdi, qword str.enter_the_password: ; 0x402004 ; "enter the password: "
| 0x00401178 b800000000 mov eax, 0
| 0x0040117d e8cefeffff call sym.imp.printf ; int printf(const char *format)
| 0x00401182 488b15c72e00. mov rdx, qword [obj.stdin__GLIBC_2.2.5] ; obj.__TMC_END ; [0x404050:8]=0
| 0x00401189 488d45fb lea rax, qword [local_5h]
| 0x0040118d be05000000 mov esi, 5
| 0x00401192 4889c7 mov rdi, rax
| 0x00401195 e8c6feffff call sym.imp.fgets ; char *fgets(char *s, int size, FILE *stream)
| 0x0040119a 488d45fb lea rax, qword [local_5h]
| 0x0040119e 4889c7 mov rdi, rax
| 0x004011a1 e89afeffff call sym.imp.strlen ; size_t strlen(const char *s)
| 0x004011a6 4883f804 cmp rax, 4 ; 4
| ,=< 0x004011aa 7559 jne 0x401205
| | 0x004011ac 0fb645fb movzx eax, byte [local_5h]
| | 0x004011b0 3c79 cmp al, 0x79 ; 'y' ; 121
| ,==< 0x004011b2 7554 jne 0x401208
| || 0x004011b4 0fb645fc movzx eax, byte [local_4h]
| || 0x004011b8 0fbed0 movsx edx, al
| || 0x004011bb 0fb645fd movzx eax, byte [local_3h]
| || 0x004011bf 0fbec0 movsx eax, al
| || 0x004011c2 01d0 add eax, edx
| || 0x004011c4 3dda000000 cmp eax, 0xda ; 218
| ,===< 0x004011c9 7540 jne 0x40120b
| ||| 0x004011cb 0fb645fd movzx eax, byte [local_3h]
| ||| 0x004011cf 3c6c cmp al, 0x6c ; 'l' ; 108
| ,====< 0x004011d1 7e3b jle 0x40120e
At 0x004011b4 is where I start to get stuck.
| || 0x004011b4 0fb645fc movzx eax, byte [local_4h]
| || 0x004011b8 0fbed0 movsx edx, al
| || 0x004011bb 0fb645fd movzx eax, byte [local_3h]
| || 0x004011bf 0fbec0 movsx eax, al
| || 0x004011c2 01d0 add eax, edx
| || 0x004011c4 3dda000000 cmp eax, 0xda ; 218
| ,===< 0x004011c9 7540 jne 0x40120b
Are local variables local_3h
and local_4h
ever initialized? If so, how? How should I go about stepping through this on my own?
I've tried toying around with different functions in r2, like afvd
, e [ ]
, etc., but haven't gotten anywhere yet.
Any tips appreciated. Thanks!
0x6c
before thecmp
operation at0x004011cf
. FWIW, I've included all the output in my OP (through0x004011c9
)