浅析Large_bins_attack在高低版本的利用
字数 2030 2025-08-24 07:48:34

Large Bin Attack 高低版本利用详解

导言

在libc版本越来越高的情况下,许多旧的攻击方式已经失效,但large_bins_attack始终屹立不倒,是许多攻击方式的先决条件。本文将详细分析large_bins_attack在高低版本中的利用方法。

Large Bin 基本概念

基本特性

  • large_bin是一种堆分配的管理方式,是双向链表,用于管理大于某个特定大小阈值的内存块
  • 进入large_bin的最低字节一般为0x200(512)
  • 由于引入了tcache_bin,在tcache_bin尚未填满的情况下,进入large_bin的最低字节为0x410(1040)

结构特点

  • large_bins含有63个bin
  • large_bins总体又被分成6个组,每个组对应一个区间,且容纳个数呈指数性减少
  • 排列顺序是从大到小,越大的chunk越靠前,越小的chunk越靠后
  • 在相同大小的情况下,按照free的时间进行排序
  • 只有首堆块的fd_nextsize、bk_nextsize会指向其它大小的堆块,后续堆块的fd_nextsize、bk_nextsize通常为0

glibc-2.23版本的攻击方式

适用条件

  1. 存在能够修改堆内容的函数
  2. 从unsorted_bins里提取出来的堆块要紧挨着我们伪造过的large_bins里的堆块

攻击原理

  1. 申请三个大堆块(p1=0x420, p2=0x500, p3=0x500)
  2. 释放p1和p2到unsorted_bin
  3. 申请一个0x90的小堆块,使p2进入large_bin,p1被分割后部分留在unsorted_bin
  4. 释放p3到unsorted_bin
  5. 修改p2的size、bk和bk_nextsize指针:
    • 减小p2的size(0x3f1)
    • 设置bk指向target1-0x10
    • 设置bk_nextsize指向target2-0x20
  6. 再次申请0x90的堆块,触发p3被插入large_bin
  7. 攻击完成:target1和target2被写入p3的头指针

关键代码分析

p2[-1] = 0x3f1;  // 修改size
p2[0] = 0;       // fd置0
p2[2] = 0;       // fd_nextsize置0
p2[1] = (unsigned long)(&stack_var1 - 2);  // bk指向target1-0x10
p2[3] = (unsigned long)(&stack_var2 - 4);  // bk_nextsize指向target2-0x20

攻击流程图示

  1. 初始状态:p1和p2在unsorted_bin
  2. malloc(0x90)后:
    • p2进入large_bin
    • p1被分割,剩余部分留在unsorted_bin
  3. free(p3)后:p3进入unsorted_bin
  4. 修改p2的元数据
  5. 再次malloc(0x90)触发攻击

glibc-2.31版本的攻击方式

新增检测

glibc-2.31新增了两个检测:

if (__glibc_unlikely(fwd->bk_nextsize->fd_nextsize != fwd))
    malloc_printerr("malloc(): largebin double linked list corrupted (nextsize)");

if (bck->fd != fwd)
    malloc_printerr("malloc(): largebin double linked list corrupted (bk)");

这使得旧版的large_bin攻击方式失效。

新攻击原理

  1. 申请两个大堆块(p1=0x428, p2=0x418)
  2. 释放p1到unsorted_bin
  3. 申请更大的堆块(0x438)使p1进入large_bin
  4. 释放p2到unsorted_bin
  5. 修改p1的bk_nextsize指向target-0x20
  6. 再次申请大堆块(0x438)使p2进入large_bin
  7. 攻击完成:target被写入p2的头指针

关键代码分析

p1[3] = (size_t)((&target) - 4);  // 修改p1->bk_nextsize为target-0x20

攻击流程图示

  1. 初始状态:p1和p2在unsorted_bin
  2. malloc(0x438)后:p1进入large_bin
  3. free(p2)后:p2进入unsorted_bin
  4. 修改p1的bk_nextsize
  5. 再次malloc(0x438)触发攻击

高低版本差异对比

特性 glibc-2.23 glibc-2.31
检测机制 新增两个链表完整性检测
可写目标数量 可同时写两个地址 只能写一个地址
攻击复杂度 相对简单 需要更精确的控制
适用场景 更广泛 受限但仍可利用

实际应用案例:LitCTF2024 Heap2.39

题目特点

  • 高版本堆(glibc 2.39)
  • 限制size大小,适合large_bins攻击
  • 有UAF漏洞
  • 可主动触发exit

利用步骤

  1. 泄露libc和heap基址
  2. 布置堆结构:
    • 创建多个大堆块(0x508, 0x510, 0x500, 0x520, 0x500)
    • 释放特定堆块到unsorted_bin
  3. 利用large_bin攻击修改_IO_list_all
  4. 伪造IO结构,使用House of Apple2的_IO_wfile_overflow控制执行流
  5. 触发exit执行shell

关键代码

# 泄露libc和heap基址
delete(2)
add(4, 0x550)  # 分配2进large_bins
show(2)
large_bin = u64(p.recv(6).ljust(8, b'\x00'))
libc_base = large_bin - 0x203F50

# large_bin攻击
delete(0)
edit(2, p64(large_bin) + p64(large_bin) + p64(heap_addr) + p64(IO_list_all - 0x20))
add(5, 0x550)

# 伪造IO结构
edit(8, b'a'*0x500 + p32(0xfffff7f5) + b';sh\x00')
fake_IO = p64(0)*2 + p64(1) + p64(2)  # 设置flag
fake_IO = fake_IO.ljust(0xa0-0x10, b'\x00') + p64(chunk + 0x100)  # wide_data
fake_IO = fake_IO.ljust(0xc0-0x10, b'\x00') + p64(0xffffffffffffffff)  # mode
fake_IO = fake_IO.ljust(0xd8-0x10, b'\x00') + p64(IO_wfile_jumps)  # vtable
edit(0, fake_IO)

总结

large_bin攻击是一种强大的堆利用技术,尽管高版本增加了防护措施,但仍然可以通过精心构造的攻击链实现利用。理解large_bin的组织结构和攻击原理对于现代堆漏洞利用至关重要。在实际应用中,通常需要结合其他攻击技术(如IO_FILE利用)来实现完整的攻击链。

Large Bin Attack 高低版本利用详解 导言 在libc版本越来越高的情况下,许多旧的攻击方式已经失效,但large_ bins_ attack始终屹立不倒,是许多攻击方式的先决条件。本文将详细分析large_ bins_ attack在高低版本中的利用方法。 Large Bin 基本概念 基本特性 large_ bin是一种堆分配的管理方式,是双向链表,用于管理大于某个特定大小阈值的内存块 进入large_ bin的最低字节一般为0x200(512) 由于引入了tcache_ bin,在tcache_ bin尚未填满的情况下,进入large_ bin的最低字节为0x410(1040) 结构特点 large_ bins含有63个bin large_ bins总体又被分成6个组,每个组对应一个区间,且容纳个数呈指数性减少 排列顺序是从大到小,越大的chunk越靠前,越小的chunk越靠后 在相同大小的情况下,按照free的时间进行排序 只有首堆块的fd_ nextsize、bk_ nextsize会指向其它大小的堆块,后续堆块的fd_ nextsize、bk_ nextsize通常为0 glibc-2.23版本的攻击方式 适用条件 存在能够修改堆内容的函数 从unsorted_ bins里提取出来的堆块要紧挨着我们伪造过的large_ bins里的堆块 攻击原理 申请三个大堆块(p1=0x420, p2=0x500, p3=0x500) 释放p1和p2到unsorted_ bin 申请一个0x90的小堆块,使p2进入large_ bin,p1被分割后部分留在unsorted_ bin 释放p3到unsorted_ bin 修改p2的size、bk和bk_ nextsize指针: 减小p2的size(0x3f1) 设置bk指向target1-0x10 设置bk_ nextsize指向target2-0x20 再次申请0x90的堆块,触发p3被插入large_ bin 攻击完成:target1和target2被写入p3的头指针 关键代码分析 攻击流程图示 初始状态:p1和p2在unsorted_ bin malloc(0x90)后: p2进入large_ bin p1被分割,剩余部分留在unsorted_ bin free(p3)后:p3进入unsorted_ bin 修改p2的元数据 再次malloc(0x90)触发攻击 glibc-2.31版本的攻击方式 新增检测 glibc-2.31新增了两个检测: 这使得旧版的large_ bin攻击方式失效。 新攻击原理 申请两个大堆块(p1=0x428, p2=0x418) 释放p1到unsorted_ bin 申请更大的堆块(0x438)使p1进入large_ bin 释放p2到unsorted_ bin 修改p1的bk_ nextsize指向target-0x20 再次申请大堆块(0x438)使p2进入large_ bin 攻击完成:target被写入p2的头指针 关键代码分析 攻击流程图示 初始状态:p1和p2在unsorted_ bin malloc(0x438)后:p1进入large_ bin free(p2)后:p2进入unsorted_ bin 修改p1的bk_ nextsize 再次malloc(0x438)触发攻击 高低版本差异对比 | 特性 | glibc-2.23 | glibc-2.31 | |------|------------|------------| | 检测机制 | 无 | 新增两个链表完整性检测 | | 可写目标数量 | 可同时写两个地址 | 只能写一个地址 | | 攻击复杂度 | 相对简单 | 需要更精确的控制 | | 适用场景 | 更广泛 | 受限但仍可利用 | 实际应用案例:LitCTF2024 Heap2.39 题目特点 高版本堆(glibc 2.39) 限制size大小,适合large_ bins攻击 有UAF漏洞 可主动触发exit 利用步骤 泄露libc和heap基址 布置堆结构: 创建多个大堆块(0x508, 0x510, 0x500, 0x520, 0x500) 释放特定堆块到unsorted_ bin 利用large_ bin攻击修改_ IO_ list_ all 伪造IO结构,使用House of Apple2的_ IO_ wfile_ overflow控制执行流 触发exit执行shell 关键代码 总结 large_ bin攻击是一种强大的堆利用技术,尽管高版本增加了防护措施,但仍然可以通过精心构造的攻击链实现利用。理解large_ bin的组织结构和攻击原理对于现代堆漏洞利用至关重要。在实际应用中,通常需要结合其他攻击技术(如IO_ FILE利用)来实现完整的攻击链。