美文网首页CTF-PWN程序员
理解glibc的堆管理策略

理解glibc的堆管理策略

作者: 91a96ee9d8f9 | 来源:发表于2017-08-06 12:40 被阅读500次

说明:CTF的pwn题很多与malloc()与free()有关
这关系到系统堆管理策略的实现
这一节主要讨论主流的堆管理策略glibc在系统中的结构和一些基本概念
本文主要是一篇国外写的挺好的介绍堆的博客的翻译+读书笔记,建议可以读一读
原文地址:https://sploitfun.wordpress.com/2015/02/10/understanding-glibc-malloc/
以后会深入学习堆管理策略的实现和堆机制漏洞攻击的方法
最后推荐一个在线画结构图、流程图、思维导图的网站:https://www.processon.com

历史沿革

常常用到的堆管理策略主要有以下几种

  • dlmalloc – General purpose allocator
  • ptmalloc2 – glibc
  • jemalloc – FreeBSD and Firefox
  • tcmalloc – Google
  • libumem – Solaris

ptmalloc2最初由dlmalloc修改而来,后来ptmalloc2加入了多线程机制的支持,从此与dlmalloc渐渐区分开来,现在是linux的默认内存管理策略。
dlmalloc为多个线程维护一个堆,多个线程调用malloc时只能依次执行。ptmalloc为每个线程分配一个arena,在各个线程专属的arena中进行堆管理,因此可以同时处理多个线程的malloc调用,该机制称为Per Thread Arena

实现细节

调用的系统函数

  1. brk:改变程序退出的节点地址所在,一般情况下,程序退出节点位于数据段末尾后内存,但是堆管理过程需要在数据段后附加新数据(堆),因此调用系统函数brk()增加内存空间
  2. mmap:与brk直接粗暴的改变程序退出节点不同,mmap用来添加新的映射到其余的内存地址中,堆管理在映射到的内存地址中进行

malloc()

  1. 调用malloc后,会根据情况调用brk和mmap两个系统函数创建堆
  • brk:当主线程调用malloc(),且请求的内存大小较小时(<128KB),使用brk分配堆
    直接在数据段之后请求一段内存负责堆管理,返回的内存比请求的内存更大,以用于后续的需求
  • mmap:当普通线程调用malloc()时,调用mmap()系统函数将线程的arena分配到映射的内存空间中
  1. 堆会维护一个freelist(glibc里面称为bin)来对堆中未被使用的内存地址进行记录,如果在同一个arena中请求堆,先检查bin中是否有free的堆地址,如果堆不够用时,才会向内核请求增加arena的内存大小

free()

调用free()函数并不会将malloc()分配的内存释放掉,仅仅是将free的内存地址加入bin,在下一次malloc的时候可以使用

堆结构

堆结构分为三层:arena、heap、chunk
这里绘制了一副图表明堆,类似的这样的图网上还有很多

arena

  1. arena的个数有上限,通常为CPU核心的个数2(32位系统)8(64位系统),如果超过了这一上限,则内核可能将多个线程的堆映射到一个arena
  2. 一个arena可以维护多个堆,但是只维护一个malloc_state(即Arena Header)
只有一个堆的内存地址

当当前堆内存地址空间不足时,调用mmap()在内存空间中映射一个新的堆出来,映射出来后的结果如下

heap

  1. 如果一个arena维护了多个堆,每个堆需要维护一个heap_info(即Heap Header)。但main arena是例外,因为他不需要调用mmap,只需要往后增加内存大小就可以,他只用维护一个堆就好
  2. main heap

chunk

chunk是堆中分出的数据块,每个chunk是一个连续的内存地址,用来存放比如数组等程序运行时的数据
chunk分为四种类型

  • Allocated chunk
  • Free chunk
  • Top chunk
  • Last Remainder chunk

1. allocated chunk

被分配了的在使用中的chunk

image.png
  • prev chunk:记录上一个chunk的大小,将chunk想象成一个单链表,prev chunk就是chunk上的上一个数据单元,不同的chunk间是不连续的
  • chunk size:记录当前chunk的大小,其中,包含三比特的符号位
    • N:置0表示该chunk属于main arena
    • P:置1表示prev chunk在使用中(没有被free掉)
    • M:置1表示该chunk是调用mmap而产生的(即被映射到了其他的内存空间中)

2. free chunk

记录在bin中未被使用的chunk。两个chunk不能是地址连续的,否则会被合并掉
除了allocated chunk中记录的数据外,free chunk还记录了一些指针指向bin中记录的上一个/下一个free chunk的地址

bin

bin即freelist,维护一个记录freechunk地址的列表,根据free chunk的大小不同分为4种chunk

  • Fast bin
  • Small bin
  • Large bin
  • Unsorted bin(还没有排序过大小的chunk,排序后分为上述三类)
  1. bins数组用于记录Small bin、Large bin、Unsorted bin。fastbinsY记录fast bin,共包含10个bin。bins数组包含共126个bin,第1个bin记录unsorted chunks,Bin 2-63是Small bin,Bin 64-126是Large bin
  2. fast bins:
  • 单链表FILO(first in last out),每个freechunk维护一个fd指针指向bin中记录的下一个fast chunk的地址
  • 每个bins记录的chunk大小一致,第0个bin记录8字节的chunk,第一个记录16字节,第二个记录24字节,此后递增
  • fast chunks可以是内存地址上连续的,这是chunk中的一个例外


  1. unsorted bins:
  • 当small 和large chunk被free后,chunk会被加入到unsorted bins
  • 双链表,在调用malloc()时会首先检查是否有unsorted chunk,然后根据size决定将他分类或者合并
  1. small bins:
  • 双链表FIFO(first in first out)
  • 与fast bins类似,以8个字节为单位分类bin。smallchunk的尺寸大小为120~512字节
  • free时,先检查前/后一个chunk是否是free的,如果是,则合并,之后加入到unsorted中
  1. large bins:
  • 类似于一个网状的链表,有多个指针,除了指向list中的下/上一个指针,还会指向按照size排序比他大/小一点的其他chunk
  • 不同的bin维护不同size范围的large chunk,但是同一个bin中记录的chunk size不一定相等
  • 调用malloc时,找到size相等或者最相近的那个large chunk,再将其分为两部分,一部分叫做:used chunk,另外一部分叫做remaining chunk,归入unsorted bin重新分配
  • 调用free过程与small chunk类似

3. Top Chunk

堆中最高地址处的chunk,不属于任何bin,当最大的chunk都不能满足用户的需求时,调用此处chunk,如果还不够,则调用系统函数增加top chunk

4. Last Remainder Chunk

unsorted bin中存放的最后一个没有被使用的chunk

相关文章

  • 理解glibc的堆管理策略

    说明:CTF的pwn题很多与malloc()与free()有关这关系到系统堆管理策略的实现这一节主要讨论主流的堆管...

  • Glibc中堆管理的变化

    前言 在学pwn的道路上,我们大多从linux入手,从栈到堆,各种漏洞利用,都和Glibc或多或少打过交道。我的堆...

  • 堆相关数据结构

    本文只捡练了一些(以32位系统为例),高手绕过,参考:CTF-wiki堆,glibc内存管理ptmalloc2源码...

  • Glibc Heap 利用之初识 Unlink

    0x0 malloc_chunk 详解 在Glibc管理堆的过程中,无论一个内存块(chunk)是处于已分配状态还...

  • 理解Linux堆内存管理

    一、堆的基础知识 1.1 堆的内存布局 1.2 堆和栈的区别 栈主要用来维护函数调用的上下文,由高向低增长; 堆用...

  • unlink

    堆 pwn glibc中间维护的bins其实是用来存放malloc时从heap中割下来的堆,为了避免在heap中割...

  • 网格策略资金管理思路

    网格策略资金管理解决思路 1. 策略交易反思 a. 下单执行的策略与网格策略本身有本质冲突:在7月份我在H...

  • 堆的理解

    参考hac师傅的博客和CTF-wiki自己总结一下。理解有误,请多指正。 堆块概念 堆为程序运行时可以由程序动态申...

  • 2019-06-18 unlink源码解释

    Linux中的un 在此输入正文link glibc2.27中的unlink源码分析 堆溢出漏洞利用,过检测方式的...

  • 测试架构师的修炼之道(一)

    测试的核心不是业务、测试方法、测试设计、自动化、测试 管理、测试流程等,而是“测试策略”。我们该如何理解测试策略呢...

网友评论

    本文标题:理解glibc的堆管理策略

    本文链接:https://www.haomeiwen.com/subject/jsbglxtx.html