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 |
|