fastbin_House Of Spirit
本文最后更新于 2024年10月13日 晚上
Fastbin_attack_House Of Spirit
House Of Spirit
原理
House of Spirit这种技术的核心在于在目标位置处伪造fastbin chunk,并将其释放,从而达到分配指定地址
的chunk的目的
与double_free的区别
double_free利用的是malloc自己生成的chunk,但是House of Spirit是为了释放任意可写地址的chunk,这个chunk可以由我们自己来构造,相比于double_free来说限制少得多
伪造检查
我们在释放这个伪造的chunk的时候他是不能够直接挂进fastbin单向链表中的,因为你在释放时,需要经过一些检查,去判断该释放的chunk是否为程序自身创建的。那么我们需要做的就是绕过这些检查
- fake chunk 的 ISMMAP 位不能为 1,因为 free 时,如果是 mmap 的 chunk,会单独处理
- fake chunk 地址需要对齐, MALLOC_ALIGN_MASK
- fake chunk 的 size 大小需要满足对应的 fastbin 的需求,同时也得对齐
- fake chunk 的 next chunk 的大小不能小于
2 * SIZE_SZ
,同时也不能大于av->system_mem
- fake chunk 对应的 fastbin 链表头部不能是该 fake chunk,即不能构成 double free 的情况
接下来我们用题目来更好的理解
2014 hack.lu oreo
add(sub_8048644)函数
我们来分析一下这个函数,它先是让v1指向dword_804A288,然后请0x38大小的chunk,并把chunk指针存在dword_804A288,重点是下面的一句代码
1 |
|
把v1存到(_DWORD *)dword_804A288 + 13的位置,而一个_DWORD *是4个字节,申请的chunk总共才56个字节,而4*13=52,所以他会把上一个chunk的指针存在现在的chunk的末尾位置
接下来是把name存在dword_804A288+25的位置,把description存在dword_804A288位置,可以轻易推出name的最大值应该只有27个字节,description的最大值应该是25个字节,但是fgets的字节是56个,可以看到这里存在堆溢出
最后是在dword_804A2A4的地方进行技术操作
这个函数的特殊在于他没有利用结构体进行操作,可以根据偏移来,这为我们利用它提供了空间
校验(sub_80485EC)函数
这个函数是一个字节的校验函数,这里基本每一个fgets后面都有
show(sub_8048729)函数
这是一个打印函数。为了打印所有已创建的chunk的内容,而块与块之间的联系就是靠存他们末尾的指针实现的
free(sub_8048810)函数
这个函数也很简单,它通过循环把所有的chunk全部释放掉
message(sub_80487B4)函数
这个函数可以在dword_804A2A8存有的指针指向的区域写入128个字节的数据
思路
泄露libc
在上面的分析中我们知道,show函数是根据每一个chunk的数据域中的chunk指针实现打印的,而add函数的溢出漏洞是可以让我们把其中的chunk指针覆盖成got表地址的,被覆盖之后再执行show函数的话,不久可以泄露出libc了吗
1 |
|
那么接下来就要想办法修改got表了
修改got表
问题就在这,我们可以通过什么方式来伪造呢?前面我们知道message函数可以往dword_804A2A8中的指针指向的区域写入数据的
可以看到dword_804A2A8存的指针是0x804a2c0
也就是这个地方数据我们是可以控制的,那么我们如果可以伪造一个chunk,并把它挂进fastbin,那么当我们再一次申请合适的chunk的时候就可以对这个fake_chunk进行操作了,这就是我们今天技术的核心,House Of Spirit
伪造fake_chunk
因为add函数申请的chunk的大小是0x38,那我们就在0x804a2a0处,伪造一个0x40大小的fake_chunk,那么那处计数的地址我们可以申请40个chunk来让它成为fake_chunk的size域
1 |
|
在伪造的时候,我们要注意一些细节来绕过检查
首先的就是地址需要对齐
其二是fake_chunk的next chunk的大小不能小于2 * SIZE_SZ,也就是0x10
其三就是fake chunk 对应的 fastbin 链表头部不能是该 fake chunk,即不能构成 double free 的情况
我个人认为早libc-2.23最重要的就这三个,wiki上的其他限制,在这道题我都试过,是没有影响的,当然我没有说wiki是错的,这可能是版本高一点加的新限制
可以看到我们是成功把fake_chunk挂进了fastbin
修改got表
那么我们再一次申请chunk,就可以对它操作,如果把原本dword_804A2A8存的指针改成strlen的got表,那么我们调用message函数的时候就是再改变strlen的got表的值
1 |
|
此时调用message函数
1 |
|
可以看到此时got表修改成功
这里面存在strlen(dword_804A2A8),这也是上面的代码中为什么/bin/sh接在后面的原因,而dword_804A2A8第一个元素是p32(system),所以要用分号来继续执行指令
最终exp
1 |
|