一、何为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。
![](https://i-blog.csdnimg.cn/blog_migrate/d06038c59c1c2b6880303f715881860e.png)
![](https://i-blog.csdnimg.cn/blog_migrate/cf25aa518c53abfc6c82f21219c456e7.png)
- 情景二与情景一、三的不同:情景二的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循环中。
![](https://i-blog.csdnimg.cn/blog_migrate/d5bc17bdcead20cbdfd13935537bc2a0.png)
- 第二步:malloc去检查unsortedbin中是否有与自己malloc大小相对应的chunk可以使用,如果有与自己malloc大小相对应的chunk可以使用就直接使用;如果没有那么就去判断unsortedbin中是否有可以用来切割的大chunk可以使用,如果可以切割,就切割大的chunk使用,然后产生last remainder(这个过程发生在_int_malloc函数的for循环中)。
![](https://i-blog.csdnimg.cn/blog_migrate/e15d08713818dee08f5615fbcb5fde7c.png)
- 第三步:如果没有可以切割的大chunk可以使用,此时就将unsortedbin上的chunk放入到对应的bins链上(这个过程发生在_int_malloc函数的此处,见下图)。
![](https://i-blog.csdnimg.cn/blog_migrate/5c14a63f0ff2292375392a6d742fc4bf.png)
- 第四步:malloc从第一次分配的大堆块上面找空间来使用(这个过程发生在_int_malloc函数的此处,见下图)。
![](https://i-blog.csdnimg.cn/blog_migrate/ffea8d13885ed8b5c915aabcdd35e7b4.png)
七、FASTBIN_CONSOLIDATION_THRESHOLD
![](https://i-blog.csdnimg.cn/blog_migrate/a809db986f1b33b006bade160f8130e6.png)
- 为什么设计这个宏定义:我们知道fastbins中的fastchunk是不会进行合并的,但是当被free的fastchunk与该chunk相邻的chunk合并后的大小大于FASTBIN_CONSOLIDATION_THRESHOLD时,此时内存碎片可能就比较多了,我们就需要将fastbins中的chunk都进行合并(调用malloc_consolidate函数)以减少内存碎片。
- 何处使用:在_int_free函数中被使用,malloc_consolidate函数可以将fastbins中能和其它chunk合并的fastchunk进行合并,然后将合并后的碎片进行consolidate。
![](https://i-blog.csdnimg.cn/blog_migrate/10913f3bc09b313c8df489fdd6829561.png)
八、演示案例
#include <unistd.h>
#include <malloc.h>
int main()
{
void *p=malloc(0x30);
sleep(0); //只为了程序打断点使用,无其他作用
free(p);
void *p2=malloc(0x500);
free(p2);
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/fb36b4c071fc807bf054253c4ed0acba.png)
- 第二步:释放p,可以看到fastchunk被放到了fastbins上去了(注意:此时虽然fastchunk虽然与topchunk相邻,但是不会合并)。
![](https://i-blog.csdnimg.cn/blog_migrate/772578604eec787ed6d6af8fc5018031.png)
![](https://i-blog.csdnimg.cn/blog_migrate/72c4f2718011c8ef4b3b62da57e7cdae.png)
- 第三步:申请p2(可以看到系统去检测fastbins,发现fastbins中有一个freechunk,于是将freechunk移动到unsortedbin中,然后malloc去切割unsortedbin中的这个freechunk,发现不能够切割,于是就放入smallbin中,放入smallbin中之后便成为smallchunk了,就可以与topchunk合并了,于是就与topchunk合并。合并之后malloc从topchunk中申请一个堆块,所以下面的bins查看,可以看到bins链中没有任何freechunk),此处触发了unsortedbin的consolidate。
![](https://i-blog.csdnimg.cn/blog_migrate/e5702a86812cfb0bdfaa5f4e7dbd7ca8.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d7a33c0faa1d287b7fa0de9f41059026.png)
九、演示案例
#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;
}
![](https://i-blog.csdnimg.cn/blog_migrate/9b2eeb5cf0cc9739a2ccdf7396442eb2.png)
- 第二步:释放p,可以看到smallchunk被放到了unsortedbin上去了。
![](https://i-blog.csdnimg.cn/blog_migrate/03ab82e25d107d5cc4c107d7e6dbe677.png)
![](https://i-blog.csdnimg.cn/blog_migrate/1b57834f6b37872cc801ed3b3fe520be.png)
- 第三步:申请p2,先去切割unsortedbin是否有可以用的大freechunk,发现不可以切割来使用,就触发unsortedbin的consolidate,将0x602000这个chunk分类到smallbins中去了,然后去第一次申请的大堆块上面申请了一块堆内存来使用。
![](https://i-blog.csdnimg.cn/blog_migrate/572d5a9e8de76bb13923877f4a99ec87.png)
![](https://i-blog.csdnimg.cn/blog_migrate/b6ae182687beff7c23d356c37d8e6ce1.png)
十、演示案例
#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;
}
![](https://i-blog.csdnimg.cn/blog_migrate/fb8844ec20d035dcf0495a0881a0d5fc.png)
- 第二步:释放p和q,可以看到这两个chunk被放入了fastbins中。
![](https://i-blog.csdnimg.cn/blog_migrate/4c75ecc7eba785a0a26a9c481f1af12c.png)
![](https://i-blog.csdnimg.cn/blog_migrate/205bfd1d2cf108952d50067fae2cd204.png)
- 第三步:申请一个大于smallchunk大小的堆空间(两个在fastbins上面的空闲chunk先被整理到了unsortedbin上,然后不够malloc(0x400)使用,就被unsortedbin通过consolidate整理到了smallbins上),因为没有bins链中没有满足条件的chunk使用,所以就去第一次申请的大堆块上面取空间来使用。
- 注意:因为两个fastchunk从fastbins中移到了smallbins中,所以其fd和bk改变了(从单链表存储变为了双向循环列表存储)。
![](https://i-blog.csdnimg.cn/blog_migrate/e4c8a45fe069854f4ae4dd320afeec4b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/863cb8757b3bfd9c7032206da829a264.png)
十一、演示案例
#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;
}
![](https://i-blog.csdnimg.cn/blog_migrate/bac2c1785811933bb844301856a720da.png)
- 第二步:n几下,释放p,查看p已经被放入fastbin中。
![](https://i-blog.csdnimg.cn/blog_migrate/d7dd536b4870899fb6c19c8c08a62113.png)
![](https://i-blog.csdnimg.cn/blog_migrate/6ab08a241c7e1e7fa15490db7e99b2e5.png)
![](https://i-blog.csdnimg.cn/blog_migrate/1481ac814d0160aa25af3ae0d85e6dc7.png)
![](https://i-blog.csdnimg.cn/blog_migrate/434bcd7a679f3cc09ccd933d070d617f.png)
- 第四步:此时去malloc(0x400),此时可以看到原本在fastbin中的两个freechunk由于是物理相邻的,所以在consolidate的过程中两者被整理合并了,然后一起放入smallbin中了。
![](https://i-blog.csdnimg.cn/blog_migrate/a56954537a9889b0fd217df9654e5db7.png)
![](https://i-blog.csdnimg.cn/blog_migrate/26b8e098b35b20e67c052a60ddab2c0b.png)
- 我是小董,V公众点击"笔记白嫖"解锁更多【堆漏洞挖掘】资料内容。
![](https://i-blog.csdnimg.cn/blog_migrate/4e8489a1b95c3911ab85d46835eeb6a8.png)