Выбрать главу

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 <stdint.h>

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

| 0x08048487 83ec18 sub esp, 0x18

| 0x0804848a 8d45fc lea eax, [var_4h]

| 0x0804848d 89442408 mov dword [var_8h], eax

| 0x08048491 c74424046886. mov dword [var_sp_4h], 0x8048668 ; [0x8048668:4]=0x50006425 %d

| 0x08048499 8b4508 mov eax, dword [arg_8h]

| 0x0804849c 890424 mov dword [esp], eax

| 0x0804849f e800ffffff call sym.imp.sscanf ; int sscanf(const char *s, const char *format, ...)

....

The mov dword [esp], eax is the nearest instruction to sscanf (and it's equivalent to a push instruction). It stores the string 's' to the stack top (arg1). mov dword [var_sp_4h], 0x8048668 push '%d' as arg2 into stack. var_8h (esp + 0x8) which keeps the address of var_4h is the arg3.

Finally we have the corrected pseudo code:

uint32_t parell (char * s) {

sscanf (s, %d, &var_4h);

if ((var_4h & 1) == 0) {

printf ("Password OK!\n");

exit(0);

}

return 0;

}

Now there are 2 constraints:

   • Digit Sum is 16 (0x10)

   • Must be an odd number (1 & number == 0)

The password is at our fingertips now.

./crackme0x05

IOLI Crackme Level 0x05

Password: 88

Password OK!

./crackme0x05

IOLI Crackme Level 0x05

Password: 12346

Password OK!

we can also use angr to solve it since we have two constraints to the password.

nearly a routine to check this binary (not complete output in the following):

rabin2 -z ./crackme0x06

[Strings]

nth paddr vaddr len size section type string

―――――――――――――――――――――――――――――――――――――――――――――――――――――――

0 0x00000738 0x08048738 4 5 .rodata ascii LOLO

1 0x00000740 0x08048740 13 14 .rodata ascii Password OK!\n

2 0x0000074e 0x0804874e 20 21 .rodata ascii Password Incorrect!\n

3 0x00000763 0x08048763 24 25 .rodata ascii IOLI Crackme Level 0x06\n

4 0x0000077c 0x0804877c 10 11 .rodata ascii Password:

rabin2 -I ./crackme0x06

arch x86

baddr 0x8048000

bintype elf

bits 32

compiler GCC: (GNU) 3.4.6 (Gentoo 3.4.6-r2, ssp-3.4.6-1.0, pie-8.7.10)

crypto false

endian little

havecode true

lang c

machine Intel 80386

maxopsz 16

minopsz 1

os linux

static false

va true

and analyze it then decompile main

[0x08048400]> pdd@main

/* r2dec pseudo code output */

/* ./crackme0x06 @ 0x8048607 */

#include <stdint.h>

int32_t main (int32_t arg_10h) {

int32_t var_78h;

int32_t var_4h;

// adjusting stack

eax = 0;

eax += 0xf;

eax += 0xf;

eax >>= 4;

eax <<= 4;

// main logic

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

printf ("Password: ");

eax = &var_78h;

scanf (0x8048787, eax);

eax = arg_10h;

eax = &var_78h;

check (eax, arg_10h);

eax = 0;

return eax;

}

main has 3 arguments argc, argv, envp, and this program is compiled with GCC, so the stack should be like this :

[esp + 0x10] - envp

[esp + 0x0c] - argv

[esp + 0x08] - argc

[esp + 0x04] - return address

enter the check() and decompile it. this function is different from 0x05 now. but they still have similar code structure.

int32_t check (char * s, int32_t arg_ch) {

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, 0x804873d);

edx = var_4h;

eax = &var_8h;

*(eax) += edx;

if (var_8h == 0x10) {

eax = arg_ch;

eax = s;

parell (eax, arg_ch);

}

eax = &var_ch;