行业新闻

How2heap--fastbin_dup_consolidate(by glibc-2.23)

How2heap--fastbin_dup_consolidate(by glibc-2.23)

fastbin_dup_consolidate.c 源码

image-20201215015112694.png

调试分析

首先malloc两个0x40大小的fastbin chunk

image-20201215015312576.png

同样申请0x40,加上0x10大小的chunk头,1字节的假大小(由于inuse位为1),实际大小为0x50

继续调试,对p1进行了free

image-20201215015535667.png

p1被放进fastbin的空闲链表

然后再malloc一个0x400大小的largbin chunk

来看一下_int_malloc()源码

image-20201216015034005.png

检查是否是fastbin范围

image-20201216015217168.png

检查是否是smallbin范围

image-20201216015245918.png

都不是就判断属于largebin

image-20201216015307573.png

可以看到这里在获取了largebin的下表后会检查在分配区(av)内是否有fast chunk (本例有)

如果有则触发malloc_consolidate,对分配区内的chunk进行合并分类

查看consolidate源码

image-20201216020654470.png

image-20201216020945739.png

主要做的就是向前合并、向后合并相邻的chunk,如果相邻的是top chunk则并入top chunk,重复这三步直到fastbin链表为空,且合并后的chunk会放到unsortedbin中,除了top chunk

而这里在free完p1后malloc了一个0x400大小的chunk

image-20201216020945739.png

0x400 = 1024,实际分配大小为0x400 + 0x10 = 0x410

大于1024字节的chunk会从largebins中申请

此时就会触发malloc_consolidate

p1就会从fastbin中被放到unsortedbin

之后会先在unsortedbin里面整理查找是否有符合大小的chunk,在这个过程中p1就会被分类到smallbin中(因为这里已经没有去fastbin的选择了)

这个过程我们没有跟踪所以我们查看heap的时候会看到0x40大小的p1 chunk被分到了smallbin中而不是unsortedbin

image-20201216022759341.png

然后unsortedbin为空,仍未返回需要大小的chunk,则在largebin中查找是否有合适大小的chunk(这里就不是'exact fit'了),由于largebin此时为空,则在lastremainder中切割一块0x410大小的chunk出来返回给用户,并将剩下的lastremainder保存为top chunk

image-20201216022905077.png

而由于在consolidate的过程中p1被移动到smallbin中了,fastbin现在没有记录p1

image-20201216023102256.png

所以我们可以再次free p1

image-20201216023133009.png

现在,我们就同时在fastbin和smallbin里有p1

image-20201216023220130.png

我们就可以malloc p1两次

第一次malloc结束

image-20201216023306027.png

image-20201216023416344.png

p1从原来的fastbin记录变为了smallbin

第二次malloc结束

image-20201216023328468.png

image-20201216023502296.png

p1被malloc两次才变为allocated状态

image-20201216023743030.png

此时就发生了 'double free',两次申请的chunk指针指向同一块内存,造成了

关闭