二进制安全:ptmalloc内存管理机制与堆块chunk源码分析
Posted 鸿渐之翼
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二进制安全:ptmalloc内存管理机制与堆块chunk源码分析相关的知识,希望对你有一定的参考价值。
声明:本文仅供开发者与信息安全从业者学习参考,请遵守行业道德底线。
底层安全垃圾小废物请指教,嘤嘤嘤。
作者:深圳市狩猎者网络安全技术有限公司-知柯信息安全团队-hongsofwing
本文参考:glibc内存管理ptmalloc源代码分析 华庭(庄明强)2011/4/17
本文源代码使用glibc-2.15 source code 下载地址直达glibc-2.15
参考阅读:Heap overflow堆溢出(一)
这是一篇结合了malloc.c源代码分析的文章,也许部分读者朋友会认为这篇文章在炒冷饭,我不是炒冷饭!本文是我学习heap的笔记,本文包括了堆溢出的基本概念。
Ptmalloc内存管理概述:
简介:
ptmalloc 实现了 malloc(),free()以及一组其它的函数. 以提供动态内存管理的支持。分配器处在用户程序和内核之间,它响应用户的分配请求,向操作系统申请内存,然后将其返回给用户程序,为了保持高效的分配,分配器一般都会预先分配一块大于用户请求的内存, 并通过某种算法管理这块内存。
堆是一个结构,可以对不同的内存进行管理,下面是Linux系统中的堆,堆的增长是从小到大。
+--- Heap grows to bigger positions
|
| +-+-+-+-+-+-+ 0x00000000
V | CODE |
+-----------+
| HEAP |
| |
+-----------+
| | A
| | |
+-----------+ +---- Stack grows to lower positions
| STACK |
+-----------+ 0xFFFFFFFF
Malloc Chunk 堆块分析
想必我们都看过这张图片:malloc chunk
/malloc/malloc.c中1072行代码注释有上图的源码
malloc.c关于chunk声明的C源码
struct malloc_chunk
INTERNAL_SIZE_T mchunk_prev_size; /* Size of previous chunk (if free). */
INTERNAL_SIZE_T mchunk_size; /* Size in bytes, including overhead. */
struct malloc_chunk* fd; /* double links -- used only if free. */
struct malloc_chunk* bk;
/* Only used for large blocks: pointer to next larger size. */
struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */
struct malloc_chunk* bk_nextsize;
;
以上程序中在定义了mchunk_prev_size域,mchunk_size域,fd,bk
fd_nextsize,bk_nextsize
各个域的作用
指针FD与BK只有当CHUNK块空闲时存在,如下图所示,FD指针指向下一个CHUNK头部Prev_size,BK指向上一个CHUNK的Prev_size
FreeChunk过程
实现FreeChunk是通过双链表完成的如下图所示
CHUNK在FREE之前的结构
chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of previous chunk, if unallocated (P clear) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of chunk, in bytes |A|M|P|
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| User data starts here... .
. .
. (malloc_usable_size() bytes) .
. |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| (size of chunk, but used for application data) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of next chunk, in bytes |A|0|1|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
CHUNK在FREE之后的结构:
chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of previous chunk, if unallocated (P clear) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
`head:' | Size of chunk, in bytes |A|0|P|
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Forward pointer to next chunk in list |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Back pointer to previous chunk in list |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Unused space (may be 0 bytes long) .
. .
. |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
`foot:' | Size of chunk, in bytes |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of next chunk, in bytes |A|0|0|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
关于Arena
在 ptmalloc2 的实现中,Arena 是程序存储每线程堆 per-thread heaps的地方。 理想情况下,人们会认为每个线程都应该有自己的 Arena,每一个Arena需要几个堆,例如具有大量多线程的 Apache Web Server就无法使用它。
static struct malloc_par mp_ =
.top_pad = DEFAULT_TOP_PAD,
.n_mmaps_max = DEFAULT_MMAP_MAX,
.mmap_threshold = DEFAULT_MMAP_THRESHOLD,
.trim_threshold = DEFAULT_TRIM_THRESHOLD,
#define NARENAS_FROM_NCORES(n) ((n) * (sizeof (long) == 4 ? 2 : 8))
.arena_test = NARENAS_FROM_NCORES (1)
;
malloc/malloc.c:1750
#define NARENAS_FROM_NCORES(n) ((n) * (sizeof (long) == 4 ? 2 : 8))
malloc/arena.c:906
int n = __get_nprocs ();
if (n >= 1)
narenas_limit = NARENAS_FROM_NCORES (n);
else
/* We have no information about the system. Assume two
cores. */
narenas_limit = NARENAS_FROM_NCORES (2);
关于Top:
在malloc
当我们在分配Heap的时候,TOP始终位于顶部。TOP的大小取决于Arena的空间大小。当我们首次调用Heap的时候,TOP为0。TOP会存在Heap的分配内存中,如下是它的分配结构代码:
+---HEAP GROWS UPWARDS
|
| +-+-+-+-+-+-+
| | MALLOC 1 |
| +-----------+
| | MALLOC 2 |
| +-----------+
| | MALLOC 3 |
| +-----------+
| | TOP |
| | |
V | |
+-----------+
--- WILDERNESS ---
关于Bins:
Bins结构:
+---HEAP GROWS UPWARDS
| Bins
| +-+-+-+-+-+-+ +------------------------+
| | CHUNK 1 | | |
| +-----------+ +------------------------+
| | CHUNK 2 |
| +-----------+
| | CHUNK 3 |
| +-----------+
| | CHUNK 4 |
| +-----------+
| | CHUNK 5 |
| +-----------+
| | CHUNK 6 |
| +-----------+
| | TOP |
| | |
V | |
+-----------+
--- WILDERNESS ---
Bins是内存中的双链表结构,bins用于跟踪被FREE的CHUNK。当一个CHUNK被释放后,它会被放入Bins数组中。
这里有128个Bins,一个unsorted chunks bin与剩下的127个Bins。
这127个Bins由21个small chunk和96个Bins组成
1(Unsorted) + 96(Small chunks) + 31(Large chunks) = 128(Bins).
Small Chunk与Chunk的区别
这里我们又会有疑问smallchunk和 普通chunk的区别是什么?
在这里把Chunk分为Small Chunk与Large Chunk
它们最大的不同在于当chunk被释放(free)时bins回收大小不一样。
Small Chunk会把相同大小的Free chunk储存在bins中。
在以下案例中,我们分配6个相同大小的CHUNK
+---HEAP GROWS UPWARDS
| Bins
| +-+-+-+-+-+-+ +------------------------+
| | CHUNK 1 | | |
| +以上是关于二进制安全:ptmalloc内存管理机制与堆块chunk源码分析的主要内容,如果未能解决你的问题,请参考以下文章
Linux glibc内存管理:用户态内存分配器——ptmalloc实现原理
Linux 内核 内存管理内存管理架构 ② ( 用户空间内存管理 | malloc | ptmalloc | 内核空间内存管理 | sys_brk | sys_mmap | sys_munmap)