堆漏洞挖掘中的malloc_consolidate与FASTBIN_CONSOLIDATION_THRESHOLD

一、何为consolidate

  • 我们知道大于0x80的chunk被释放之后就放到了unsortedbin上面去,但是unsortedbin是一个未分类的bin,上面的chunk也处于未分类的状态。但是这些chunk需要在特定的条件下被整理然后放入到smallbins或者largebins中。
  • 这个整理的过程被称为unsortedbin的“consolidate”,但是“consolidate”是要在特定的条件下才会发生的,并且与malloc紧密相关。

二、consolidate的目的

  • 对堆中的碎片chunk进行合并整理,减少堆中的碎片。

三、consolidate的触发情景

  • 情景一:当我们malloc一个chunk,这个chunk的大小大于smallbin的范围,在unsortedbin中寻找可用的freechunk使用时,会触发malloc_conlolidate。

  • 情景二:发现unsortedbin中有大的freechunk可以切割给malloc使用时,切割unsortedbin,产生last remainder的时候会consolidate,见文章:https://blog.csdn.net/qq_41453285/article/details/97803141(此种情况不同于情景一,不需要考虑malloc的大小)。
  • 情景三:malloc时如果bin链中没有可以使用的freechunk,并且去切割topchunk,发现topchunk也不够用,此时回去再去调用malloc_consolidate进行一次整理。

  • 情景二与情景一、三的不同:情景二的consolidate不会去整理fastbins中的freechunk,而情景一、三的consolidate回去整理fastbins中的freechunk(在情景二的链接里有演示案例)。

四、相关注意事项

  • 申请的chunk在smallbin范围内,虽然没有触发consolidate,但是如果smallbin中没有适合的freechunk,还会向后执行,仍然可能会触发consolidate。

五、情景一的注意事项

  • 当发生consolidate时,fastbin链中的freechunk先被整理到unsortedbin上,如果不被mallco使用,之后会被放到smallbin中。
  • 我们前面知道fastbins中的freechunk是不会和任何chunk之间发生合并的,但是如果consolidate了,那么fastbin中的freechunk就会被整理,此时fastbins中的freechunk就会与物理相邻的chunk之间发生合并(例如一个fastchunk后面是一个空闲的smallchunk,那么就与后面的chunk合并。或者fastchunk与topchunk相邻,consolidate之后就与topchunk合并了,见下面的8)。

六、consolidate的情景一

  • 当我们malloc一个大小大于smallbin的chunk时:
  • 第一步:将fastbins中的chunk都整理到unsortedbin中,整理的过程中如果有物理相邻且空闲的fastchunk就合并,如果fastchunk与topchunk相邻,那么fastchunk就与topchunk合并(这个过程发生在_int_malloc函数调用的malloc_consolidate函数中)。malloc_consolidate (av)函数:只是将fastbins中的chunk进行整理放入到unsortedbin上,unsortedbin将chunk整理到其他bin链中发生在下面的for循环中。

  • 第二步:malloc去检查unsortedbin中是否有与自己malloc大小相对应的chunk可以使用,如果有与自己malloc大小相对应的chunk可以使用就直接使用;如果没有那么就去判断unsortedbin中是否有可以用来切割的大chunk可以使用,如果可以切割,就切割大的chunk使用,然后产生last remainder(这个过程发生在_int_malloc函数的for循环中)。

  • 第三步:如果没有可以切割的大chunk可以使用,此时就将unsortedbin上的chunk放入到对应的bins链上(这个过程发生在_int_malloc函数的此处,见下图)。

  • 第四步:malloc从第一次分配的大堆块上面找空间来使用(这个过程发生在_int_malloc函数的此处,见下图)。

七、FASTBIN_CONSOLIDATION_THRESHOLD

  • 为什么设计这个宏定义:我们知道fastbins中的fastchunk是不会进行合并的,但是当被free的fastchunk与该chunk相邻的chunk合并后的大小大于FASTBIN_CONSOLIDATION_THRESHOLD时,此时内存碎片可能就比较多了,我们就需要将fastbins中的chunk都进行合并(调用malloc_consolidate函数)以减少内存碎片。
  • 何处使用:在_int_free函数中被使用,malloc_consolidate函数可以将fastbins中能和其它chunk合并的fastchunk进行合并,然后将合并后的碎片进行consolidate。

八、演示案例

#include <unistd.h>
#include <malloc.h>

int main()
{
    void *p=malloc(0x30);

    sleep(0); //只为了程序打断点使用,无其他作用
    free(p);

    void *p2=malloc(0x500);
    free(p2);
    return 0;
}
  • 第一步:打断点到sleep,然后运行程序。

  • 第二步:释放p,可以看到fastchunk被放到了fastbins上去了(注意:此时虽然fastchunk虽然与topchunk相邻,但是不会合并)。

  • 第三步:申请p2(可以看到系统去检测fastbins,发现fastbins中有一个freechunk,于是将freechunk移动到unsortedbin中,然后malloc去切割unsortedbin中的这个freechunk,发现不能够切割,于是就放入smallbin中,放入smallbin中之后便成为smallchunk了,就可以与topchunk合并了,于是就与topchunk合并。合并之后malloc从topchunk中申请一个堆块,所以下面的bins查看,可以看到bins链中没有任何freechunk),此处触发了unsortedbin的consolidate。

九、演示案例

#include <unistd.h>
#include <malloc.h>

int main()
{
    void *p=malloc(0x200);
    void *temp=malloc(0x30); //为了达到演示效果,阻止p释放后与topchunk合并

    sleep(0); //只为了程序打断点使用,无其他作用
    free(p);

    void *p2=malloc(0x500);
    free(p2);
    return 0;
}
  • 第一步:打断点到sleep,然后运行程序。

  • 第二步:释放p,可以看到smallchunk被放到了unsortedbin上去了。

  • 第三步:申请p2,先去切割unsortedbin是否有可以用的大freechunk,发现不可以切割来使用,就触发unsortedbin的consolidate,将0x602000这个chunk分类到smallbins中去了,然后去第一次申请的大堆块上面申请了一块堆内存来使用。

十、演示案例

#include<malloc.h>
#include<unistd.h>

int main(){
    int size = 0x60;
    void *p = malloc(size);
    void *junk = malloc(size);
    void *q = malloc(size);
    void *r = malloc(size); //防止q被释放之后,与topchunk合并

	
    sleep(0); //只为了打断点使用,无其他意义
    free(p);
    free(q);

    malloc(0x400);

    return 0;
}
  • 第一步:打断点到sleep,运行程序。

  • 第二步:释放p和q,可以看到这两个chunk被放入了fastbins中。

  • 第三步:申请一个大于smallchunk大小的堆空间(两个在fastbins上面的空闲chunk先被整理到了unsortedbin上,然后不够malloc(0x400)使用,就被unsortedbin通过consolidate整理到了smallbins上),因为没有bins链中没有满足条件的chunk使用,所以就去第一次申请的大堆块上面取空间来使用。
  • 注意:因为两个fastchunk从fastbins中移到了smallbins中,所以其fd和bk改变了(从单链表存储变为了双向循环列表存储)。

十一、演示案例

#include<malloc.h>
#include<unistd.h>

int main(){
    int size = 0x60;
    void *p = malloc(size);
    void *q = malloc(size);
    void *r = malloc(size); //防止q被释放之后,与topchunk合并


    sleep(0); //只为了打断点使用,无其他意义
    free(p);
    free(q);

    malloc(0x400);

    return 0;
}
  • 第一步:打断点到sleep,运行程序。

  • 第二步:n几下,释放p,查看p已经被放入fastbin中。

  • 第三步:再释放q。

  • 第四步:此时去malloc(0x400),此时可以看到原本在fastbin中的两个freechunk由于是物理相邻的,所以在consolidate的过程中两者被整理合并了,然后一起放入smallbin中了。


  • 我是小董,V公众点击"笔记白嫖"解锁更多【堆漏洞挖掘】资料内容。

  • 12
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

董哥的黑板报

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值