菜鸟PWN手进阶之堆基础

3 篇文章 1 订阅

一、 什么是堆

堆是可以根据运行时的需要进行动态分配和释放的内存,大小可变
Malloc/New
Free/Delete
1
堆的实现重点关注内存块的组织和管理方式,尤其是空闲内存块

  • 如何提高分配和释放效率
  • 如何降低碎片化、提高空间利用率

glibc的堆管理实现

ptmalloc2-glibc
不同线程维护不同的堆,称为per thread arena
主线程创建的堆,称为main arena
Arena数量受到CPU核数的限制

  • 对于32位系统 arena数量上限=2*核数
  • 对于64位系统 arena数量上限=8*核数
(一)arena
  • 指的是堆内存区域本身,并非结构
  • 主线程的main arena通过sbrk创建
  • 其他线程arena通过mmap创建
(二)malloc_state
  • 管理arena的核心机构,包括堆的状态信息、bins链表等
  • main arena对应的malloc_state结构存储在glibc的全局变量中
  • 其他线程arena对应的malloc_state存储在arena本身中
(三) bins
  • bins用来管理空闲内存块,通常使用链表结构来进行组织
  • 一个记录空闲块的账本
    根据chunk的大小和状态,有许多种不同的Bins结构
1.Fast bins

fastbin
用于管理小的chunk

  • 大小:
    • x86_32平台:16-64字节
    • x64平台:32-128字节
  • 相同大小的chunk放在一个bin中
  • 单向链表
  • 后进先出
  • 相邻空闲fast bin chunk不会被合并
  • 当chunk被free时,不会清理PREV_INUSE标志
2.bins

在这里插入图片描述

(1)small bins

用于管理中等大小的chunk

  • chunk大小<1024bytes(64bit)
  • 相同大小的chunk放在一个bin中
  • 双向循环链表
  • 先进先出
  • 当有空闲块相邻时,chunk会被合并成一个更大的chunk
  • bins[2]bins[3]…bins[125]共62组smallbin,大小范围[0x20,0x3f0](64位)
(2)large bins

用于管理较大的chunk,代码量多,在范围内寻找合适的chunk返回给用户

  • chunk大小>=1024bytes(64bit)
  • 每组bin表示一组size范围而不是具体的size,例如bins[126],bin[127]的链表中保存长度在[0x400,0x440]的chunk
  • 双向循环链表
  • 先进先出
  • chunk按照从大到小排序
  • 当有空闲块相邻,chunk会被合并
  • bins[126],bin[127]…bin[250,bin[251]共有63组largebin,大小范围[0x400,x](64位)
(3)unsorted bins

用于存放未整理的chunk

  • 64位平台中:chunk大小>128字节
  • 只存在唯一一个unsorted bin
  • 双向循环链表
  • 当一个chunk(非fast bin)被free,它首先被放入对应的small bin/large bin
  • bins[0],bins[1]

对双向链表的解释:这样看,低地址是前,高地址后
1

(四)chunk

内存块的结构

1. free chunk

fre64位平台下,free chunk的第一个字段prev_size(8字节)存储了前一个chunk的大小。
free chunk的第二个字段size记录了当前chunk的大小,该字段最低三个bit被用作其他含义。
P代表PREV_INUSE,即代表前一个chunk是否被使用
M代表IS_MMAPPED,代表当前chunk是否被mmap出来的。
N代表NON_MAIN_ARENA,代表改chunk是否属于非Main Arena
第三个字段fd和第四个字段bk(8字节)前向指针和后向指针,这两个字段用于bin链表单重,用来链接大小相同或者相近的free chunk,便于后续分配时查找

2.allocted chunk

在这里插入图片描述
allocted chunk的前两个字段和free chunk相同
第三个字段开始到最后,chunk中存储的都是用户数据。甚至下一个chunk的第一个字段prev_size,也可被用来存放数据,原因是prev_size字段只有当前一个chunk是free的时候才有意义,如果前一个chunk是已经分配的,堆管理器并不放心。
所以对一个chunk来说,用户可用大小从偏移+8(为何+8,是加上下一个chunk的prev_size的8个字节)开始,一直到下一个chunk的prev_size字段。
在64位平台下,chunk的大小一定是0x10zijie的整数倍。malloc返回的指针位图中mem指向的位置,即数据开头

malloc参数与chunk大小的关系
malloc参数为用户申请的内存大小
chunk包含数据和metadata
返回的chunk只要保证其中可用数据大小大于等于用户申请
在x86 32位平台下,chunk的大小一定是8字节的整数倍,x64平台下,chunk的大小一定是16字节的整数倍

3.Top chunk
  • 不属于任何bin
  • 在arena中处于最高地址
  • 当没有其他空闲块时,top chunk就会被用于分配
  • 分裂时:
    • 一块是请求大小的chunk
    • 另一块余下chunk将成为新的top chunk
4.Last_remainder

当请求small chunk大小的内存时,如发生分裂,则剩余的chunk保存为last_remainder

二、 malloc和free的工作流程

(一)malloc工作流程
  1. 如果size<max first,在fast bins中存在fast chunk,如找到则结束
  2. 如果size in_smallbin_range,在small bins中寻找small chunk,如找到则结束
  3. 如果size not in _smallbin_range,合并所有fastbin的chunk
  4. 循环:
    a.检查unsorted bin中的last_remainder
    如果满足一定条件,则分裂之,将剩余的chunk标记为新的last_remainder
    b.在unsorted bin中搜索,同时进行整理
    如遇到精确大小,则返回否则就把当前chunk整理到small/large bin中去
    c.在small bin和large bin中搜索最合适的chunk(不一定是精确大小)
  5. 使用top chunk
(二)free流程
  1. 如果size<max fast,放入fast bin,结束
  2. 如果前一个chunk是free的
    a. unlink前面的chunk
    b.合并两个chunk,并放入unsorted bin
  3. 如果后一个chunk是top chunk,则将当前chunk并入top chunk
  4. 如果后一个chunk时free的
    a.unlink后面的chunk
    b.合并两个chunk,并放 入unsorted bin
  5. 前后chunk都不是free的,放入unsorted bin

三、fastbin attack

Fast bin利用技术

  • Fast bin为单向链表,结构简单,容易伪造
  • 为了提高效率,安全检查较少
  • 只针对Fast bin大小的chunk,small/large chunk 不适用

利用思路

  • 空闲Fast chunk如果发生溢出被覆盖,则链表指针fd可以被修改
  • 可以通过修改链表指针fd,在Fast bin链表中引入伪造的空闲Fast chunk
  • 下次分配时分配出伪造的Fast chunk
  • 伪造的Fast chunk可以在.bss全局变量处,也可以在栈上·
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值