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

uint32_t var_8h;

int32_t var_4h;

char * format;

int32_t var_sp_8h;

var_8h = 0;

var_ch = 0;

do {

eax = s;

eax = strlen (eax);

if (var_ch >= eax) {

goto label_0;

}

eax = var_ch;

eax += s;

eax = *(eax);

var_dh = al;

eax = &var_4h;

eax = &var_dh;

sscanf (eax, eax, 0x8048638);

edx = var_4h;

eax = &var_8h;

*(eax) += edx;

if (var_8h == 0xf) {

printf ("Password OK!\n");

exit (0);

}

eax = &var_ch;

*(eax)++;

} while (1);

label_0:

printf ("Password Incorrect!\n");

return eax;

}

manually analyze with both the assembly and pseudo code we can simply write down the C-like code to describe this function:

#include 

int32_t check(char *s)

{

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 == 0xf)

printf("Password OK\n");

}

printf("Password Incorrect!\n");

return 0;

}

In short, it calculates the Digit Sum of a number (add a number digit by digit. for example, 96 => 9 + 6 = 15) :

./crackme0x04

IOLI Crackme Level 0x04

Password: 12345

Password OK!


./crackme0x04

IOLI Crackme Level 0x04

Password: 96

Password OK!

IOLI 0x05

check again, it uses scanf() to get our input and pass it to check() as parameter.

[0x080483d0]> pdd@main

/* r2dec pseudo code output */

/* ./crackme0x05 @ 0x8048540 */

#include 


int32_t main (void) {

int32_t var_78h;

int32_t var_4h;

eax = 0;

eax += 0xf;

eax += 0xf;

eax >>= 4;

eax <<= 4;

printf ("IOLI Crackme Level 0x05\n");

printf ("Password: ");

eax = &var_78h;

scanf (0x80486b2, eax);
// 0x80486b2 is %s

eax = &var_78h;

check (eax);

eax = 0;

return eax;

}

the check() function:

/* r2dec pseudo code output */

/* ./crackme0x05 @ 0x80484c8 */

#include 


int32_t check (char * s) {

char * var_dh;

uint32_t var_ch;

uint32_t var_8h;

int32_t var_4h;

char * format;

int32_t var_sp_8h;

var_8h = 0;

var_ch = 0;

do {

eax = s;

eax = strlen (eax);

if (var_ch >= eax) {

goto label_0;

}

eax = var_ch;

eax += s;

eax = *(eax);

var_dh = al;

eax = &var_4h;

eax = &var_dh;

sscanf (eax, eax, 0x8048668);
// 0x8048668 is %d

edx = var_4h;

eax = &var_8h;

*(eax) += edx;

if (var_8h == 0x10) {

eax = s;

parell (eax);

}

eax = &var_ch;

*(eax)++;

} while (1);

label_0:

printf ("Password Incorrect!\n");

return eax;

}

The same, we can write our own C-like pseudo code.

#include 

int32_t check(char *s)

{

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)

parell(s);

}

printf("Password Incorrect!\n");

return 0;

}

The if condition becomes var_8h == 0x10. In addition, a new function call - parell(s) replace the printf("password OK")now. The next step is to reverse sym.parell.

[0x08048484]> s sym.parell

[0x08048484]> pdd@sym.parell

/* r2dec pseudo code output */

/* ./crackme0x05 @ 0x8048484 */

#include 


uint32_t parell (char * s) {

int32_t var_4h;

char * format;

int32_t var_8h;

eax = &var_4h;

eax = s;

sscanf (eax, eax, 0x8048668);

eax = var_4h;

eax &= 1;

if (eax == 0) {

printf ("Password OK!\n");

exit (0);

}

return eax;

}

the decompiled code looks well except the sscanf() function. It can be easily corrected by checking the assembly code.

/ 68: sym.parell (int32_t arg_8h);

|           ; var int32_t var_4h @ ebp-0x4

|           ; arg int32_t arg_8h @ ebp+0x8

|           ; var int32_t var_sp_4h @ esp+0x4

|           ; var int32_t var_8h @ esp+0x8

|           0x08048484      55             push ebp

|           0x08048485      89e5           mov ebp, esp