敬告:
《中华人民共和国刑法》第三百八十六条【破坏计算机系统罪;网络服务渎职罪】违反国家规定,对计算机信息系统功能进行删除、修改、增加、干扰,造成计算机系统不能正常运行,后果严重的,处五年以下有期徒刑或者拘役;后果特别严重的,处五年以上有期徒刑。
违反国家规定,对计算机系统中存储、处理或者传输的数据和应用程序进行删除、修改、增加的操作,后果严重的,依照前款规定处罚。
故意制作、传播计算机病毒等破坏性程序,影响计算机系统正常运行,后严重的,依照第一款规定处罚。
单位犯前三款罪的,对单位判处罚金,对其直接负责的主管人员和其他直接负责人员,依照第一款的规定处罚。
声明:本文仅供开发者与信息安全从业者学习参考,请遵守行业道德底线。
作者:深圳市狩猎者网络安全技术有限公司-知柯信息安全团队-王驭停
本文参考:glibc内存管理ptmalloc源代码分析 华庭(庄明强)2011/4/17
本文源代码使用glibc-2.15 source code 下载地址直达glibc-2.15
参考阅读:Heap overflow堆溢出(一)
这是一篇结合了malloc.c源代码分析的文章,也许部分读者朋友会认为这篇文章在炒冷饭,本文是我学习heap的笔记,本文包括了堆溢出的基本概念。
更新日期:
2022年1月29日
2022年1月26日
文章目录
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 | | |
| +-----------+ +------------------------+
| | CHUNK 2 |
| +-----------+
| | CHUNK 3 |
| +-----------+
| | CHUNK 4 |
| +-----------+
| | CHUNK 5 |
| +-----------+
| | CHUNK 6 |
| +-----------+
| | TOP |
| | |
V | |
+-----------+
--- WILDERNESS ---
我们释放CHUNK4,接着释放CHUNK2
+---HEAP GROWS UPWARDS
| Bins
| +-+-+-+-+-+-+ +------------------------+
| | CHUNK 1 | | ADDRESS OF FREESPACE 4 | (1)free
| +-----------+ +------------------------+
| |FREESPACE 2 | (2)free | ADDRESS OF FREESPACE 2 | (2)free
| +-----------+ +------------------------+
| | CHUNK 3 |
| +-----------+
| |FREESPACE 4 | (1)free
| +-----------+
| | CHUNK 5 |
| +-----------+
| | CHUNK 6 |
| +-----------+
| | TOP |
| | |
V | |
+-----------+
--- WILDERNESS ---
FREECHUNK4和FREECHUNK2被合成FREECHUNK2
+---HEAP GROWS UPWARDS
| Bins
| +-+-+-+-+-+-+ +------------------------+
| | CHUNK 1 | | ADDRESS OF FREECHUNK 2 |
| +-----------+ +------------------------+
| |FREECHUNK 2|
| | |
| | |
| | |
| | |
| +-----------+
| | CHUNK 5 |
| +-----------+
| | CHUNK 6 |
| +-----------+
| | TOP |
| | |
V | |
+-----------+
--- WILDERNESS ---
当一个Chunk被释放后,in-use位被设置为0,程序会检查上一个或者下一个是否存在空闲空间,Bins会把空余空间合并。
Fastbins
Fastbins在源码中最大大小是这么定义的
#define MAX_FAST_SIZE (80 * SIZE_SZ / 4)
SIZE_SZ 在64位系统上是8bit,在32位系统上是4bit.MAX_FAST_SIZE在32位和64位系统上分别大小是160bytes和80bytes
这就意味着小于MAX_FAST_SIZE的FREE CHUNK会被回收到Fastbins数组中
目前遇到一个棘手的问题,fastbin是一个释放小chunk的列表数组Fastbins] is an array of lists holding recently freed small chunks。单链接存储在“LIFO”中。
—分割线:2022年1月29日,更新2022年1月26日,更新2022年2月6日—