高版本Large Bin Attack 原理与利用详解
字数 1495 2025-12-16 12:31:13
高版本Large Bin Attack原理与利用详解
1. 背景知识
1.1 内存管理基础
- tcache:默认缓存最大到1032字节(0x408)的chunk(64位系统)
- large_bin:用于管理大于特定大小阈值的内存块,是双向链表结构
- 大小阈值:进入large_bin的最低字节为0x200(512),但由于tcache_bin的存在,实际进入large_bin的最低字节为0x410(1040)
1.2 Large Bin特性
- 排列顺序:从大到小的顺序排列,越大的chunk越靠前
- 相同大小处理:按照free的时间进行排序
- 指针有效性:只有首堆块的fd_nextsize、bk_nextsize会指向其它大小的堆块,后续堆块的这些指针通常为0
2. Large Bin结构详解
2.1 链表结构
largebin管理器(main_arena)
│
├── 最大chunk(头节点)
│ ├── fd: 指向同大小下一个chunk
│ ├── bk: 指向同大小上一个chunk
│ ├── fd_nextsize: 指向更小的chunk
│ └── bk_nextsize: 指向更大的chunk
│
├── 中间chunk
│ ├── fd: 指向同大小下一个chunk
│ └── bk: 指向同大小上一个chunk
│
└── 最小chunk(尾节点)
├── fd: 指向main_arena+偏移
└── bk: 指向main_arena+偏移
2.2 关键指针说明
- fd/bk:连接相同大小的chunk
- fd_nextsize/bk_nextsize:连接不同大小的chunk,形成大小排序链
3. Large Bin Attack原理
3.1 攻击条件
- 存在一个已归位的large chunk在large bin中
- 有一个未归位的chunk在unsorted bin中
- 能够控制large chunk的bk和bk_nextsize指针
3.2 核心漏洞点
在unsorted bin中的chunk插入到large bin时,存在两处关键操作:
// 第一处攻击点(从中间插入时)
else
{
// 从中间插入
victim->fd_nextsize = fwd;
victim->bk_nextsize = fwd->bk_nextsize;
// 漏洞:缺少对fwd->bk_nextsize的完整性验证
if (__glibc_unlikely (fwd->bk_nextsize->fd_nextsize != fwd))
malloc_printerr ("malloc(): largebin double linked list corrupted (nextsize)");
fwd->bk_nextsize = victim;
victim->bk_nextsize->fd_nextsize = victim; // 攻击点1
}
bck = fwd->bk;
// 漏洞:缺少对bck的完整性验证
if (bck->fd != fwd)
malloc_printerr ("malloc(): largebin double linked list corrupted (bk)");
// 第二处攻击点(当unsorted chunk小于large bin中最小的chunk时)
if ((unsigned long) (size) < (unsigned long) chunksize_nomask (bck->bk))
{
fwd = bck;
bck = bck->bk;
victim->fd_nextsize = fwd->fd;
victim->bk_nextsize = fwd->fd->bk_nextsize; // 攻击点2,无检测
// 关键攻击操作
fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim;
}
3.3 攻击效果
通过伪造large chunk的bk和bk_nextsize指针,可以实现:
- 任意地址写:将victim chunk的地址写入目标地址
- 内存破坏:破坏堆管理结构,为进一步利用奠定基础
4. 利用过程详解
4.1 环境准备
- 申请多个large chunk(大小≥0x410)
- 释放这些chunk到unsorted bin
- 通过特定操作使部分chunk归位到large bin
4.2 攻击步骤
步骤1:构造初始状态
large bin: [chunk1] ←→ [chunk2] (chunk1 > chunk2)
unsorted bin: [chunk3] (size < chunk2)
步骤2:触发插入操作
当申请特定大小的chunk时,堆管理器:
- 遍历unsorted bin寻找合适chunk
- 将不合适的chunk整理回对应的bin
- 在chunk3插入large bin的过程中触发漏洞
步骤3:利用写入操作
// 关键写入操作
victim->bk_nextsize->fd_nextsize = victim; // 写入目标地址1
bck->fd = victim; // 写入目标地址2
通过精心构造的bk_nextsize指针,可以将victim地址写入任意内存位置。
4.3 版本差异
- 2.31之前:先有小的堆块,然后大堆块插入触发攻击
- 2.31之后:先有大的堆块,然后小的堆块插入,攻击路径不同但原理相似
5. 防护与检测
5.1 安全检测
代码中存在的检测机制:
// 检测1:双向链表完整性
if (__glibc_unlikely (fwd->bk_nextsize->fd_nextsize != fwd))
malloc_printerr ("malloc(): largebin double linked list corrupted (nextsize)");
// 检测2:前后指针一致性
if (bck->fd != fwd)
malloc_printerr ("malloc(): largebin double linked list corrupted (bk)");
5.2 绕过技巧
攻击成功的关键在于:
- 确保检测通过的前提下伪造指针
- 精心控制chunk的大小关系和插入顺序
- 利用检测逻辑的局限性(检测不完整)
6. 实际利用考虑
6.1 利用限制
- 需要能够控制large chunk的元数据
- 需要精确控制chunk的分配和释放顺序
- 受glibc版本影响,不同版本需要调整利用方法
6.2 应用场景
- 堆风水攻击(Heap Feng Shui)
- 绕过ASLR等安全机制
- 实现任意地址读写能力
7. 总结
Large Bin Attack是一种基于堆管理机制的高级利用技术,其核心在于利用large bin插入操作中的指针更新逻辑缺陷。理解large bin的组织结构、掌握不同版本下的攻击路径差异、以及熟悉防护机制的绕过方法,是成功利用该漏洞的关键。
该攻击技术虽然条件较为苛刻,但在精心构造的环境下能够实现强大的内存操作能力,是二进制安全研究中的重要课题。