CTF-PWN-堆
- 堆
- 申请堆块
- main_areana
- brk&sbrk函数
- malloc
- free
- free后
- top chunk
堆
由malloc alloc realloc 函数分配
chunk的前指的是地址低的,chunk的高指的是地址高的
申请堆块
ptmalloc2堆管理器: 通俗的讲就是相当于一个”中间商”,在程序想要申请向系统申请堆空间时,这里的 ptmalloc2 就会申请一块很大的空间,然后把用户真正的空间部分分配给用户。
main_areana
main_arena 其实就是 ptmalloc2 堆管理器通过与操作系统内核进行交互申请到的(比自己所要申请的大)
牢牢记住
malloc得到的内存地址为user data部分 (参数为0 为系统允许堆的最小内存块 为负数 会对于无符号数会贼大 所以可能失败)
presize字段:前一地址chunk被free则记录前一个chunk大小(包括chunk头)若没有被free则可用被前一个chunk存储数据。通过pre_size字段来获取上一个chunk的大小及地址(空间复用:当一个chunk没有被free时,它的下一个chunk的prev_size可以被当前chunk使用。prev_size已经有值时,下一个chunk被free了,prev_size不会被清掉。如果是已经free掉的了,他的pre_size也能被前一个chunk使用)
size字段:当前堆块大小(chunk头+userdata)大小必须是2SIZE_SZ的整数倍,若不是
当请求为小于2SIZE_SZ时此时分配2SIZE_SZ
当请求大于2SIZE_SZ的n倍却小于2SIZE_SZ的n倍+SIZE_SZ时,分配2SIZE_SZ的n倍
当请求大于2SIZE_SZ的n倍+SIZE_SZ却小于2SIZE_SZ的(n+1)倍时,分配2*SIZE_SZ的(n+1)倍
有点四舍五入的感觉
该字段的底三位对chunk大小没影响(因为size大小2*SIZE_SZ的整数倍)
倒数第三位A:no_main_arena:0表示为主线程分配的 1为非主线程分配的
倒数第二位M:is_mapped:1从mmap 0为heap
倒数第一位P:prev_inuse:0为上一个chunk被free 1为没有被free
64位最小:16+8+8 size:16+8+8+1
32位最小:8+4+4 size:8+4+4+1
user data字段:64位最小:16
32位最小:8
brk&sbrk函数
start_brk和brk,他们分别表示堆块的开始地址和结束地址
初始时
如果开启ALSR:start_brk和brk相同且为数据段末尾后
如果没开启ALSR:start_brk和brk相同切为数据段末尾后随即偏移处
sbrk函数
定义:传参0时可以获取当前brk指针的值,传参num时可以将当前brk指针的值增加拓展num字节(传参整数是增加,传参负数是减少)
返回值:若成功,brk()会返回0,否则返回-1。
brk函数
定义:可以改变brk指针内存储的地址(即堆结束地址,又叫堆顶),传参多少就把brk设置为多少
返回值:若成功,brk()会返回0,否则返回-1。
malloc
malloc一方面会检查malloc的参数在负数范围内不得大于-2*MINSIZE且top_size的值减去分配的chunk的size大小的值大于MINSIZE (MINSIZE是最小的chunk的size大小)
malloc接受数值会经过下列转化:
(((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? MINSIZE: ((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ! MALLOC_ALIGN_MASK
一个三目运算符 a?b :c
reg为malloc传入的参数,SIZE_SZ和操作系统位数有关 32位为4,64位为8位。MALLOC_ALIGN_MASK也与操作系统位数有关,32位为7,64位为15.最后的值为size大小(不包括标志位)(除了malloc参数小于8和16,size大小一律为0x10和0x20)
free
1.不会清空此堆块的 user data
2.将此堆块的指针存储到 main_arena 中了
参数为空 啥都没做
参数对应chunk已经被释放,会出现乱七八糟的情况
free后
不存在M状态
user data头部分配出fd和bk,未free时候没有fd和bk存的是数据。free后会被添加到对应的freechunk管理表。fd为前一个已经free的chunk的地址,bk为后一个已经free的chunk的地址
fd_nextsize,bk_nextsize是较大的chunkfree后有的
fd_nextsize为前一个与当前chunk大小不同的freechunk地址
bk_nextsize为后一个与当前chunk大小不同的freechunk地址
一般空闲的较大的chunk按照从大到小的顺序排列
top chunk
在系统当前的所有 free chunk(无论那种 bin),都无法满足用户请求的内存大小的时候,就会从 top chunk 上”剪切”一部分作为 chunk 分配给他,top chunk的size减小