I am trying to solve this ELF - Ptrace challenge. I use Radare 2
. This is the commands I execute to print the assembly code.
radare2 ch3.bin
[0x080482f0]> aaa
[[anal.jmptbl] Missing cjmp bb in predecessor at 0x08057fca
[anal.jmptbl] Missing cjmp bb in predecessor at 0x08057f4a
[anal.jmptbl] Missing cjmp bb in predecessor at 0x0808fc43
[anal.jmptbl] Missing cjmp bb in predecessor at 0x0808fc23
[anal.jmptbl] Missing cjmp bb in predecessor at 0x0808fc63
[anal.jmptbl] Missing cjmp bb in predecessor at 0x0808fc83
[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] Type matching analysis for all functions (aaft)
[x] Use -AA or aaaa to perform additional experimental analysis.
[0xf7f0b049]> pd 100 @ main
;-- main:
/ (fcn) sym.main 175
| int sym.main (int argc, char **argv, char **envp);
| ; var char *s @ ebp-0x16
| ; var int var_ch @ ebp-0xc
| ; var int var_4h @ ebp-0x4
| ; arg int arg_4h @ esp+0x4
| ; DATA XREF from entry0 (0x8048307)
| 0x080483f0 8d4c2404 lea ecx, [arg_4h] ; sym._nl_current_LC_MONETARY
| 0x080483f4 83e4f0 and esp, 0xfffffff0
| 0x080483f7 ff71fc push dword [ecx - 4]
| 0x080483fa 55 push ebp
| 0x080483fb 89e5 mov ebp, esp
| 0x080483fd 51 push ecx
| 0x080483fe 83ec14 sub esp, 0x14
| 0x08048401 c745f488280c. mov dword [var_ch], str.ksuiealohgy ; 0x80c2888 ; "ksuiealohgy"
| 0x08048408 6a00 push 0 ; void*data
| 0x0804840a 6a01 push 1 ; ecx ; void*addr
| 0x0804840c 6a00 push 0 ; pid_t pid
| 0x0804840e 6a00 push 0 ; __ptrace_request request
| 0x08048410 e85b060100 call sym.ptrace
| 0x08048415 83c410 add esp, 0x10
| 0x08048418 85c0 test eax, eax
| ,=< 0x0804841a b 791a jns 0x8048436
| | 0x0804841c 83ec0c sub esp, 0xc
| | 0x0804841f 6894280c08 push str.Debugger_detect___..._Exit ; 0x80c2894 ; "Debugger detect\u00e9 ... Exit" ; const char *s
| | 0x08048424 e8a70e0000 call sym.puts ; int puts(const char *s)
| | 0x08048429 83c410 add esp, 0x10
| | 0x0804842c b801000000 mov eax, 1
| ,==< 0x08048431 e9c3000000 jmp loc.080484f9
| || ; CODE XREF from sym.main (0x804841a)
| |`-> 0x08048436 83ec0c sub esp, 0xc
| | 0x08048439 68b0280c08 push 0x80c28b0 ; const char *s
| | 0x0804843e e88d0e0000 call sym.puts ; int puts(const char *s)
| | 0x08048443 83c410 add esp, 0x10
| | 0x08048446 83ec0c sub esp, 0xc
| | 0x08048449 68f0280c08 push str.Bienvennue_dans_ce_challenge_de_cracking ; 0x80c28f0 ; "## Bienvennue dans ce challenge de cracking ##" ; const char *s
| | 0x0804844e e87d0e0000 call sym.puts ; int puts(const char *s)
| | 0x08048453 83c410 add esp, 0x10
| | 0x08048456 83ec0c sub esp, 0xc
| | 0x08048459 6830290c08 push 0x80c2930 ; const char *s
| | 0x0804845e e86d0e0000 call sym.puts ; int puts(const char *s)
| | 0x08048463 83c410 add esp, 0x10
| | 0x08048466 b86e290c08 mov eax, str.Password_: ; 0x80c296e ; "Password : "
| | 0x0804846b 83ec0c sub esp, 0xc
| | 0x0804846e 50 push eax
| | 0x0804846f e8ec0a0000 call sym.__printf
| | 0x08048474 83c410 add esp, 0x10
| | 0x08048477 a19c540e08 mov eax, dword obj.stdin ; obj._IO_stdin ; [0x80e549c:4]=0x80e5080 obj._IO_2_1_stdin
| | 0x0804847c 83ec04 sub esp, 4
| | 0x0804847f 50 push eax ; FILE *stream
| | 0x08048480 6a09 push 9 ; 9 ; int size
| | 0x08048482 8d45ea lea eax, [s]
| | 0x08048485 50 push eax ; char *s
| | 0x08048486 e8050b0000 call sym.fgets ; char *fgets(char *s, int size, FILE *stream)
| | 0x0804848b 83c410 add esp, 0x10
| | 0x0804848e 8d0597840408 lea eax, loc._notng ; 0x8048497
| | 0x08048494 40 inc eax
\ | 0x08048495 ffe0 jmp eax
| ;-- _notng:
| ; DATA XREF from sym.main (0x804848e)
| 0x08048497 b88a55ea8b mov eax, 0x8bea558a
| 0x0804849c 45 inc ebp
| 0x0804849d f4 hlt
| 0x0804849e 83c004 add eax, 4
| 0x080484a1 8a00 mov al, byte [eax]
| 0x080484a3 38c2 cmp dl, al
|,=< 0x080484a5 b 753d jne 0x80484e4
|| 0x080484a7 8a55eb mov dl, byte [ebp - 0x15]
|| 0x080484aa 8b45f4 mov eax, dword [ebp - 0xc]
|| 0x080484ad 83c005 add eax, 5
|| 0x080484b0 8a00 mov al, byte [eax]
|| 0x080484b2 38c2 cmp dl, al
,===< 0x080484b4 752e jne 0x80484e4
||| 0x080484b6 8a55ec mov dl, byte [ebp - 0x14]
||| 0x080484b9 8b45f4 mov eax, dword [ebp - 0xc]
||| 0x080484bc 40 inc eax
||| 0x080484bd 8a00 mov al, byte [eax]
||| 0x080484bf 38c2 cmp dl, al
,====< 0x080484c1 b 7521 jne 0x80484e4
|||| 0x080484c3 8a55ed mov dl, byte [ebp - 0x13]
|||| 0x080484c6 8b45f4 mov eax, dword [ebp - 0xc]
|||| 0x080484c9 83c00a add eax, 0xa
|||| 0x080484cc 8a00 mov al, byte [eax]
|||| 0x080484ce 38c2 cmp dl, al
,=====< 0x080484d0 b 7512 jne 0x80484e4
||||| 0x080484d2 83ec0c sub esp, 0xc
||||| 0x080484d5 687a290c08 push str.Good_password ; 0x80c297a ; "\nGood password !!!\n"
||||| 0x080484da e8f10d0000 call sym.puts ; int puts(const char *s)
||||| 0x080484df 83c410 add esp, 0x10
,======< 0x080484e2 eb10 jmp 0x80484f4
|||||| ; CODE XREFS from loc._notng (+0xe, +0x1d, +0x2a, +0x39)
|```-`-> 0x080484e4 b 83ec0c sub esp, 0xc
| | 0x080484e7 688e290c08 push str.Wrong_password. ; 0x80c298e ; "\nWrong password.\n"
| | 0x080484ec e8df0d0000 call sym.puts ; int puts(const char *s)
| | 0x080484f1 83c410 add esp, 0x10
| | ; CODE XREF from loc._notng (+0x4b)
`------> 0x080484f4 b800000000 mov eax, 0
|- loc.080484f9 8
| loc.080484f9 ();
| | ; var int var_4h @ ebp-0x4
| | ; CODE XREF from sym.main (0x8048431)
| `--> 0x080484f9 8b4dfc mov ecx, dword [var_4h]
| 0x080484fc c9 leave
| 0x080484fd 8d61fc lea esp, [ecx - 4]
\ 0x08048500 c3 ret
0x08048501 90 nop
0x08048502 90 nop
0x08048503 90 nop
0x08048504 90 nop
0x08048505 90 nop
0x08048506 90 nop
0x08048507 90 nop
0x08048508 90 nop
0x08048509 90 nop
0x0804850a 90 nop
0x0804850b 90 nop
I can see that there is an anti-debugging technic at instruction 0x0804841a
, I can bypass it putting a break point and modifying eip adress on the fly.
I can also see that there is several tests before print Good Password!!!
I put all the breakpoints I need :
[0x00000000]> ood
[0x080482f0]> db 0x0804841a
[0x080482f0]> db 0x080484a5
[0x080482f0]> db 0x80484e4
[0x080482f0]> db 0x080484c1
[0x080482f0]> db 0x080484d0
[0x080482f0]> dc
child stopped with signal 28
[+] SIGNAL 28 errno=0 addr=0x00000000 code=128 ret=0
[0x080482f0]> dc
hit breakpoint at: 804841a
[0x0804841a]> dr eip=0x08048436
0x0804841a ->0x08048436
[0x0804841a]> dc
############################################################
## Bienvennue dans ce challenge de cracking ##
############################################################
Password : badpassword
hit breakpoint at: 80484a5
[0x080484a5]> dr eip=0x080484a7
0x080484a5 ->0x080484a7
[0x080484a5]> dc
hit breakpoint at: 80484e4
[0x080484a5]> dr eip=0x080484b6
0x080484e4 ->0x080484b6
[0x080484a5]> dc
hit breakpoint at: 80484c1
[0x080484a5]> dr eip=0x080484c3
0x080484c1 ->0x080484c3
[0x080484a5]> dc
hit breakpoint at: 80484d0
[0x080484a5]> ptr axt
[0x080484a5]> dr
eax = 0x080c2879
ebx = 0x00000000
ecx = 0xffffffff
edx = 0x080e6515
esi = 0x08048bc0
edi = 0x08048b20
esp = 0xffe51480
ebp = 0xffe51498
eip = 0x080484d0
eflags = 0x00000297
oeax = 0xffffffff
Now, at this point (and for each conditinal previous tests), I would like to print the value of the stack or adresses to see exactly what is compared. My problem is I can't understant what values are compared in the first test for example :
| ; DATA XREF from sym.main (0x804848e)
| 0x08048497 b88a55ea8b mov eax, 0x8bea558a
| 0x0804849c 45 inc ebp
| 0x0804849d f4 hlt
| 0x0804849e 83c004 add eax, 4
| 0x080484a1 8a00 mov al, byte [eax]
| 0x080484a3 38c2 cmp dl, al
|,=< 0x080484a5 753d jne 0x80484e4
I think I use a bad way to solve this challenge because I modify each eip to print finally Good Password!!!, I can't see the password on the stack or something else. I use the command pxr @ esp
.
What is the content of al
and dl
?
I also tried to generate the source code with Snowman
but it doesn't help me :
void fun_804849e(void** ecx) {
signed char dl2;
struct s2421* eax3;
int32_t ebp4;
int32_t ebp5;
int32_t ebp6;
int32_t ebp7;
int32_t ebp8;
int32_t ebp9;
int32_t v10;
int32_t v11;
int32_t v12;
int32_t v13;
int32_t v14;
int32_t v15;
if (dl2 != eax3->f4 || (*reinterpret_cast<signed char*>(ebp4 - 21) != (*reinterpret_cast<struct s2422**>(ebp5 - 12))->f5 || (*reinterpret_cast<signed char*>(ebp6 - 20) != (*reinterpret_cast<struct s2423**>(ebp7 - 12))->f1 || *reinterpret_cast<signed char*>(ebp8 - 19) != (*reinterpret_cast<struct s2424**>(ebp9 - 12))->f10))) {
_IO_puts(ecx, "\nWrong password.\n", v10, v11, v12, __return_address());
} else {
_IO_puts(ecx, "\nGood password !!!\n", v13, v14, v15, __return_address());
}
}