首先我们现在main函数下断点,观察此时内存情况
可以看到此时在虚拟内存中系统还没有给我们开辟堆
然后我们运行完第一个malloc之后
可以看到此时出现了一片很大的堆空间,再用heap命令观察
在fastbin中出现了一个0x21(33)大小的chunk,我们申请了0x10,为什么会是0x21呢,这就涉及到了一个chunk的最小大小,chunk是有格式的,由chunk头和用户数据区组成(使用中),其中chunk头由prev_size和size组成(之后会说),用户数据区才是我们申请的0x10
我们称运行过程中被malloc分配的内存为一个chunk,这块内存在ptmalloc中用malloc_chunk结构体表示,当程序申请的chunk被free时,会被加入相应的空闲管理列表中(也就是bins)。
由上图知道,chunk由一个统一的结构体声明,但是它的神奇之处在于,在被使用时和空闲时却又有两种不同的状态
prev_size :如果前一个chunk是空闲的,该域表示前一个chunk的大小,如果前一个chunk不空闲,该域无意义
chunk的复用:chunk可以使用它的下一个chunk的prev_size字段
size :当前chunk的大小,并且它的二进制的后三位为标记位,记录了当前chunk和前一个chunk的一些属性,重点是最后一位(P位)
PREV_INUSE:记录前一个chunk是否被分配
fd :指向了下一个(非物理相邻)空闲的chunk,其实也就是前一个被free的chunk
bk :指向了上一个(非物理相邻)空闲的chunk,就是后一个被free的chunk
因为bins采取链表管理,新的chunk是往前插入(伪链表头),有点类似于栈,在下边实例2可以直观看到
fd_nextsize :指向前一个与当前大小不同的第一个空闲块,不包含bin的头指针(用于large chunk)
bk_nextsize :指向了后一个与当前chunk大小不同的第一个空闲块,不包含bin的头指针(用于large chunk)
Ptmalloc使用chunk实现内存管理,对chunk的管理基于独特的边界标记法;重要的是对地址的对齐。
Ptmalloc的地址对齐方式依赖平台定义的size_t长度,对于32位平台,size_t长度为4字节,对Linux x86_64为8字节
以64位为例
prev_size = 8byte
size = 8byte
所以一个使用中 的chunk的大小的计算公式应该是:
加16也就是prev_size和size的大小,减去8是因为向一个chunk“借”了8B(prev_size)
所以在64位平台上一个最小chunk的大小为0x20(chunk header+fd+bk),再加上地址的对齐因素,所以size字段的低三位永远不会被使用,所以可以用来当作flag位
堆的释放一般都是用free函数实现。堆释放后,会被添加到相应bins中进行管理;对于空闲的chunk,ptmalloc采用分箱式内存管理方式,根据空闲chunk的大小和处于的状态将其放在四个不同的bin中,这四个空闲chunk的容器包括fast bin,unsorted bin,small bin 和 large bin
glibc malloc分配了若干个bins,为了方便查找,glibc提供了两个数组:fastbinY和bins
Bins,英文解释为垃圾桶,在这里就是存放free的chunk
采用链表管理
执行完四个malloc后
一个独有的特点:
fastbin无论在使用中还是free后,它的inuse位都是置1的
运行完第一个free后
我这里出现了tcachebins,按理说应该是fastbins,查资料
tcache 是glibc2.26之后引进的一种新机制,类似于fastbin一样的东西,每条链上最多可以有7个chunk,free的时候当tcache满了才放入fastbin,unsortbin中,当malloc的时候,优先去tcache找
我们先从glibc2.23开始学习,所以用patchelf更换成2.23,gdb再次调试
好,这样就可以看到fastbins中已经有了一个chunk的指针,然后我们再free一个chunk
可以看到fastbins链表的第一个chunk为新free的chunk
可以看到第二个chunk的fd指针变为了第一个chunk的地址
依次运行完四个free后,情况也是一样
fastbins主要是用于提高小内存的分配效率,默认情况下,对于SIZE_SZ为4B的平台,小于64B的chunk分配请求,对于SIZE_SZ为128B的chunk分配请求,首先会查找fastbins中是否有所需大小的chunk存在(精确匹配),如果存在,就直接返回。(glibc2.23)
fastbins采用单链表管理。其他bins采用双链表
而对于大小超出fastbins范围的chunk,会先到unsortedbin中。
分配时,如果在unsorted bin中没有合适的chunk,就会把unsorted bin 中所有的chunk分别加入到所属的bin中,然后再在bin中分配合适的chunk。
下面进行验证
我们把第一个chunk改为0x110大小,再看第一次free后的结果
可以看到出现在了unsortedbin中,符合验证。
再看再次malloc(0x110)之后的结果
可以看到已经被分配出去了
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2021-6-18 23:46
被77pray编辑
,原因: