largebin attack学习

想读源码可以看看这里

达到的效果

2.30之前可以往任意两个地址写一个堆地址,2.30之后只能往一个任意地址写堆地址

利用条件

存在UAF,可以修改largebin的内容

两次申请的largebin大小不能相同

largebin的结构

要知道第一点,在largebin里,几个大小相近的chunk会用一个指针进行维护,通常其存放大小大于0x400的堆块,不过一般申请0x420以上的堆块,因为低版本0x400可能会被放到tcache里

在largebin里,除了原先的堆块结构,还新增了fd_nextsize和bk_nextsize两个指针,前者指向比当前堆块小的最大chunk,后者指向比当前堆块大的最小chunk

对于对应同一个index的一堆chunk,按照以下规则排序:

1.大堆块靠前,小堆块靠后

2.对于相同大小的堆块,最先释放的堆块会成为堆头,其fd_nextsizebk_nextsize会被赋值,其余的堆块释放后都会插入到该堆头结点的下一个结点,通过fdbk链接,形成了先释放的在链表后面的排序方式,且其fd_nextsizebk_nextsize都为0。

3.不同大小的堆块通过堆头串联,即堆头中fd_nextsize指向比它小的堆块的堆头,bk_nextsize指向比它大的堆块的堆头,从而形成了第一点中的从大到小排序堆块的方式。同时最大的堆块的堆头的bk_nextsize指向最小的堆块的堆头,最小堆块的堆头的fd_nextsize指向最大堆块的堆头,以此形成循环双链表。

largebin的插入

1.在delete一个堆块时,如果其范围超过0x400(或0x420,原因前文提过了),会优先将其放于unsortedbin里,之后,如果申请一块比当前unsortedbin大的堆块,那么在遍历unsortedbin试图寻找合适堆块时,会将不合适的堆块统统放入对应的bin里,该放到smallbin的放smallbin,该放largebin的放largebin,从而我们可以获得一块largebin。 2.找到当前要插入的chunk对应的largebin的index,并定位该index中的最小的chunk:bck和最大的chunk:fwd。
3.如果fwd等于bck,表明当前链表为空,则直接将该chunk插入,并设置该chunk为该大小堆块的堆头,将bk_nextsize和fd_nextsize赋值为它本身。
4.如果fwd不等于bck,表明当前链表已经存在chunk,要做的就是找到当前chunk对应的位置将其插入。首先判断其大小是否小于最小chunk的size,(size) < (bck->bk->size),如果小于则说明该chunk为当前链表中最小的chunk,即插入位置在链表末尾,无需遍历链表(这里关系到2.31前后的区别),直接插入到链表的末尾,且该chunk没有对应的堆头,设置该chunk为相应堆大小堆的堆头,将bk_nextsize指向比它大的堆头,fd_nextsize指向双链表的第一个节点即最大的堆头。
5.如果当前chunk的size不是最小的chunk,则从双链表的第一个节点即最大的chunk的堆头开始遍历,通过fd_nextsize进行遍历,由于fd_nextsize指向的是比当前堆头小的堆头,因此可以加快遍历速度。直到找到小于等于要插入的chunk的size。
6..如果找到的chunk的size等于要插入chunk的size,则说明当前要插入的chunk的size已经存在堆头,那么只需将该chunk插入到堆头的下一个节点。
7.如果找到的chunk的size小于当前要插入chunk的size,则说明当前插入的chunk不存在堆头,因此该chunk会成为堆头插入到该位置,设置fd_nextsize与bk_nextsize。

largebin的取出

1.找到当前要申请的空间对应的largebin链表,判断第一个结点即最大结点的大小是否大于要申请的空间,如果小于则说明largebin中没有合适的堆块,需采用其他分配方式。
2.如果当前largebin中存在合适的堆块,则从最小堆块开始,通过bk_nextsize反向遍历链表,找到大于等于当前申请空间的结点。
3.为减少操作,判断找到的相应结点(堆头)的下个结点是否是相同大小的堆块,如果是的话,将目标设置为该堆头的第二个结点,以此减少将fd_nextsize与bk_nextsize赋值的操作。
4.调用unlink将目标largebin chunk从双链表中取下。
5.判断剩余空间是否小于MINSIZE,如果小于直接返回给用户。否则将剩余的空间构成新的chunk放入到unsorted bin中。

largebin attack

取出时attack

没学,想看点这里

插入时attack

2.30以前

在2.30以前,缺少对largebin attack的检查,所以我们可以大胆的进行伪造,在插入一块新的largebin时,会将当前堆块的bk->fd和bk_nextsize->fd_nextsize写成当前堆块的地址,如下图,所以如果根据下图把bk构造成targetaddr1-0x10,bk_nextsize构造成targetaddr1-0x20,即可在插入largebin时触发unlink进行同时改写两处地址为heapaddr

2.30以后

2.30之后会进行如下两个检查

这就导致在申请的堆块大于最小chunk时我们不能随意地修改bk和bk_nextsize了,为了绕过这个检查,我们要使得当前申请的堆块小于目前的最小chunk(即它是新的最小),还记得为什么吗?上文中红色的部分,因为如果它是最小它会直接被链入,没有这些乱七八糟的检查,但这也导致他只能任意写bk_nextsize指向的位置,所以在这种情况下,可以将bk_nextsize赋成targetaddr-0x20

2.34版本下,通过该打打,成功修改_IO_list_all为堆地址,可以利用这个进行后续很多操作

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇