堆入门1—堆概念与glibc堆管理器

参考:

董哥的黑板报(堆漏洞挖掘):https://blog.csdn.net/qq_41453285/category_9150569.html
CTFwiki:https://wiki.x10sec.org/
以及互联网其它文章、博客等

概述:

堆(heap)是程序在运行过程中,所申请的动态分配和使用的内存区域,对比栈,虽然二者都在程序运行内存里,但是堆没有默认的生存周期。程序可以动态的申请和释放不同大小的堆内存区域,如果没有明确的释放堆内存操作,则堆内存区域一直有效。

堆内存的数据通过指向内存的指针进行调用,这里的调用主要是对结构体的成员变量和成员函数的调用。

堆管理器:

libc和glibc都是linux下的C函数库,glibc是GNU旗下的C标准库,现在linux发行版本都用的glibc,libc已经不再维护。

目前 Linux 标准发行版中主要使用的堆分配器是 glibc 中的:ptmalloc2。

其它内存管理机制:dlmalloc,tcmalloc,jemalloc...

ptmalloc2 主要是通过 malloc/free 函数来分配和释放内存块。

malloc(size_t n)

  1. 返回值:所申请堆块开始位置的指针。
  2. 当 n=0 时,返回当前系统允许的堆的最小内存块,32位是8字节,64位是16字节。
  3. 当 n 为负数时,由于在大多数系统上,size_t 是无符号数(这一点非常重要),所以程序就会申请很大的内存空间,但通常来说都会失败,因为系统没有那么多的内存可以分配。
  4. malloc用mmap来创建独立映射段,其背后用brk函数申请内存地址。
  5. 使用malloc申请的内存,释放后,若再次申请同样大小的堆时,还是从申请到第一次释放的那个堆。(UAF,double free)

free(void* p)

  1. free 函数会释放由 p 所指向的内存块。这个内存块有可能是通过 malloc 函数得到的,也有可能是通过其它函数得到的。
  2. 当 p 为空指针时,函数不执行任何操作。
  3. 当 p 已经被释放之后,再次释放会导致double free错误。
  4. 除了被禁用(mallopt)的情况下,当释放很大的内存空间时,程序会将这些内存空间还给系统,以便于减小程序所使用的内存空间。
  5. feer释放堆时会检查之前的 chunk 是否被释放,若已经释放,则和当前释放的 chunk 合并,之后再放入Unsorted Bin。

glibc 的堆管理实现:

arena 指的是堆内存区域本身,并不是结构;主线程的 main arena 通过 sbrk 创建;其他线程的 arena 通过 mmap 创建。

malloc_state 管理 arena 的核心结构,包含堆的状态信息、bins 链表等;main arena 对应的 malloc state 结构存储在 glibc 全局变量中;其他线程 arena 对应的 malloc_state 存储在 arena 本身中

bins 用来管理空闲内存块,通常用链表的结构来进行组织
chunks 内存块结构

在内存分配与使用中只有当真正去访问一个地址的时候,系统才会建立虚拟页面与物理内存的映射关系

发表评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据