编辑: kr9梯 | 2016-06-22 |
4 2.基础知识 2.1 X86 平台 Linux 进程内存布局 Linux 系统在装载 elf 格式的程序文件时,会调用 loader 把可执行文件中的各个段依次 载入到从某一地址开始的空间中(载入地址取决 link editor(ld)和机器地址位数,在32 位机 器上是 0x8048000, 即128M 处) . 如下图所示, 以32 位机器为例, 首先被载入的是.text 段, 然后是.data 段,最后是.bss 段.这可以看作是程序的开始空间.程序所能访问的最后的地 址是 0xbfffffff,也就是到 3G 地址处,3G 以上的 1G 空间是内核使用的,应用程序不可以直 接访问.应用程序的堆栈从最高地址处开始向下生长,.bss 段与堆栈之间的空间是空闲的, 空闲空间被分成两部分,一部分为 heap,一部分为 mmap 映射区域,mmap 映射区域一般 从TASK_SIZE/3 的地方开始, 但在不同的 Linux 内核和机器上, mmap 区域的开始位置一般是 不同的.Heap 和mmap 区域都可以供用户自由使用,但是它在刚开始的时候并没有映射到 内存空间内,是不可访问的.在向内核请求分配该空间之前,对这个空间的访问会导致 segmentation fault.用户程序可以直接使用系统调用来管理 heap 和mmap 映射区域,但更 多的时候程序都是使用 C 语言提供的 malloc()和free()函数来动态的分配和释放内存.Stack 区域是唯一不需要映射, 用户却可以访问的内存区域, 这也是利用堆栈溢出进行攻击的基础. 2.1.1
32 位模式下进程内存经典布局 这种布局是 Linux 内核 2.6.7 以前的默认进程内存布局形式, mmap 区域与栈区域相对增 长,这意味着堆只有 1GB 的虚拟地址空间可以使用,继续增长就会进入 mmap 映射区域, 这显然不是我们想要的.这是由于
32 模式地址空间限制造成的,所以内核引入了另一种虚 拟地址空间的布局形式,将在后面介绍.但对于
64 位系统,提供了巨大的虚拟地址空间, 这种布局就相当好.
5 2.1.2
32 位模式下进程默认内存布局 从上图可以看到,栈至顶向下扩展,并且栈是有界的.堆至底向上扩展,mmap 映射区 域至顶向下扩展,mmap 映射区域和堆相对扩展,直至耗尽虚拟地址空间中的剩余区域,这 种结构便于 C 运行时库使用 mmap 映射区域和堆进行内存分配.上图的布局形式是在内核 2.6.7 以后才引入的,这是
32 位模式下进程的默认内存布局形式. 2.1.3
64 位模式下进程内存布局 在64 位模式下各个区域的起始位置是什么呢?对于 AMD64 系统,内存布局采用经典 内存布局,text 的起始地址为 0x0000000000400000,堆紧接着 BSS 段向上增长,mmap 映射 区域开始位置一般设为 TASK_SIZE/3. #define TASK_SIZE_MAX ((1UL size &
NON_MAIN_ARENA) chunk 在分割时总是以地址对齐(默认是
8 字节,可以自由设置,但是
8 字节是最小值 并且设置的值必须是
2 为底的幂函数值,即是 alignment = 2^n,n 为整数且 n>
=3)的方式来 进行的,所以用 chunk->
size 来存储本 chunk 块大小字节数的话,其末 3bit 位总是 0,因此 这三位可以用来存储其它信息,比如: 以第
0 位作为 P 状态位,标记前一 chunk 块是否在使用中,为1表示使用,为0表示空 闲. 以第
1 位作为 M 状态位, 标记本 chunk 块是否是使用 mmap()直接从进程的 mmap 映射 区域分配的,为1表示是,为0表示否. 以第
2 位作为 A 状态位,标记本 chunk 是否属于非主分配区,为1表示是,为0表示 否. /* Bits to mask off when extracting size Note: IS_MMAPPED is intentionally not masked off from size field in macros for which mmapped chunks should never be seen. This should cause helpful core dumps to occur if it is tried by accident by people extending or adapting this malloc. */ #define SIZE_BITS (PREV_INUSE|IS_MMAPPED|NON_MAIN_ARENA) /* Get size, ignoring use bits */ #define chunksize(p) ((p)->