house_of_einherjar攻击
house_of_einherjar攻击
介绍
house of einherjar 是一种堆利用技术,由 Hiroki Matsukuma 提出。该堆利用技术可以强制使得 malloc 返回一个几乎任意地址的 chunk 。其主要在于滥用 free 中的后向合并操作(合并低地址的 chunk),从而使得尽可能避免碎片化。
此外,需要注意的是,在一些特殊大小的堆块中,off-by-one 不仅可以修改下一个堆块的 prev_size,还可以修改下一个堆块的 PREV_INUSE 比特位。
攻击条件
- 可以修改下一个堆快的
prev_size位和PREV_INUSE比特位 - 可以分配大于等于
unsortedbin的chunk
攻击过程
演示poc
1 | |
堆空间申请,申请了三个利用堆块,chunk1进行了伪造,把fd和bk制作伪造为自身。利用chunk2进行溢出伪造chunk3的prev_size

然后把tcachebins填满,去free chunk3,效果如下,堆块进行了合并,造成了堆块重叠

接下来申请unsortedbin大小的空间,申请chunk2大小的空间,释放chunk2大小的两个堆块,后放入chunk2,为了绕过fd检查。然后通过申请到的unsortedbin进行修改chunk2的fd指针,可以进行任意地址申请

攻击原理
free合法性校验
当去free一个堆块的时候,调用glibc/malloc/malloc.c中的_int_free函数,该函数前面会进行校验判断,优先考虑放入tcachebins,如果tcachebins满了,且大小符合fashbin,会考虑放入fashbin,最后是放入unsortedbin。此攻击手法主要分析放入unsortedbin的分支。
当进入unsortedbin分支的时候,首先经过下面的一些校验,通过校验才会成功释放
1 | |
向前合并校验
经过合法性检查之后下面进行unlink条件判断,首先进行向前合并检查。
- 根据
prev_inuse判断,如果prev_inuse为0说明上一个chunk未在使用,通过prevsize更新指针,如果伪造prevsize大小就会造成指针指向我们伪造的地址,经过检查之后,进行向前合并操作,造成堆块重叠。
1 | |
原理图如下
伪造蓝色堆块和绿色堆块的prevsize,然后free绿色堆块

向后合并校验
如果不符合向前合并条件,就接着检查向后合并
- 如果下一个
nextchunk不是topchunk,进入分支判断下一个chunk的是否在使用,如果空闲进行合并,非空闲仅把p_inuse位置0
1 | |
unlink_chunk合法性校验
1 | |
校验绕过
经过源码分析,我们可以利用的分支只有向前合并,总结出如下需要绕过的校验
- 要释放的
chunk的prev_inuse位为0(通过堆溢出、off-by-null、off-by-one进行设置) - 被合并的
chunk的size必须和释放的prev_size相同(由于空间复用,可以编辑当前堆块,设置下一个堆块的prev_size) - 被合并的
chunk的fd-bk和bk-fd必须指向自己(通过设置fd和bk都为当前堆块的地址绕过)
湾区杯2025-digtal_bomb
题目分析
ida反编译进行简单的函数、变量重命名,然后进入welcome函数,发现题目介绍是实现了一个你和电脑共同排除炸弹的功能
首先分析main函数。让你输入一个炸弹范围,然后通过伪随机生成一个炸弹数,并且炸弹数控制在你输入的范围内。然后进入一个循环,会通过inputgGuessNum函数让你输入一个数,然后对你输入的数通过chunk1函数进行校验

我们跟进函数chunk1,如果我们猜的数是炸弹数,就会爆炸return 1,如果我们没有猜到炸弹数,就会通过update_boundary进行更新边界然后当仅剩一个数的时候,且这个数是炸弹数的时候,就会进入heapFunc函数。

继续跟进update_boundary函数,是一个更新边界的函数,通过分析我们可以实习100绕过炸弹数,开始输入499-500,然后随机数就会随机到499,然后输入500,边界更新为499-499,完成炸弹数绕过

接着进入函数heapFunc,是一个经典的堆题样式。

首先跟进add函数,只允许创建10个堆块,且有大小限制在0x10-0x800,申请的堆块地址储存在chunk_addr,然后向堆块输入数据,并在数据末位进行\x00截断,这里就造成了off-by-null漏洞

然后跟进free函数,正常的free,不存在UAF漏洞

跟进show函数,会打印堆块内容

最后跟进edit_one函数,只有一次编辑功能,且和申请的编辑不一样,不存在/x00截断,可以配合show函数进行地址泄露

漏洞利用
- 利用炸断数生成缺陷,绕过炸弹,进入heap功能
- 利用
largerbin和edit函数泄露heap地址 - 利用
off-by-null漏洞配合house_of_einherjar攻击手法造成堆块重叠 - 利用堆块重叠泄露地址泄露
libc地址 - 利用堆块重叠修改堆块
fd指针 - 打
libc.got,修改strlen的got表为onegadget
EXP
1 | |