个人认为讲堆技术之前应该先强调一下钩子函数的作用,ret2libc是修改了库函数的GOT表来让程序运行某一函数的时候变为运行其他函数,但是对于保护全开的程序来说就很难操作了,因此考虑堆利用来操作内存空间

那么如何操作内存呢?
1.如果在free后没有将指针置零,考虑double free&UAF
2.根据libc版本猜测,高版本是Tchache,低版本是fast bin attack/unsorted bin attack

然后泄露libc基址

内存管理方式:
通过brk()和sbrk() 来改变program_break使堆增长
通过mmap()和munmap来管理内存的映射

堆的位置:BSS段高地址处

申请一块小内存时,会依次从Tchache(after glibc2.26),unsorted bin,small bin,large bin找一块内存给你
如果都满了,会去堆的末尾找,Libc是默认有一块20,000 bytes的内存被映射到堆的,所以末尾可能有一块内存是依然可用且为被分配的,这时malloc会整一个chunk返回给你用
如果不够且需要的是一块大空间,这里会调用mmap来整块大空间进行分配(且使用unmap来进行回收)
如果空间不够但只要块小空间,那么会用brk系统调用增长堆的空间,然后再整块chunk来返回给你用

arena:
包括一片或数片连续的内存,主线程的这块区域称为main_arena
包含了start_brk和brk间的内存,这片连续内存一般就是堆了
主线程的arena只有堆,可以通过brk()扩展
子线程分配的映射段大小固定,不够用只能用mmap()

/* 分配器的标志位/
int flags;
/
Fastbins ,一种数组实现/
mfastbinptr fastbinsY[NFASTBINS];
/
Base of the topmost chunk -- not otherwise kept in a bin /
/
顶部内存块,是最近从小内存请求中分裂出来的剩余部分,原注释中有说明不在任何其他分区中保留/
mchunkptr top;
/
The remainder from the most recent split of a small request /
mchunkptr last_remainder;
/
Normal bins packed as described above /
mchunkptr bins[NBINS * 2 - 2];
/
bins的位图/
unsigned int binmap[BINMAPSIZE];
/
指向下一个malloc_state的地址,用于管理多个内存区域 /
struct malloc_state next;
/
连接到这个arena的线程数。如果arena在空闲列表上则为0。在arena.c中锁定
/
struct malloc_state next_free;
/
连接到这个arena的线程数,如果 /
INTERNAL_SIZE_T attached_threads;
/
当前arena从系统获取的总大小以及能从系统获得的最大内存大小 */
INTERNAL_SIZE_T system_mem;
INTERNAL_SIZE_T max_system_mem;
};

struct malloc_chunk
{
INTERNAL_SIZE_T prev_size; /如果上一个chunk被释放,则用于表示其大小,否则会作为上一个chunk的一部分用于储存数据/
INTERNAL_SIZE_T size; /* 空间大小,为2SIZE_SZ的整数倍,SIZE_SZ在64位下为8字节,32位为4字节;受内存对齐的影响,最后三个比特位用作状态标识,记录chunk来源和使用/释放状态. /
struct malloc_chunk
fd; /
被释放时才有效的字段,分别指向上一个和下一个chunk /
struct malloc_chunk
bk;
/* 与前两个指针相似,但是仅用于largebin/
struct malloc_chunk
fd_nextsize;
struct malloc_chunk* bk_nextsize;
};

Wildness:
一块假的chunk,位于堆的末尾,用于记录剩余的大小

chunk:
glibc管理内存的基本方式,被free释放的堆叫free chunk,另外整个堆初始化过后会被作为一个free chunk,称作top trunk;用户正在使用的叫allocated chunk;

bin:
由free chunk组成的链表叫bin,不同大小范围的chunk组成不同的bin,记录在malloc_state结构,按照以下规则划分(一些堆的结构变量见右侧的结构定义)
fast bin
unsorted bin
small bin
large bin

Tcache
一个 tcache chunk 大概长这样:
大小会是16的倍数

地址 内容
chunk_addr 前块(上一次释放的)地址的大小(前面的chunk未使用时)
这块地址的大小
3bit的判断位:
PREV_IS_USED
IS_MAPPED
NON_MAIN_ARENA
mem_addr 用户数据

unsorted bin
一个 unsorted bin 长这样:

地址 内容
chunk_addr 当前 Chunk 的地址
fd 前一个 Chunk 的指针 (forward pointer)
bk 后一个 Chunk 的指针 (backward pointer)
fd_nextsize 用于管理大小块的指针 (仅在 large bins 中使用)
bk_nextsize 用于管理大小块的指针 (仅在 large bins 中使用)
chunk_size 当前 Chunk 的大小,通常是 16 的倍数
PREV_INUSE 1 bit,表示前一个 Chunk 是否正在使用
IS_MAPPED 1 bit,表示 Chunk 是否通过 mmap 分配
NON_MAIN_ARENA 1 bit,表示 Chunk 是否属于主线程的主 Arena
mem_addr 用户数据的开始地址
posted @ 2024-08-14 03:36  mcrock  阅读(14)  评论(0编辑  收藏  举报