堆漏洞挖掘:13---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

堆漏洞挖掘:13---malloc_consolidate与FASTBIN_CONSOLIDATION_THRESHOLD_第1张图片

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

堆漏洞挖掘:13---malloc_consolidate与FASTBIN_CONSOLIDATION_THRESHOLD_第2张图片

情景二与情景一、三的不同:情景二的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合并了,见下面的八)

六、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循环中

堆漏洞挖掘:13---malloc_consolidate与FASTBIN_CONSOLIDATION_THRESHOLD_第3张图片

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

堆漏洞挖掘:13---malloc_consolidate与FASTBIN_CONSOLIDATION_THRESHOLD_第4张图片

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

堆漏洞挖掘:13---malloc_consolidate与FASTBIN_CONSOLIDATION_THRESHOLD_第5张图片

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

堆漏洞挖掘:13---malloc_consolidate与FASTBIN_CONSOLIDATION_THRESHOLD_第6张图片

七、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 
#include 

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

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

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

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

堆漏洞挖掘:13---malloc_consolidate与FASTBIN_CONSOLIDATION_THRESHOLD_第7张图片堆漏洞挖掘:13---malloc_consolidate与FASTBIN_CONSOLIDATION_THRESHOLD_第8张图片

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

堆漏洞挖掘:13---malloc_consolidate与FASTBIN_CONSOLIDATION_THRESHOLD_第9张图片堆漏洞挖掘:13---malloc_consolidate与FASTBIN_CONSOLIDATION_THRESHOLD_第10张图片

九、演示案例

#include 
#include 

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上去了

堆漏洞挖掘:13---malloc_consolidate与FASTBIN_CONSOLIDATION_THRESHOLD_第11张图片堆漏洞挖掘:13---malloc_consolidate与FASTBIN_CONSOLIDATION_THRESHOLD_第12张图片

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

堆漏洞挖掘:13---malloc_consolidate与FASTBIN_CONSOLIDATION_THRESHOLD_第13张图片堆漏洞挖掘:13---malloc_consolidate与FASTBIN_CONSOLIDATION_THRESHOLD_第14张图片

十、演示案例

#include
#include

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中

堆漏洞挖掘:13---malloc_consolidate与FASTBIN_CONSOLIDATION_THRESHOLD_第15张图片堆漏洞挖掘:13---malloc_consolidate与FASTBIN_CONSOLIDATION_THRESHOLD_第16张图片

  • 第三步:申请一个大于smallchunk大小的堆空间(两个在fastbins上面的空闲chunk先被整理到了unsortedbin上,然后不够malloc(0x400)使用,就被unsortedbin通过consolidate整理到了smallbins上),因为没有bins链中没有满足条件的chunk使用,所以就去第一次申请的大堆块上面取空间来使用

注意:因为两个fastchunk从fastbins中移到了smallbins中,所以其fd和bk改变了(从单链表存储变为了双向循环列表存储)

堆漏洞挖掘:13---malloc_consolidate与FASTBIN_CONSOLIDATION_THRESHOLD_第17张图片堆漏洞挖掘:13---malloc_consolidate与FASTBIN_CONSOLIDATION_THRESHOLD_第18张图片

十一、演示案例

#include
#include

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中

堆漏洞挖掘:13---malloc_consolidate与FASTBIN_CONSOLIDATION_THRESHOLD_第19张图片堆漏洞挖掘:13---malloc_consolidate与FASTBIN_CONSOLIDATION_THRESHOLD_第20张图片

  • 第三步:再释放q

堆漏洞挖掘:13---malloc_consolidate与FASTBIN_CONSOLIDATION_THRESHOLD_第21张图片堆漏洞挖掘:13---malloc_consolidate与FASTBIN_CONSOLIDATION_THRESHOLD_第22张图片

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

堆漏洞挖掘:13---malloc_consolidate与FASTBIN_CONSOLIDATION_THRESHOLD_第23张图片堆漏洞挖掘:13---malloc_consolidate与FASTBIN_CONSOLIDATION_THRESHOLD_第24张图片

你可能感兴趣的:(堆漏洞挖掘)