今天学习下linux的堆管理。本次学习主要针对,glibc的prmalloc2
堆溢出主要包括:unlink,double free ,uaf。
调用malloc后会调用brk 和mmap两个系统函数创建堆。
start_brk 是堆的起始,brk是堆的终止。如果打开aslr时,会在start_brk(在.bss端段)前加入一段随机的偏移
如果关闭aslr则是直接从bss段结尾开始。
malloc之后系统会分配比申请大很多的空间,后面再次申请时会从第一次申请的堆中分配
free调之后由glibc的malloc库管理,会从添加到第一次的堆里。有申请时再次分配。
堆结构分为三层:arena,heap,chunk
arena:
1.个数有上限,一般为2(x86) 8(x64) 如果 超过了,则内核可能将多个线程的堆映射到arena
2.一个arena可以维护多个堆,但只维护一个malloc_state(即Arena Header) (main arena没有heap_info)
当当前堆内存地址空间不足时,调用mmap()在内存空间映射出一个新的堆
chunk:
是堆中的数据库,每个chunk都是一个连续的内存地址。一共有四种chunk:
1.allocated chunk
被分配的chunk
2.free chunk
bin中未被使用的chunk,两个chunk地址连续则会被合并。比allocated chunk中还记录了指向上一个和下一个free chunk的指针
ps:bin即freelis,记录freechunk的地址列表,根据free chunk的大小分为四种chunk
1.unsorted bin 即没有排序过的chunk,排序后会分为后面三种
2.fast bin
3.large bin
4.small bin
bins数组用于记录small bin,large bin 和unsorted bin 包含126个bin,第一个bin记录unsorted chunks,2-63记录small bin ,64-126记录large bin
fastbinsY 记录了fastbin 含有十个bin
fastbin是单向链表,每个freechunk维护一个fd指针指向bin中下一个fast chunk地址
8 16 24 递增的chunk
fast chunks是内存地址上连续的
unsorted bins:
small 和large chunk被free后 会加入unsorted bins
双链表,调用malloc时会先检测是否有unsorted chunk 然后根据size决定分类或合并
small bins:
双向链表 与fast bins类似 以8字节为单位分类,尺寸为120-512
free时先检测前后chunk是否free 如果是就合并加入到unsorted中
large bins:
类似网状链表,有多个指针除了上下的指针还会指向比他大一点和小一点的chunk
不同bin维护不同size范围的large chunk 但同一个bin记录的chunk size不一定相等
调用malloc是 找到size相等 或最相近的large chunk 然后分为两个 一个为used chunk 一个为remaining chunk 归入unsorted bin重新分配
free 类似small chunk
3.top chunk
堆中最高地址的chunk。不属于bin,当最大的chunk不能满足需求时则调用此处chunk,如果还不够就增加top chunk
4.last Remainder Chunk
unsorted bin中存放的最后一个没有使用的chunk