1

I am trying to crack a crackme. I already catch the flag because I seen the string variable which represants flag. I would like to catch the flag on an other way, I want to set a breakpoint when there is a comparison of the string. I want to use radare2.

When I use the dc command to run the program which should stop to breakpoint I set up, I have the message TO DO continue. I don't know why. I expected a message in the form :

string 1 : TheStringIEnter string 2 : TheFlagOfTheChallenge 

This is the commands I execute :

radare 2 -d ch1.bin s sym.main aaa pdf VV : :> db 0x08048705 :> dc TODO continue :> 

This is the output of pdf command :

[0x0804869d]> pdf / (fcn) main 155 | main (int argc, char **argv, char **envp); | ; var int local_ch @ ebp-0xc | ; var int local_8h @ ebp-0x8 | ; var int local_4h @ esp+0x4 | ; DATA XREF from entry0 (0x8048507) | 0x0804869d 8d4c2404 lea ecx, [local_4h] ; 4 | 0x080486a1 83e4f0 and esp, 0xfffffff0 | 0x080486a4 ff71fc push dword [ecx - 4] | 0x080486a7 55 push ebp | 0x080486a8 89e5 mov ebp, esp | 0x080486aa 51 push ecx | 0x080486ab 83ec24 sub esp, 0x24 ; '$' | 0x080486ae c745f8418804. mov dword [local_8h], str.123456789 ; 0x8048841 ; "123456789" | 0x080486b5 c704244c8804. mov dword [esp], str. ; [0x804884c:4]=0x23232323 ; "############################################################" | 0x080486bc e807feffff call sym.imp.puts ; int puts(const char *s) | 0x080486c1 c704248c8804. mov dword [esp], str.welcome_to_challenge ; [0x804888c:4]=0x20202323 ; "## Welcome to this challenge ##" | 0x080486c8 e8fbfdffff call sym.imp.puts ; int puts(const char *s) | 0x080486cd c70424cc8804. mov dword [esp], str. ; [0x80488cc:4]=0x23232323 ; "############################################################\n" | 0x080486d4 e8effdffff call sym.imp.puts ; int puts(const char *s) | 0x080486d9 c704240c8904. mov dword [esp], str.please_enter_pass: ; [0x804890c:4]=0x69756556 ; "Please enter the password : " | 0x080486e0 e8b3fdffff call sym.imp.printf ; int printf(const char *format) | 0x080486e5 8b45f4 mov eax, dword [local_ch] | 0x080486e8 890424 mov dword [esp], eax | 0x080486eb e80effffff call sym.getString | 0x080486f0 8945f4 mov dword [local_ch], eax | 0x080486f3 8b45f8 mov eax, dword [local_8h] | 0x080486f6 89442404 mov dword [local_4h], eax | 0x080486fa 8b45f4 mov eax, dword [local_ch] | 0x080486fd 890424 mov dword [esp], eax | 0x08048700 e8d3fdffff call sym.imp.strcmp ; int strcmp(const char *s1, const char *s2) | 0x08048705 85c0 test eax, eax | ,=< 0x08048707 7515 jne 0x804871e | | 0x08048709 8b45f8 mov eax, dword [local_8h] | | 0x0804870c 89442404 mov dword [local_4h], eax | | 0x08048710 c70424308904. mov dword [esp], str.good_job:__s ; [0x8048930:4]=0x6e656942 ; "Good job ! You just pass the challenge with the pass : %s!\n" | | 0x08048717 e87cfdffff call sym.imp.printf ; int printf(const char *format) | ,==< 0x0804871c eb0c jmp 0x804872a | || ; CODE XREF from main (0x8048707) | |`-> 0x0804871e c70424708904. mov dword [esp], str.bad__password. ; [0x8048970:4]=0x6d6d6f44 ; "Bad password." | | 0x08048725 e89efdffff call sym.imp.puts ; int puts(const char *s) | | ; CODE XREF from main (0x804871c) | `--> 0x0804872a b800000000 mov eax, 0 | 0x0804872f 83c424 add esp, 0x24 ; '$' | 0x08048732 59 pop ecx | 0x08048733 5d pop ebp | 0x08048734 8d61fc lea esp, [ecx - 4] \ 0x08048737 c3 ret [0x0804869d]> 
4
  • I think there are issues already open for this. Disable ESIL emulation and don't open in debug mode. Use doo in normal mode for dc to work Commented Dec 25, 2018 at 5:40
  • Ok, I executed the doo command and it works : radare2 ch1.bin aaa s sym.main pdf ood db 0x08048705 dc Now, radare2 show me this message : hit breakpoint at: 8048705. How can I print the two strings which are compared. Commented Dec 26, 2018 at 14:22
  • Can you share the binary? Commented Dec 27, 2018 at 5:26
  • Sure, this is the link of the challenge : root-me.org/fr/Challenges/Cracking/ELF-0-protection Commented Dec 27, 2018 at 9:53

1 Answer 1

3

Here's how you do it with debugging.

$ r2 ch1.bin [0x080484f0]> aaa [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 (afta) [x] Use -AA or aaaa to perform additional experimental analysis. [0x080484f0]> doo Process with PID 18337 started... File dbg:///tmp/ch1.bin reopened in read-write mode = attach 18337 18337 18337 [0xf7f6fc70]> pdf @ sym.main ~strcmp │ 0x08048700 e8d3fdffff call sym.imp.strcmp ; int strcmp(const char *s1, const char *s2) 

Set a breakpoint at the strcmp call and continue execution.

[0xf7f6fc70]> s 0x08048700 [0x08048700]> db 0x08048700 [0x08048700]> dc ############################################################ ## Bienvennue dans ce challenge de cracking ## ############################################################ Veuillez entrer le mot de passe : test hit breakpoint at: 8048700 

Use pxr to dump esp with flags and information about addresses.

[0x08048700]> pxr@esp~:0..5 0xfff45270 0x09075570 pU.. @esp eax (test) 0xfff45274 0x08048841 A... (.rodata) (/tmp/ch1.bin) str.123456789 program R X 'xor dword [edx], esi' 'ch1.bin' (123456789) 0xfff45278 0xfff452a8 .R.. stack R W 0x0 --> edi 0xfff4527c 0x08048769 i... (.text) (/tmp/ch1.bin) sym.__libc_csu_init program R X 'lea eax, [ebx - 0xe8]' 'ch1.bin' 0xfff45280 0x00000000 .... edi [0x08048700]> 

Stack top points to our input test passed as first param to strcmp. The next dword points to the second param at 0x08048841 string 123456789.

Since strcmp is a library function you can use ltrace to do the same.

$ ltrace ./ch1.bin __libc_start_main(0x804869d, 1, 0xffbe8304, 0x8048750 <unfinished ...> puts("################################"...############################################################ ) = 61 puts("## Bienvennue dans ce cha"...## Bienvennue dans ce challenge de cracking ## ) = 61 puts("################################"...############################################################ ) = 62 printf("Veuillez entrer le mot de passe "...) = 34 malloc(2) = 0x9352570 getchar(2, 0, 0xffbe8258, 0xf7d792f6Veuillez entrer le mot de passe : test ) = 116 realloc(0x9352570, 2) = 0x9352570 getchar(0x9352570, 2, 0xffbe8258, 0xf7d792f6) = 101 realloc(0x9352570, 3) = 0x9352570 getchar(0x9352570, 3, 0xffbe8258, 0xf7d792f6) = 115 realloc(0x9352570, 4) = 0x9352570 getchar(0x9352570, 4, 0xffbe8258, 0xf7d792f6) = 116 realloc(0x9352570, 5) = 0x9352570 getchar(0x9352570, 5, 0xffbe8258, 0xf7d792f6) = 10 strcmp("test", "123456789") = 1 puts("Dommage, essaye encore une fois."...Dommage, essaye encore une fois. ) = 33 +++ exited (status 0) +++ 

TBF you don't need to debug it at all and just static analysis would do.

[0x080484f0]> pdf @ sym.main~strcmp │ 0x08048700 e8d3fdffff call sym.imp.strcmp ; int strcmp(const char *s1, const char *s2) [0x080484f0]> s 0x08048700 [0x08048700]> pd-10 │ 0x080486d9 c704240c8904. mov dword [esp], str.Veuillez_entrer_le_mot_de_passe_: ; [0x804890c:4]=0x69756556 ; "Veuillez entrer le mot de passe : " ; const char *format │ 0x080486e0 e8b3fdffff call sym.imp.printf ; int printf(const char *format) │ 0x080486e5 8b45f4 mov eax, dword [s1] │ 0x080486e8 890424 mov dword [esp], eax │ 0x080486eb e80effffff call sym.getString │ 0x080486f0 8945f4 mov dword [s1], eax │ 0x080486f3 8b45f8 mov eax, dword [local_8h] │ 0x080486f6 89442404 mov dword [s2], eax ; const char *s2 │ 0x080486fa 8b45f4 mov eax, dword [s1] │ 0x080486fd 890424 mov dword [esp], eax ; const char *s1 [0x08048700]> 

Now we know the arguments to strcmp : s1 and local_8h. s1 was populated with a call to sym.getString, so thats probably our input and hence local_8h is the string we need to find to match.

We'll see where it was used//modified (read/write) in the function. Use afv(R/W)

[0x08048700]> afv? Usage: afv [rbs] | afvr[?] manipulate register based arguments | afvb[?] manipulate bp based arguments/locals | afvs[?] manipulate sp based arguments/locals | afv* output r2 command to add args/locals to flagspace | afvR [varname] list addresses where vars are accessed (READ) | afvW [varname] list addresses where vars are accessed (WRITE) | afva analyze function arguments/locals | afvd name output r2 command for displaying the value of args/locals in the debugger | afvn [new_name] ([old_name]) rename argument/local | afvt [name] [new_type] change type for given argument/local | afv-([name]) remove all or given var 

Use this on local_8h

[0x08048700]> afvR local_8h local_8h 0x80486f3,0x8048709 [0x08048700]> afvW local_8h local_8h 0x80486ae 

At 0x80486ae it was written to or initialized.

[0x08048700]> pd3 @ 0x80486ae │ 0x080486ae c745f8418804. mov dword [local_8h], str.123456789 ; 0x8048841 ; "123456789" │ 0x080486b5 c704244c8804. mov dword [esp], str. ; [0x804884c:4]=0x23232323 ; "############################################################" ; const char *s │ 0x080486bc e807feffff call sym.imp.puts ; int puts(const char *s) [0x08048700]> 

Here r2 resolved the address 0x8048841 to a string 123456789

0