明天有CTF 今天赶快临时抱佛脚写了这篇文章 冲啊兄弟们

什么是堆

堆

在程序运行过程中,堆可以提供动态分配的内存,允许程序申请大小未知的内存。堆其实就是程序虚拟地址空间的一块连续的线性区域,它由低地址向高地址方向增长。我们一般称管理堆的那部分程序为堆管理器

堆 其实和栈差不多 都是储存内存的某一种方式 而说起堆 你可能就会想起栈 其实 堆的最大的一个特征 就是 它的大小是由系统申请的 堆还具有几个特性:


是虚拟地址空间的一块连续的线性区域
提供动态分配的内存,允许程序申请大小未知的内存
在用户与操作系统之间,作为动态内存管理的中间人
响应用户的申请内存请求,向操作系统申请内存,然后将其返回给用户程序
管理用户所释放的内存,适时归还给操作系统

堆的概述就那么点 但是 后面会引出跟多的概念 我们继续吧

堆管理器

堆 都有不同的管理方式 如下:

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

这里我们主要以 glibc 进行介绍

堆管理器的操作

在这里我们主要介绍

  • 基本的堆操作,包括堆的分配,回收,堆分配背后的系统调用
  • 介绍堆目前的多线程支持。

malloc

malloc 的源码说明如下

/*
  malloc(size_t n)
  Returns a pointer to a newly allocated chunk of at least n bytes, or null
  if no space is available. Additionally, on failure, errno is
  set to ENOMEM on ANSI C systems.
  If n is zero, malloc returns a minumum-sized chunk. (The minimum
  size is 16 bytes on most 32bit systems, and 24 or 32 bytes on 64bit
  systems.)  On most systems, size_t is an unsigned type, so calls
  with negative arguments are interpreted as requests for huge amounts
  of space, which will often fail. The maximum supported value of n
  differs across systems, but is in all cases less than the maximum
  representable value of a size_t.
*/

在Malloc函数 我们通常会会通过使用malloc函数来获取一个对应大小字节的内存块的指针(说白了就是申请堆chunk)
但是 需要注意的是 size_t 是一个无符号数 所以说 当你申请一个负数大小的堆时 可能会出现整形溢出漏洞但是 一般来说 不会出现这样的问题 因为系统大概率不会有那么大的内存给你

还有就是当 n=0 时 会返回当前系统允许的堆的最小内存块

free

free的源码说明如下:

/*
      free(void* p)
      Releases the chunk of memory pointed to by p, that had been previously
      allocated using malloc or a related routine such as realloc.
      It has no effect if p is null. It can have arbitrary (i.e., bad!)
      effects if p has already been freed.
      Unless disabled (using mallopt), freeing very large spaces will
      when possible, automatically trigger operations that give
      back unused memory to the system, thus reducing program footprint.
    */

Free函数 相对应malloc其实就是释放所申请的堆块 free 函数会释放由 P 所指向的内存块 这里 也有一些需要关注的:

  • 当 p 为空指针时,函数不执行任何操作。
  • 当 p 已经被释放之后,再次释放会出现乱七八糟的效果,这其实就是 double free
  • 除了被禁用 (mallopt) 的情况下,当释放很大的内存空间时,程序会将这些内存空间还给系统,以便于减小程序所 使用的内存空间。

arena

这个其实应该放在前面讲
很简单 arena就是malloc申请的那玩应的前身 一块chunk被申请前 他就是arena 换一句话来说 arena就是堆管理器所拥有的空闲内存没啥好说的
arena

chunk

chunk是用户所申请的内存的单位 也就是 你申请的堆就是chunk
在malloc函数中 申请也是chunk
chunk
[chunk也是由结构的!]

chunk的分类

状态大小功能
mallocedfasttop chunk
freesmalllast remainder chunk
\large\
\tcache\

现在 我会一个一个的讲解(图片来自星盟安全团队)

malloced chunk

顾名思义 就是申请过的chunk

malloced

free chunk

被释放掉的malloced chunk

free

top chunk

就是一块不经常用的chunk 和栈不一样的是 chunk的使用都会在topchunk之下 看完下面的动画 你就应该懂了
1

变成了
2

last remainder chunk

就是一块被分割的chunk 一块剩下来的被分割过的被free的chunk 就是它了

image.png

堆的大小

在32位时 堆得大小为 2*4*n 在64位时 则是 2*8*n
而由于 8的2进制 是2000 除了代表数量的比特位或用来表达其他的
大概如下:

nabc

n代表数量 而abc代表符不符合某些条件
1 = yes 0 = no
a NON_MIAN_ARENA,记录当前chunk是否不属于主线程
b IS_MAPPED,记录当前chunk是否是由mmap分配的
c PREV_INUSE,记录前一个chunk块是否被分配

今天就跟新到这 有时间继续

最后修改:2021 年 08 月 15 日 11 : 45 PM
如果觉得我的文章对你有用,请随意赞赏