2022柏鹭杯-note2
通过本题的学习明白了,高版本中 fastbin
做出 double free
是如何打 tcache poisoning
的过程。并且了解到了一条新的 IO
链,目前感觉是最好用的一条,可以通杀 2.36
及以下的 libc
版本 具体请见 文章
这位师傅提供了题目附件 2022年柏鹭杯 pwn题复现 - tolele - 博客园 (cnblogs.com)
题目信息
本题存在一个 UAF
漏洞,并且可以无限次的使用 add
和 delete
show
函数,size
被限定到了 0x200
以下,并且可以触发 exit
函数退出。( libc
版本为 2.35
)
解题思路
因为没有 edit
函数,因此我们考虑 double free
,但由于 key
机制的存在,无法直接在 tcache bin
直接打 double free
,解决方法有两种,第一是 house of botcake ,这个方法本题是可以打通的,不过主要的学习收获是第二种方法,就是填满 tcache bin
,然后在 fast bin
中做出 double free
,再打 tcache poisoning
将 IO_list_all
申请出来写入堆地址,从而触发最后的 IO attack
。
本文主要介绍在 fastbin
中做出的 double free
是如何打出 tcache poisoning
,至于 safe-Linking
机制的绕过和 IO_attack
不再介绍。
double free
与 tcache poisoning
malloc
函数内部执行会先进入 libc_malloc
函数,判断是否 tcache bin
的链上有需要的堆块,如果没有的话则进入 int_malloc
函数(有的话则申请出来,直接返回)
在 int_malloc
函数的最开始就去判断了 fastbin
中对应的链上是否有所需要的堆块,如果有的话就将该堆块取出,作为接下来要返回给用户的堆块。同时去判断这条链上是否还有堆块,如果还有堆块并且 tcache bin
上对应的这条链还有空位置,就将 fastbin
剩下的堆块都放入 tcache bin
中(除非 tcache bin
被填满了)
本题 double free
以及 tcache poisoning
的利用思路是先将 tcache bin
填满,然后正常的在 fastbin
链中做出 double free
(如 A->B->A
)
接着再将 tcache bin
中的堆块全部取出(此时的情况如下) 注意: fastbin
中的 fd
指针也是经过了异或运算的
ptmalloc
对于 fastbin
中堆块移入 tcache bin
的机制是这样处理的。(最初的结构为 A->B->A
)(如下)
- 首先判断
fastbin
中第一个堆块A
的fd
指针是否为空,来检测该链是否还有其他堆块 - 无论该链是否有其他堆块,都会将
A
取出来暂存(为之后返回给用户做准备),而将A
取出后fastbin
中的结构变成了B->A->B
- 如果该
fastbin
链已经没有其他堆块了,那么就将刚刚的A
返回给用户 - 如果检测出该链还有其他堆块,并且
tcache bin
对应的这条链没有满,就逐个将堆块链出fastbin
,链入tcache bin
- 因为此时的
tcache bin
是空的,那就不考虑tcache bin
被装满的这个限制,上面提到此时的结构是B->A->B
,先去移动当前fastbin
的第一个堆块B
,因为double free
的特殊性,在从fastbin
取出一个堆块B
后,其结构变为了A->B->A
此时刚刚取出的堆块还没有进入tcache bin
- 刚刚这个取出的堆块链入到
tcache bin
时,其next
指针一定会被置成0
,因为tcache bin
最初是没有堆块的,此时的fastbin
结构会受到tcache bin
中堆块B
next
指针置0
的影响,从而结构变成了A->B->0
(因为这个置空的next
指针是B
堆块的,因此并不会干扰到A->B
的这个关系) - 依次类推,从
fastbin
中取出A
然后再放入到tcachebin
中,此时的fastbin
为B->0
,tcache bin
为A->B
(LIFO
) fastbin
中最后一个B
进入tcache bin
,此时tcache bin
的结构为B->A->B
(由于确实是有三个堆块进入了tcache bin
所以此时的tcache_counts
为3
)
因为最初就确定了申请出去的是 A
,所以 malloc
返回出来 A
后,将数据写入 A
中篡改 next
指针(因为 A
此时还在 tcache bin
中),从而完成了 tcache poisoning
。因此写入数据后的结构为 B->A->address
(如下)
简单总结一下:将 tcache bin
填满,然后在 fastbin
中做 double free
,申请出一个堆块后,可以直接打 tcache poisoning
,并且不用担心 tcache_counts
的问题
因为将 IO_list_all
申请出来了,后面就是 IO_FILE
的伪造和布局,本文重点不在这里,就此略过。不过 tools函数库 封装了该 obstack
链的攻击模板,直接使用即可。
EXP
from tools import* |