0

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!

2
  • look at the start you will see radare2 telling you what each of those local points to they are resp rbp - 2,3,4,5 1 is 6c other is 79 and the rest is an addition result
    – blabb
    Commented Apr 20, 2019 at 6:11
  • Sorry, @blabb , I don't see that... is that included in my code above? For example, I don't see reference to 0x6c before the cmp operation at 0x004011cf. FWIW, I've included all the output in my OP (through 0x004011c9)
    – ch-pub
    Commented Apr 20, 2019 at 6:16

2 Answers 2

3

Yes, they are initialized, albeit indirectly.

Have a look at this fragment:

   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)

Here we're calling the fgets function, passing to it the address of the local_5h as s and value 5 as size. This means that up to 5 bytes (including the terminating zero) can be read into the memory starting at local_5h, i.e. local_4h and local_3h are the second and third characters of the retrieved string.

2
  • Thanks! Is the qword in your referenced fragment a clue that more variables are being initialized? i.e., since local_5h appears to be only 0x1 wide? Wondering if I'm interpreting this correct: local_5h @ rbp-0x5, local_4h @ rbp-0x4, local_3h @ rbp-0x3, etc...
    – ch-pub
    Commented Apr 20, 2019 at 15:42
  • @ClarkHenry I think it's just an artifact of r2's disassembler. Since lea is taking an address and not moving any data, the size of the variable is not relevant. You could try reporting this issue to the developers.
    – Igor Skochinsky
    Commented Apr 20, 2019 at 15:45
0

I would say they are initialized on the stack for the local scope, as local variables for the function. My thoughts are look at the data stored on the local stack. I'm not sure if that is what you are looking for as an answer. I hope that helps.

2
  • 2
    Thanks for the feedback. Could you please elaborate a little? Would you happen to know how to do that in radare2? Would I find that in the 'entry0' or '.data' section of the disassembled program?
    – ch-pub
    Commented Apr 20, 2019 at 5:33
  • i haven't used it before, but I took a quick look at the documentation and this console string - pm xxs @ esp should print the stack, or possibly substitute ebp, let me know what that gives you! Commented Apr 20, 2019 at 5:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.