首页
社区
课程
招聘
[原创]关于fastbin合并问题的研究
发表于: 2020-2-19 11:03 10207

[原创]关于fastbin合并问题的研究

2020-2-19 11:03
10207

最近做题遇到了fastbin合并相关的内容,对于合并时机与合并过程一头雾水,于是结合glibc源码(glibc-2.23)看了看,做个小总结。

首先帮助大家快速回顾一下fastbin,直接从走位的文章中搬运了过来。fastbin的chunksize为16到80字节,在内存分配和释放中,fastbin是速度最快的。fastbin的两个特点:
1、fastbin的个数为10个。
2、fastbin由单链表构成,无论是添加还是移除fastchunk,都对链表尾进行操作,采取后入先出算法。fastbinsY数组中每个fastbin元素均指向了该链表的rear end(尾结点),而尾结点通过其fd指针指向前一个结点。
如图所示:

fastbin会在以下情况下进行合并(合并是对所有fastbin中的chunk而言)。
malloc:
1、在申请large chunk时。
2、当申请的chunk需要申请新的top chunk时。
free:
3、free的堆块大小大于fastbin中的最大size。(注意这里并不是指当前fastbin中最大chunk的size,而是指fastbin中所定义的最大chunk的size,是一个固定值。)
另外:malloc_consolidate既可以作为fastbin的初始化函数,也可以作为fastbin的合并函数。

截取了malloc中的部分关键代码。其中nb为所申请的chunk的真实大小。

第一个malloc_consolidate (av)的作用是初始化fastbin,在这里跳过。我们聚焦第二个malloc_consolidate (av)。这里首先进行了in_smallbin_range (nb),判断所申请的大小是否在smallbin所定义的大小中,如果不是,则会对fastbin进行合并。我们来写个小程序验证一下。

在free了ptr1与ptr2之后,此时的堆情况:

在malloc了一个large chunk之后,此时的堆情况:

我们发现fastbin已经进行了合并。
这里有人可能觉得这么做太激进了,因为可能在我们申请large chunk的时候根本用不上这些释放的空间,但是首先这能很好的解决碎片化问题,其次程序很少会连续的既使用小堆块,又使用大堆块,因此这种情况发生的并不多。

首先看一下关键代码

首先判断top chunk的size是否足够我们进行下一次的分配,如果不够,那么判断是否有fastbin的存在,如果存在fastbin,那么则进行合并。然后再去与smallbin和largebin匹配。如果都不匹配,则扩展top chunk。
我们还是通过一个小程序来说明

在malloc(0x70)之前,此时top chunk的size已经小于0x70

此时的堆情况

然后我们再申请一个比较小但是大于top size的堆

此时对fastbin进行了合并。

在free(chunk)的时候,如果chunk的大小大于fastbin中所定义的最大堆块的大小,则进行合并。

这里还是拿小程序进行演示。

在free(ptr1),free(ptr2)之后,此时的堆情况

在free(ptr4)以后的堆情况

可以看到fastbin被合并了。这里需要注意由于是合并到了unsortbin中,所以有时我们可以利用这里泄漏出libc基地址。

那么fastbin到底是怎么在进行合并的呢?这里我们结合malloc_consolidate函数来分析

大概过程(会循环fastbin中的每一块):
1、首先将与该块相邻的下一块的PREV_INUSE置为1。
2、如果相邻的上一块未被占用,则合并,再判断相邻的下一块是否被占用,若未被占用,则合并。
3、不管是否完成合并,都会把fastbin或者完成合并以后的bin放到unsortbin中。(如果与top chunk相邻,则合并到top chunk中)这点尤其要注意,这也是为什么可以泄漏出libc基地址的原因。
还是通过小程序来演示:


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 8
支持
分享
最新回复 (1)
雪    币: 2510
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
帮顶
2020-2-23 13:24
1
游客
登录 | 注册 方可回帖
返回
//