The Official Radare2 Book — страница 58 из 64

0x080485f0
c7442404c287.  mov dword [format], 0x80487c2 ; [0x80487c2:4]=0x50006425 ; const char *format

|      |:   ;-- eip:

|      |:
0x080485f8
8d45f3         lea eax, [var_dh]

|      |:
0x080485fb
890424
mov dword [esp], eax        ; const char *s

|      |:
0x080485fe
e8c5fdffff     call sym.imp.sscanf         ; int sscanf(const char *s, const char *format,   ...)

|      |:   0x08048603      8b55fc         mov edx, dword [var_bp_4h]

|      |:   0x08048606      8d45f8         lea eax, [var_8h]

|      |:   0x08048609      0110           add dword [eax], edx

|      |:   0x0804860b      837df810       cmp dword [var_8h], 0x10

|     ,===< 0x0804860f
7512
jne 0x8048623

|     ||:
0x08048611
8b450c         mov eax, dword [arg_ch]

|     ||:
0x08048614
89442404
mov dword [format], eax     ; char *arg_ch

|     ||:
0x08048618
8b4508         mov eax, dword [s]

|     ||:
0x0804861b
890424
mov dword [esp], eax        ; char *s

|     ||:
0x0804861e
e81fffffff     call fcn.08048542

|     ||:   ; CODE XREF from fcn.080485b9 @ 0x804860f

|     `---> 0x08048623
8d45f4         lea eax, [var_ch]

|      |:
0x08048626
ff00           inc dword [eax]

|      |`=< 0x08048628
eba3           jmp 0x80485cd

|      |    ; CODE XREF from fcn.080485b9 @ 0x80485db

\      `--> 0x0804862a
e8f5feffff     call fcn.08048524

we got familiar with this code structure in the previous challenges (the check function). It's not difficult for us even we don't have the symbol info. you can also use afn command to rename the function name if you like.

int32_t fcn_080485b9 (char * s, void* envp)

{

var_ch = 0;

var_8h = 0;

for (var_ch = 0; var_ch < strlen(s); ++var_ch)

{

var_dh = s[var_ch];

sscanf(&var_dh, %d, &var_4h);
// read from string[var_ch], store to var_4h

var_8h += var_4h;

if(var_8h == 0x10)

fcn_08048542(s, envp);

}

return fcn_08048524();

}

most part of crackme 0x07 is the same with 0x06. and it can be solved by the same password & environment:

$ export LOLAA=help

$ ./cracke0x07

IOLI Crackme Level 0x07

Password: 12346

Password OK!

wait ... where is the 'wtf?'. Often, we would like to find the cross reference (xref) to strings (or data, functions, etc.) in reverse engineering. The related commands in Radare2 are under "ax" namespace:

[0x08048400]> f

0x080487a8 5 str.LOLO

0x080487ad 21 str.Password_Incorrect

0x080487c5 14 str.Password_OK

0x080487d3 6 str.wtf

0x080487d9 25 str.IOLI_Crackme_Level_0x07

0x080487f2 11 str.Password:

[0x08048400]> axt 0x80487d3

(nofunc) 0x804865c [DATA] mov dword [esp], str.wtf

[0x08048400]> axF str.wtf

Finding references of flags matching 'str.wtf'...

[0x001eff28-0x001f0000] (nofunc) 0x804865c [DATA] mov dword [esp], str.wtf

Macro 'findstref' removed.

the [DATA] mov dword [esp], str.wtf at 0x804865c is an instruction of fcn.080485b9. But the analysis in my PC ignores the remained instructions and only display the incomplete assembly. the range of fcn.080485b9 should be 0x080485b9 ~ 0x0804867c . we can reset block size and print opcodes.

[0x08040000]>

s 0x080485b9

[0x080485b9]> b 230

[0x08048400]> pd

...

0x0804862f 8b450c mov eax, dword [ebp + 0xc]

0x08048632 89442404 mov dword [esp + 4], eax

0x08048636 8b45fc mov eax, dword [ebp - 4]

0x08048639 890424 mov dword [esp], eax ;

char **s1

0x0804863c e873feffff call fcn.080484b4

0x08048641 85c0 test eax, eax

,=< 0x08048643 7436 je 0x804867b

| 0x08048645 c745f4000000. mov dword [ebp - 0xc], 0

| ; CODE XREF from fcn.080485b9 @ +0xc0

.--> 0x0804864c 837df409 cmp dword [ebp - 0xc], 9

,===< 0x08048650 7f29 jg 0x804867b

|:| 0x08048652 8b45fc mov eax, dword [ebp - 4]

|:| 0x08048655 83e001 and eax, 1

|:| 0x08048658 85c0 test eax, eax

,====< 0x0804865a 7518 jne 0x8048674

||:| 0x0804865c c70424d38704. mov dword [esp], str.wtf ;

[0x80487d3:4]=0x3f667477 ; "wtf?\n" ; const char *format

||:| 0x08048663 e850fdffff call sym.imp.printf ;

int printf(const char *format)

||:| 0x08048668 c70424000000. mov dword [esp], 0 ;

int status

||:| 0x0804866f e874fdffff call sym.imp.exit ;

void exit(int status)

||:| ; CODE XREF from fcn.080485b9 @ +0xa1

`----> 0x08048674 8d45f4 lea eax, [ebp - 0xc]

|:| 0x08048677 ff00 inc dword [eax]

|`==< 0x08048679 ebd1 jmp 0x804864c

| | ; CODE XREFS from fcn.080485b9 @ +0x8a, +0x97

`-`-> 0x0804867b c9 leave

0x0804867c c3 ret


test eax, ea;je 0x804867b will jump to leave; ret, which forever skips the str.wtf part. only use aa to analyze this binary can display the whole function.

IOLI 0x08

we can reverse it and find it's similar to 0x07, and use the same password to solve it:

$ export LOLAA=help

$ ./cracke0x08

IOLI Crackme Level 0x08

Password: 12346

Password OK!

dustri provided a better way to check crackme0x08. 0x07 is the stripped version of 0x08.

$ radiff2 -A -C ./crackme0x07 ./crackme0x08

...

fcn.08048360  23 0x8048360 |   MATCH  (1.000000) | 0x8048360   23 sym._init

sym.imp.__libc_start_main   6 0x8048388 |   MATCH  (1.000000) | 0x8048388    6 sym.imp.__libc_start_main

sym.imp.scanf   6 0x8048398 |   MATCH  (1.000000) | 0x8048398    6 sym.imp.scanf