基本信息

标题:FuzzingBrain V2: A Multi-Agent LLM System for Automated Vulnerability Discovery and Reproduction

作者:Ze Sheng、Zhicheng Chen、Qingxiao Xu、Kewen Zhu、Jeff Huang(Texas A&M University)

关键词:大语言模型(LLM)、多智能体系统、模糊测试(Fuzzing)、漏洞挖掘、MCP(Model Context Protocol)、OSS-Fuzz、AIxCC 2025

原文链接:https://arxiv.org/abs/2605.21779

论文要点

论文简介:这是一篇面向真实软件安全场景的系统论文。作者提出了 FuzzingBrain V2 ——一套构建在 Google OSS-Fuzz 之上的多智能体 LLM 漏洞挖掘系统。系统针对当前 LLM 漏洞检测中的三个根本性问题(无法复现验证、定位粒度不合适、跨函数上下文推理能力不足)分别给出工程化解法,引入了介于行级和函数级之间的"可疑点(Suspicious Point, SP)"抽象、逻辑驱动的层次化搜索策略以及双层模糊测试,并通过 MCP 协议把静态分析与动态分析工具同时暴露给智能体使用。

在 AIxCC 2025 决赛 C/C++ 数据集上达到 36/40(90%)的检测率,并在真实部署中发现 41 个零日漏洞,其中 26 个被维护者确认、23 个已修复,ImageMagick 漏洞还获得了 CVE-2026-23874 与 CVE-2026-23952 两个编号。论文的价值不仅在于结果好看,更在于它把"发现-定位-复现-报告"的完整链路全部自动化,真正解决了"AI 报漏洞但不可验证"这个长期困扰行业的核心痛点。

研究目的:作者要回答的核心问题是:能不能用 LLM 多智能体在大型 C/C++ 项目里既挖到深层漏洞、又同时给出可复现的 PoC 输入,而不是输出一堆不可验证的"看起来像漏洞"的报告。围绕这个目标,论文希望构建一套可以无需额外配置就直接落到 OSS-Fuzz 上千个项目上、能保证 100% 可复现、并能自动产出可提交报告的工业级系统。

研究贡献:论文一共做了四件事。

第一,提出了端到端的多智能体漏洞挖掘系统 FuzzingBrain V2,所有被确认的漏洞都通过 OSS-Fuzz 现成的模糊测试器和 sanitizer 100% 可复现,并能自动生成 submission-ready 的报告。

第二,提出 Suspicious Point(SP)这一新粒度抽象,用控制流地标而不是行号去描述可疑代码区域,既能精准定位又能让 LLM 配合 fuzzer 完成复现。

第三,提出逻辑驱动的层次化搜索策略,配合 SP Fuzzer + Global Fuzzer 双层模糊测试,在资源受限场景下把覆盖率和深度都拉起来。

第四,在 AIxCC 决赛 C/C++ 数据集上拿到 36/40 (90%) 的检测率,并在 19 个开源项目里挖到 41 个零日漏洞,其中 26 个被确认、23 个被修复,实战效果直接对得起工程论文的价值。

引言

如果把视角拉回到整个软件安全行业的现状,情况其实相当"魔幻"。CVE 漏洞披露数从 2020 年开始一路狂飙,2024 年突破 4 万,2025 年逼近 5 万,几乎是历史高点的两倍以上。论文一开头就贴出这条触目惊心的曲线,告诉读者一个非常残酷的事实:漏洞披露速度已经远远超过传统人工审计与单点工具的处理能力。雪上加霜的是,微软和谷歌的研究都指出,C/C++ 代码库中大约 70% 的安全漏洞与内存安全有关,而 CISA 在 2025 年也专门发文强调内存安全语言的重要性。同年 12 月发生的 MongoBleed 事件(CVE-2025-14847)更是直接让八万多台 MongoDB 服务器暴露在未认证内存泄漏之下。换句话说,内存安全漏洞依旧是基础设施级别的"持续性威胁"。

更微妙的是,生成式 AI 在写代码这件事上越走越远,开发者用 AI 助手写出的代码反而表现出更高的"过度自信",研究指出这类代码的安全性往往低于人手写的版本。也就是说,当我们一边用 AI 大量产生代码,一边却没有同等强度的自动化安全工具去托底时,安全债务正在以指数级速度累积。

正是这种"漏洞越来越多、人工越来越追不上"的背景,让 LLM 自动挖洞从一个学术议题变成了一种产业刚需。但 LLM 真的能挑这个担子吗?这就要回到现实——直接把 LLM 丢去当漏洞分析员,一上场就会撞墙。

研究背景

作者在引言里把 LLM 直接做漏洞检测面临的三个"鸿沟"说得相当清楚,而这三个鸿沟也直接定义了 FuzzingBrain V2 的设计目标。第一个鸿沟是可验证性。LLM 生成的漏洞报告往往读起来头头是道,但没有可执行的 PoC,安全团队拿到一份报告后完全没法判断这是真漏洞还是模型幻觉,导致大量精力被浪费在虚假告警上。第二个鸿沟是粒度。函数级分析过于粗糙,模型在长上下文里容易出现注意力偏置,某些模式会被反复关注,而其他模式则被忽略;行级分析又过于精细,缺少必要的上下文,假阳性率居高不下。第三个鸿沟是跨函数上下文。真实漏洞往往跨越多个函数、涉及间接调用、依赖复杂的程序状态,而 LLM 单点推理很难覆盖这种跨函数的数据流和控制流。

针对这三个鸿沟,FuzzingBrain V2 给出了三组解法。对第一个鸿沟,系统把 Google 的 OSS-Fuzz 框架直接接成验证后端,任何被报告的漏洞都必须能在已有的 fuzzer + sanitizer 上被实际触发,这意味着报告等价于一份可重放的 PoC 而不是一段自然语言描述。对第二个鸿沟,作者提出 Suspicious Point(SP)抽象,把 LLM 关注的粒度卡在"控制流相关代码区域"这个新位置——既比行级有上下文,又比函数级精细。对第三个鸿沟,系统采用多智能体协作架构,让不同角色的智能体分别负责提取上下文、追踪数据流、推理状态,以分工协作的方式承担起跨函数推理。

系统设计

FuzzingBrain V2 的整体架构可以理解成一座完全自动化的安全分析工厂。最外层是一个 Controller,负责编排静态分析、智能体流水线执行和模糊测试三大模块;静态分析借助 Fuzz-Introspector 等工具构建出整个项目的调用图,把所有函数的元数据、调用关系以及"哪些 fuzzer 能到达哪些函数"标注清楚。Controller 拿到这张全局图之后,会按 (fuzzer, sanitizer) 对的方式划分工作单元,把每个组合分给一个 Worker。每个 Worker 在自己的子图上独立跑完整套智能体流水线,从而实现并行化扩展。

这种"按 fuzzer × sanitizer 切片"的设计背后有一个关键洞察:不同 fuzzer 走的代码路径不同,不同 sanitizer 检测的漏洞类别也不同,把它们解耦成独立 Worker,既避免互相干扰,又能用最简单的方式拿到并行收益。一个项目有 F 个 fuzzer 和 S 个 sanitizer,系统就最多产生 F × S 个 Worker,各自处理自己的子任务。

在每个 Worker 内部,智能体被分到三层模型上跑:T1(O3、GPT-5.2-Pro、Claude-Opus-4.5)负责复杂推理与战略规划,T2(Claude-Sonnet-4.5、GPT-5.2、Gemini-3-Pro)负责代码分析这一类核心工作,T3(Claude-Haiku-4.5、GPT-5-Mini、Gemini-3-Flash)负责上下文压缩等轻量任务。这种分层既能在重要节点用最强模型抠细节,也能用便宜模型批量处理琐碎工作,把成本和效果做到平衡。智能体团队包括 Direction Generator(把代码切成业务方向)、SP Generator(初筛可疑模式)、SP Deduplicator(合并重复 SP)、SP Verifier(深度验证)、PoC Generator(生成触发输入)、Report Agent(生成最终报告)、Seed Generator(为 fuzzer 生成种子)与 Context Compressor(为跨函数分析压缩上下文)。

(1)Suspicious Point

整套系统里最值得展开的设计,毫无疑问是 Suspicious Point(SP)。所谓 SP,其实是介于"一行代码"和"整个函数"之间的一种新粒度。它不再用行号去标记可疑代码——因为 LLM 几乎一定会幻觉出错误的行号——而是用"控制流地标"来描述,例如"在第二个 if 分支进入循环之后、调用 memcpy 之前"。这种描述方式让 LLM 既能给出足够精细的位置,又不会因为行号偏移而失真。

每个 SP 都有一套完整的字段:所属函数、来源、自然语言描述、漏洞类型、初始评分;经过验证后会补上 is_verified、最新评分和 PoC 指引;再经过 PoC 生成后,还会补上 is_real、尝试过的 fuzzer 列表和 PoC ID。SP 的生命周期被拆成三个阶段——创建、验证、PoC 生成——并且各 SP 之间相互独立,这意味着多个 SP 可以并行验证、并行生成 PoC,把整个流水线的吞吐进一步提升。

这个设计的妙处在于,它既照顾了 LLM 的能力上限(不让它做行号这种容易翻车的工作),又给了 fuzzer 足够的语义信息(让 PoC Generator 知道要瞄准哪一段控制流)。可以说,SP 是连接"语义推理"和"动态复现"的关键桥梁,是整个系统能把可复现率拉到 100% 的前提。

(2)逻辑驱动的层次化搜索

在 SP 之上,作者构建了一套逻辑驱动的层次化搜索策略,把每个 Worker 都变成一台分工明确的小型工厂。Worker 启动后,Direction Generator 会先把整个代码库切成若干"业务方向",每个方向对应一组语义相关的功能,比如 libpng 里的"PNG chunk parsing"。每个方向都包含名称、入口函数、核心函数、风险等级和风险原因。这种按业务功能而不是按漏洞模式分组的做法非常关键——因为 fuzzer 的设计本身就是冲着"功能"去的,而不是冲着"buffer overflow"或"use-after-free"这种特定 Bug 类型去的。在功能维度上聚类,后续的智能体就能在一个语义自洽的小区间里集中分析,效率远高于在整个项目里漫游。

具体到执行层,系统提供 Full-Scan 与 Delta-Scan 两种模式。Full-Scan 由 Direction Generator 切方向、SP Generator 在每个方向里做初筛、再交给 Verifier 与 PoC Generator 完成深度分析与触发,适合在一个新项目上做完整体检。Delta-Scan 则把搜索范围聚焦在 commit 改动的函数上,适合 CI 集成场景,让安全分析跟着代码变更同步发生。两种模式最后都会汇到同一条 SP 验证与 PoC 生成主线,既复用了下游基础设施,又分别为"全量普查"与"增量监控"提供了入口。

为了进一步提升效率,作者还给每个方向引入优先级调度:Direction Generator 把函数分进 Core Pool(入口函数 + 核心函数,高优先级)和 General Pool(其他可达函数,尽力而为),让昂贵的 PoC Generator 资源优先投在最值得分析的函数上。这一做法在消融实验中被验证非常关键——一旦把方向和优先级机制拿掉,Full-Scan 时间几乎涨了 3 倍,从 18 分钟飙到 48 分钟,而检测数量从 36 掉到 29,可以说是"不分级就崩溃"。

(3)双层模糊测试

光有智能体推理还不够,作者引入了双层模糊测试机制,把 LLM 的"靶向猜想"和 fuzzer 的"无差别覆盖"组合在一起。第一层是 SP Fuzzer,它在 SP 生成之后被调起,围绕 PoC Generator 给出的种子进行小范围、深度优先的试探,目标是把单个可疑点真的打穿。第二层是 Global Fuzzer,它在整个 Worker 的生命周期里持续跑,对所有可达代码做覆盖率驱动的广撒网,负责兜底那些智能体没识别出的、但确实存在的 Bug。

这种"前台靶向 + 后台兜底"的搭配在消融实验中也非常显眼。当系统去掉 SP Fuzzer 时,虽然总耗时降到 2 分钟,但检测数量从 36 暴跌到 19,而且零个 hard challenge 被发现,这说明纯靠 fuzzer 撞运气根本拿不下复杂漏洞;反过来,当系统去掉 Global Fuzzer 时,检测数从 36 降到 35、hard challenge 仍然能拿下 8/12,但是 Delta-Scan 时间从 12 分钟翻到 24 分钟、Full-Scan 也从 18 分钟拉到 31 分钟,因为没有了广覆盖兜底,系统不得不让 SP 流水线承担更多本可以由 Global Fuzzer 直接搞定的浅层 Bug。两层 fuzzer 一前一后,把命中率和效率都顶住了。

(4)MCP 工具协议

在工具层,FuzzingBrain V2 用 MCP(Model Context Protocol)把静态分析(SAST)和动态分析(DAST)统一暴露给智能体。SAST 工具可以让智能体读源码、查调用关系、追踪数据流;DAST 工具可以让智能体提交输入、看 fuzzer 真实运行情况、读取 sanitizer 报告。这种"工具是一等公民"的做法,让智能体不再是只会输出文本的语言模型,而是真的能"动手"做实验、看结果、再调整假设的研究员。

在论文给出的 Case A(Leap Second OOB)案例里,这种工具能力的价值被展现得淋漓尽致。这是一个深度 10 的漏洞,出现在某协议时间戳处理函数中,只有当解析到包含闰秒(seconds=60)的响应、并且这个闰秒还要刚好绕过日期校验时,才会触发越界。FuzzingBrain V2 在迭代过程中,先靠静态分析把可疑函数定位出来,然后通过 DAST 工具发现"目标函数根本没被命中",于是智能体改变假设,系统性地枚举不同的历史闰秒,直到迭代到第 40 次左右拿到了一个能真正命中目标函数的输入,最终在 127 次迭代内成功把漏洞挖出来。这种"假设-验证-修正"的闭环,正是工具协议带给智能体的核心战斗力——没有动态反馈,LLM 就只能凭直觉猜,猜错了也不知道。

实验设置

接下来是大家最关心的部分:这套系统到底能打吗?答案是相当能打。在 AIxCC 2025 决赛 C/C++ 数据集上,FuzzingBrain V2 在 40 个挑战题中拿下了 36 题,检测率 90%,显著高于同期其他参赛队伍。其中 12 道被标记为"hard challenge"的题目——具有深调用链、复杂依赖、被其他 Bug 遮蔽或需要顺序触发等特征——FuzzingBrain V2 拿下 9 道(75%),而对比的 Team Atlanta 只拿下 5 道(42%)。Delta-Scan 平均每题 12 分钟、19.4,Full-Scan 平均每题 18 分钟、35.2,40 道题的总成本是 $1,785.60、共消耗 526M token,把"高命中"和"成本可控"同时做到了。

更值得一提的是 Verifier 的召回率高达 97.2%——36 个真阳性里有 35 个被它确认为真阳性。作者特别强调,他们的设计哲学是"宁可让 PoC Generator 在动态阶段过滤掉假阳,也不能让 Verifier 把真漏洞误杀",因为后者一旦丢失就再也找不回来了,这种偏召回的策略很值得后续工作借鉴。

在更贴近真实世界的部署中,FuzzingBrain V2 在 19 个开源项目上跑出了 41 个零日漏洞,每个项目预算 $200(根据 fuzzer 数量略作调整)。OpenPrint CUPS 一个项目就贡献了 6 个,fwupd 和 upx 分别贡献 4 个,bluez 5 个,avro 3 个等等。截至论文提交,26 个漏洞已经被维护者确认,23 个已经修复。值得一提的是,作者并没有主动申请 CVE,但 ImageMagick 的维护者主动为这一系统挖到的漏洞申请了 CVE-2026-23874 和 CVE-2026-23952。这意味着 FuzzingBrain V2 不是只在 benchmark 上漂亮,而是真的能在大型成熟项目里挖到没人发现过的真实漏洞。

从消融实验也能看清每个模块的边际贡献。去掉 DAST 工具,系统在 Full-Scan 模式几乎全部超时——也就是说,没有动态反馈,智能体就只能瞎猜,会无止境地堆 SP;去掉 Verifier,Full-Scan 时间从 18 分钟暴涨到 31 分钟,因为下游 PoC Generator 不得不在大量未筛选的 SP 上做无用功;去掉 Direction 机制,Full-Scan 时间翻 3 倍、命中数掉 7;去掉 SP Fuzzer 命中数掉一半;去掉 Global Fuzzer 命中数稍微下降但效率显著变差。每个组件都对最终的 36/40 有贡献,而且组合起来呈现明显的协同效应。

(1)漏洞类型分布

作者还专门统计了挖出来的漏洞类型分布,结果与整个内存安全行业的形势高度一致。NULL Ptr Deref(空指针解引用)是最多的一类(7 个),其次是 Heap Buffer Overflow(6 个)、Memory Leak 与 Denial of Service 各 5 个、Stack Overflow 4 个、Path Traversal 3 个,以及 11 个其他类型。这种分布几乎照搬了 AFC 数据集的内部比例,作者据此认为系统的检测能力可以良好地泛化到真实场景,而不是过拟合到 benchmark 上特定的几类 Bug。

从安全工程师的视角看,这种结果其实非常关键。它说明 FuzzingBrain V2 不是一个"擅长某一类漏洞的特种工具",而是一个面向通用内存安全风险的全能选手——这意味着把它直接嵌入到现有的 OSS-Fuzz 流水线、把覆盖面从特定漏洞模式扩大到主流内存安全大类,边际投入产出比是相当高的。

(2)当前的局限

论文也很坦诚地讨论了 FuzzingBrain V2 当前的几个限制。第一类是多输入漏洞:有些挑战需要在同一次会话里发出多个互相依赖的输入才能触发,而当前架构主要面向"单输入"语义,这一类在 AFC 中有一题没能拿下。第二类是漏洞遮蔽:在某些目标里,先触发的浅层 Bug 会让 Worker 提前终止,导致更深的目标 Bug 永远没机会被触发;这种现象在测试时也吃掉了一题。第三类是隐式状态机:一些漏洞需要客户端先完成几步隐式协议交互(比如握手、加密协商)才能进入脆弱代码,而这种状态机如果没有显式表达在源码里,纯静态分析很难重建出来,智能体就会在错误的方向上反复浪费迭代。

这些限制其实非常具有研究价值——它们指明了下一步该往哪个方向走:多输入序列推理、Bug 遮蔽下的"绕障"策略、以及对协议状态机的自动建模,都是值得继续深入的子问题。某种意义上,这些"未解的硬题"也定义了 LLM 漏洞挖掘的下一波 SOTA。

论文结论

从更高的视角看,FuzzingBrain V2 真正打动人的地方,不是某一个单点创新,而是它把一系列在各自领域已经被验证有效的思路,以工程化的方式拼成了一台完整的机器。它把 LLM 的语义理解放在了它最擅长的位置——业务逻辑切分、可疑模式识别、PoC 思路构造;把 fuzzer 放在了它最擅长的位置——动态执行、覆盖率扩张、崩溃复现;把 sanitizer 放在了它最擅长的位置——内存错误判定;再用 SP 这个新粒度作为粘合剂,把三者的产出对齐到同一个抽象层。MCP 协议则是让智能体真正"长出手脚"的关键,使它从一个文本生成器升级成一个能做实验的研究员。

对工程实践来说,这篇论文给出的启发也非常实用。第一,LLM 漏洞挖掘必须配备可验证后端,否则报告就是垃圾;OSS-Fuzz 是一个非常合适的现成选择。第二,"粒度选择"是个核心设计决策,既不要让 LLM 看一行,也不要让它看一整个函数,Suspicious Point 这种基于控制流地标的中间粒度可能是更通用的方向。第三,多智能体不是简单地把任务拆开,而是要把每个角色绑定在合适的模型层级上,让算力和成本各司其职。第四,LLM 的强项是"提出假设",而 fuzzer 的强项是"验证假设",两者一定要做闭环,而不是各做各的。第五,业务逻辑而非漏洞模式才是更好的搜索单元,因为 fuzzer 的 harness 本来就是对功能做的。

如果要给这篇论文画一句总结,那就是:在漏洞数量爆炸、AI 写代码越来越多的时代,FuzzingBrain V2 展示了一种切实可行的"AI vs AI"路径——用一群协同工作、各司其职的智能体,以工程级标准把漏洞从发现到复现做到自动化。它把 LLM 漏洞挖掘从一个学术 demo,推到了"可以直接跑在 1000 多个开源项目上、并且真的挖到 CVE"的工业可用阶段。对于关心 AI 安全、LLM 代理工程或下一代 DevSecOps 工具链的从业者而言,这是一篇非常值得反复研读的论文。

声明:本文来自安全极客,版权归作者所有。文章内容仅代表作者独立观点,不代表安全内参立场,转载目的在于传递更多信息。如有侵权,请联系 anquanneican@163.com。