前言

要深入了解linux的内存管理,对于堆栈的认识是必不可少的。相对于栈来说,堆相对来说更加复杂。所以在看了大量文章以后,决定对堆中的一些基本概念总结一下,希望师傅们指教。 本文只讨论单线程,64位,glibc2.41版本 (等后续有空更新

堆的定义

ctf-wiki中是这样描述的

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

堆主要有两个作用:

  • 响应用户的申请内存请求,向操作系统申请内存,然后将其返回给用户程序。
  • 管理用户所释放的内存

malloc 流程图

free流程图

堆的利用

这个版本的glibc在向上合并的时候并没有把当前块的控制信息消除,所以可以double-free

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#define te

int main()
{
        int i = 0;
        void *x[7];
        for(i; i<7;i++){
                x[i] = malloc(0x100);
        }  
        void *p1;
        p1 = malloc(0x200); 
        void *p2;
        p2 = malloc(0x200); 
        malloc(10);  // 防止和av->top 合并
        for(i = 0; i< 7 ;i++){
                free(x[i]);
        } // 填满tcache_bins
        free(p1);   // 放入small_bins
        free(p2);   // 触发合并刚好进入unsorted_bins,并且没有清空控制信息
        malloc(0x200);
        free(p2); // double-free
        getchar();
        return 0;
}