loading...

IOLI crackmes - 0x00 to 0x02

aibhstin profile image Aibhstin ・5 min read

0x00

> ./crackme0x00
IOLI Crackme Level 0x00
Password: password
Invalid Password!

We start with crackme 0x00. This one is solved simply by viewing the strings in the program, which is achieved here using radare2.

> r2 crackme0x00
 -- I endians swap.
[0x08048360]> 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] Check for objc references
[x] Check for vtables
[x] Type matching analysis for all functions (aaft)
[x] Propagate noreturn information
[x] Use -AA or aaaa to perform additional experimental analysis.
[0x08048360]> iz
[Strings]
nth paddr      vaddr      len size section type  string
―――――――――――――――――――――――――――――――――――――――――――――――――――――――
0   0x00000568 0x08048568 24  25   .rodata ascii IOLI Crackme Level 0x00\n
1   0x00000581 0x08048581 10  11   .rodata ascii Password: 
2   0x0000058f 0x0804858f 6   7    .rodata ascii 250382
3   0x00000596 0x08048596 18  19   .rodata ascii Invalid Password!\n
4   0x000005a9 0x080485a9 15  16   .rodata ascii Password OK :)\n

We see 5 strings. Three of these are seen when executing the binary and trying a password, one is the 'mission pass' message, and one is a mysterious numeric string. Trying this as the password:

> ./crackme0x00
IOLI Crackme Level 0x00
Password: 250382
Password OK :)

0x01

> ./crackme0x01 
IOLI Crackme Level 0x01
Password: password
Invalid Password!

Let's see if we can find another conveniently placed password string using radare2:

> r2 crackme0x01
 -- I thought we were friends. :_
[0x08048330]> 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] Check for objc references
[x] Check for vtables
[x] Type matching analysis for all functions (aaft)
[x] Propagate noreturn information
[x] Use -AA or aaaa to perform additional experimental analysis.
[0x08048330]> iz
[Strings]
nth paddr      vaddr      len size section type  string
―――――――――――――――――――――――――――――――――――――――――――――――――――――――
0   0x00000528 0x08048528 24  25   .rodata ascii IOLI Crackme Level 0x01\n
1   0x00000541 0x08048541 10  11   .rodata ascii Password: 
2   0x0000054f 0x0804854f 18  19   .rodata ascii Invalid Password!\n
3   0x00000562 0x08048562 15  16   .rodata ascii Password OK :)\n

This time, no such look. Let's see what functions r2 can detect:

[0x08048330]> afl
0x08048330    1 33           entry0
0x080482fc    1 6            sym.imp.__libc_start_main
0x08048380    6 47           sym.__do_global_dtors_aux
0x080483b0    4 50           sym.frame_dummy
0x080484e0    4 35           sym.__do_global_ctors_aux
0x080484d0    1 5            sym.__libc_csu_fini
0x08048504    1 26           sym._fini
0x08048460    4 99           sym.__libc_csu_init
0x080484d5    1 4            sym.__i686.get_pc_thunk.bx
0x080483e4    4 113          main
0x080482d4    1 23           sym._init
0x08048354    3 33           fcn.08048354
0x0804830c    1 6            sym.imp.scanf
0x0804831c    1 6            sym.imp.printf

Let's seek to main and see what we can deduce:

[0x0804854c]> s main
[0x080483e4]> pdf
            ; DATA XREF from entry0 @ 0x8048347
┌ 113: int main (int argc, char **argv, char **envp);
│           ; var uint32_t var_4h @ ebp-0x4
│           ; var int32_t var_18h @ esp+0x4
│           0x080483e4      55             push ebp
│           0x080483e5      89e5           mov ebp, esp
│           0x080483e7      83ec18         sub esp, 0x18
│           0x080483ea      83e4f0         and esp, 0xfffffff0
│           0x080483ed      b800000000     mov eax, 0
│           0x080483f2      83c00f         add eax, 0xf                ; 15
│           0x080483f5      83c00f         add eax, 0xf                ; 15
│           0x080483f8      c1e804         shr eax, 4
│           0x080483fb      c1e004         shl eax, 4
│           0x080483fe      29c4           sub esp, eax
│           0x08048400      c70424288504.  mov dword [esp], str.IOLI_Crackme_Level_0x01 ; [0x8048528:4]=0x494c4f49 ; "IOLI Crackme Level 0x01\n" ; const char *format
│           0x08048407      e810ffffff     call sym.imp.printf         ; int printf(const char *format)
│           0x0804840c      c70424418504.  mov dword [esp], str.Password: ; [0x8048541:4]=0x73736150 ; "Password: " ; const char *format
│           0x08048413      e804ffffff     call sym.imp.printf         ; int printf(const char *format)
│           0x08048418      8d45fc         lea eax, [var_4h]
│           0x0804841b      89442404       mov dword [var_18h], eax
│           0x0804841f      c704244c8504.  mov dword [esp], 0x804854c  ; [0x804854c:4]=0x49006425 ; const char *format
│           0x08048426      e8e1feffff     call sym.imp.scanf          ; int scanf(const char *format)
│           0x0804842b      817dfc9a1400.  cmp dword [var_4h], 0x149a
│       ┌─< 0x08048432      740e           je 0x8048442
│       │   0x08048434      c704244f8504.  mov dword [esp], str.Invalid_Password ; [0x804854f:4]=0x61766e49 ; "Invalid Password!\n" ; const char *format
│       │   0x0804843b      e8dcfeffff     call sym.imp.printf         ; int printf(const char *format)
│      ┌──< 0x08048440      eb0c           jmp 0x804844e
│      ││   ; CODE XREF from main @ 0x8048432
│      │└─> 0x08048442      c70424628504.  mov dword [esp], str.Password_OK_: ; [0x8048562:4]=0x73736150 ; "Password OK :)\n" ; const char *format
│      │    0x08048449      e8cefeffff     call sym.imp.printf         ; int printf(const char *format)
│      │    ; CODE XREF from main @ 0x8048440
│      └──> 0x0804844e      b800000000     mov eax, 0
│           0x08048453      c9             leave
└           0x08048454      c3             ret

We see something interesting at 0x0804841f. An address is loaded into memory. If you examine this offset you will see the "Invalid password" message. At 0x08048432 we see a jump is made based on a previous comparison. A double-word value at var_4h is compared with the hexadecimal value 0x149a. This has a decimal value of 5274. Let's try this as the password:

> ./crackme0x01
IOLI Crackme Level 0x01
Password: 5274
Password OK :)

0x02

> ./crackme0x02
IOLI Crackme Level 0x02
Password: password
Invalid Password!

Let's look at this program in r2:

> r2 crackme0x02 
 -- It's the year of radare2 on the desktop
[0x08048330]> aaaa
[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] Check for objc references
[x] Check for vtables
[x] Type matching analysis for all functions (aaft)
[x] Propagate noreturn information
[x] Use -AA or aaaa to perform additional experimental analysis.
[x] Finding function preludes
[x] Enable constraint types analysis for variables
[0x08048330]> afl
0x08048330    1 33           entry0
0x080482fc    1 6            sym.imp.__libc_start_main
0x08048380    6 47           sym.__do_global_dtors_aux
0x080483b0    4 50           sym.frame_dummy
0x08048500    4 35           sym.__do_global_ctors_aux
0x080484f0    1 5            sym.__libc_csu_fini
0x08048524    1 26           sym._fini
0x08048480    4 99           sym.__libc_csu_init
0x080484f5    1 4            sym.__i686.get_pc_thunk.bx
0x080483e4    4 144          main
0x080482d4    1 23           sym._init
0x08048354    3 33           fcn.08048354
0x0804830c    1 6            sym.imp.scanf
0x0804831c    1 6            sym.imp.printf

Let's seek to main and disassemble like last time. The output is too much to include here, so I'll only include the important part:

│           0x0804842b      c745f85a0000.  mov dword [var_8h], 0x5a    ; 'Z' ; 90
│           0x08048432      c745f4ec0100.  mov dword [var_ch], 0x1ec   ; 492
│           0x08048439      8b55f4         mov edx, dword [var_ch]
│           0x0804843c      8d45f8         lea eax, [var_8h]
│           0x0804843f      0110           add dword [eax], edx
│           0x08048441      8b45f8         mov eax, dword [var_8h]
│           0x08048444      0faf45f8       imul eax, dword [var_8h]
│           0x08048448      8945f4         mov dword [var_ch], eax
│           0x0804844b      8b45fc         mov eax, dword [var_4h]
│           0x0804844e      3b45f4         cmp eax, dword [var_ch]

We have two hexadecimal values moved into different positions on the stack, here given helpful variable names. They are then added together at 0x0804843f. This value is then multiplied by itself. A comparison is then made between what the user supplied as input and this value. The two hexadecimal values added together (in decimal) make 582. This value squared is 338724. Let's try this as the password:

> ./crackme0x02 
IOLI Crackme Level 0x02
Password: 338724
Password OK :)

Posted on by:

aibhstin profile

Aibhstin

@aibhstin

I'm an Ethical Hacking & Cybersecurity student and a Haskell programmer.

Discussion

markdown guide