做一个固件安全 Agent:从让 AI 帮我整理线索开始

agentai
2026-07-10 02:29
608

先说清楚一个问题:为什么需要 Agent,直接把固件丢给 AI 分析不够吗。

做过固件分析的人大概都有体会:单纯聊天式地用 AI,一开始很顺手,但任务一长就容易出问题。一次完整的固件分析,通常要走这些步骤:

固件包
  │
  ├─ 解包 rootfs
  ├─ 找 Web 入口
  ├─ 找 CGI、后端程序
  ├─ 搜索危险函数和关键参数
  ├─ 追踪参数来源
  ├─ 尝试运行或模拟服务
  ├─ 整理候选漏洞
  └─ 生成报告和证据

这不是问一句答一句能搞定的事,中间会攒下大量文件、日志、尝试记录、走过的弯路,最后才是能站得住的证据。如果只靠聊天窗口,几个问题很快就会冒出来:聊得久了前面的细节容易被压缩;记不清之前为什么排除了某条路径;容易把一次失败的尝试当成最终结论;工具调用和文件状态不稳定,难以复现;日志、分析、报告混在一起,后面很难理清;下次再分析,也很难接着上次的状态继续。

AI 确实能帮你理解代码、归纳线索、给出下一步方向,但没有一套流程兜着,很容易变成一个聪明但健忘的帮手。

这里说的 Agent,不是让 AI 自己全自动挖洞,而是把 AI 放进一套可以重复、可以记录、可以扩展的流程里,让它在合适的时机调用工具、读取之前的状态、整理出结论。大致是这样一个循环:

   输入:一个固件目录
        │
        ▼
   ┌───────────────────────────────────┐
   │                                     │
   │   看看之前做到哪了、发现了什么       │
   │        │                            │
   │        ▼                            │
   │   参考经验规则,决定这一步该干什么    │
   │        │                            │
   │        ▼                            │
   │   调用对应的工具,真正执行这一步      │
   │        │                            │
   │        ▼                            │
   │   把干了什么、结果如何记下来 ────┐    │
   │        ▲                        │    │
   │        └────────────────────────┘    │
   │           没做完就回到第一步继续       │
   │                                     │
   └───────────────────────────────────┘
        │
        ▼
   输出:候选问题清单 + 一份报告

Agent 干的事不是把几个工具堆在一起,而是让 AI 反复走这个看状态、定下一步、干活、记结果的循环,每一圈都基于上一圈留下的记录往下走,直到任务做完。工具和经验规则是循环里被调用的素材,Agent 是驱动这个循环转下去的那部分。

为什么要非交互式地用 AI

很多人第一次拿 AI 做安全分析,是打开聊天窗口,把日志贴进去,问一句这里有没有漏洞。临时问一句可以,但撑不起一条长期跑的流水线。更合适的做法是让程序或命令行在后台直接调用 AI,而不是靠人守在聊天框里一来一回:

不是这样:
人 ──复制日志──▶ 聊天窗口 ──回答──▶ 人

而是这样:
程序/脚本 ──任务描述──▶ AI
        ▲                  │
        │                  ▼
   状态文件、日志 ◀── 工具调用、分析结果

这样 AI 就不只是一个聊天对象,而是分析系统里的一个干活节点。可以固定地给它喂进去这些信息:当前固件的路径、rootfs 解包出来的目录、之前的扫描结果、已经找到的 Web 入口、报告要写成什么格式、能用哪些工具、之前积累的经验和项目里的规矩。

它还可以接入别的能力:一种机制负责给 AI 接工具,一种机制负责给 AI 接经验,Agent 负责让 AI 按流程干活。举个例子:

AI
  │
  ├─ 工具:读取 rootfs、搜文件、跑分析脚本、启动模拟环境
  │
  ├─ 经验:固件分析的流程、报告要怎么写、常见的误判提醒
  │
  └─ 状态文件:记着已经分析过什么、哪些结论确认了、哪些还只是猜测

这样 AI 的记忆就不用全靠模型自己记着了。模型可能会忘事,但文件不会忘;聊天记录可能被压缩,状态文件还在;一次分析可能中断,但任务和日志还能接着往下走。

借力:让 AI 指挥专业工具,而不是自己硬算

接工具这件事,具体到固件分析里,接的往往是一些已经很成熟的专业软件:反汇编用 IDA,调试用 GDB,跑仿真用 QEMU。这些工具能读懂各种芯片架构,能把机器码翻译成能看懂的代码,能在虚拟环境里把固件的程序跑起来、单步跟着走。这些活 AI 自己干不了,也不需要它自己干。

Agent 的角色是把这些工具当成手脚去用。碰到一个可疑函数,调用 IDA 反编译成结构化代码,AI 再去读代码做判断;怀疑某处存在溢出,调用 GDB 挂断点,发一个畸形请求过去,看程序崩没崩、崩在哪;要验证一个漏洞能不能被利用,把固件丢进 QEMU 里跑起来,实际打一遍看结果。

AI 判断该往下查这个函数
        │
        ▼
调用 IDA:把机器码变成能读的伪代码
        │
        ▼
AI 读代码,找出可疑的点
        │
        ▼
调用 GDB / QEMU:真的跑一遍、断点看一看
        │
        ▼
AI 根据真实运行结果,判断这个问题是不是站得住

AI 负责读懂结果、做判断、决定下一步查什么,跟机器码和运行环境打交道的部分交给 IDA、GDB、QEMU 这些专门工具。这样 Agent 不用自己重新实现反汇编器或调试器,也能借助这些工具多年积累下来的能力,做一些聊天式 AI 单靠自己做不到的分析。

固件安全 Agent 真正的价值不是替代安全研究员,而是解决几个实际问题:

没有 Agent:
  AI 每次都像重新开始
  工具全靠手动调
  日志全靠人整理
  结论容易乱
  流程没法复现

有 Agent:
  流程是固定的
  工具是可控的
  状态能保存下来
  结果能一路追踪
  报告能反复生成

先做个基础版可以快速加深理解:给一个固件目录,自动整理出 Web 文件、可执行程序、危险函数命中情况、可疑参数和候选问题,最后生成一份 Markdown 报告。AI 在这里干的不是拍脑袋判断有没有漏洞,而是帮你把一大堆零散线索整理成更容易继续往下分析的东西。这是固件安全 Agent 比较适合入门的起点。

开发语言:为什么选 Python

解包文件、跑脚本、拼提示词、调用外部工具、整理日志、显示界面。这种把很多不同概念快速粘连起来的事情,适合选择胶水语言Python:

  • 生态成熟。固件分析常用的解包、反汇编相关工具,大多本身就是 Python 写的,或者有现成的 Python 接口,不用自己造轮子。
  • 改起来快。Python 是脚本语言,加个字段、改个流程不用大动干戈,适合边做边调整思路。
  • 上手门槛低。做安全研究的人大多本来就会 Python,不用为了写工具再学一门新语言。

GUI 用什么

想做个带界面的版本,方便实时看任务进度、日志和状态,比较省事的做法是用桌面 GUI 框架,比如 Python 的 PyQt,而不是再搭一个网页服务。固件分析通常是本地跑的长时间任务,桌面界面能直接把跑到哪一步了实时显示出来,不用管网页那一套登录、跨域、刷新丢状态的麻烦事,个人或小团队自己用比较合适。

更大的杠杆:直接用现成的 AI Agent

自己写的这一层,管的是流程固定、状态记录、结果可查这些事。真正去理解固件代码、判断有没有漏洞、想办法验证问题这部分智力活,没必要自己从头搭一套 AI 推理和调用工具的循环,直接用现成的、已经很成熟的 AI Agent,把它当成整个流程里的一个执行环节就够了。

现在比较主流的通用 AI Agent,一个是 Anthropic 的 Claude Code,一个是 OpenAI 的 Codex。它们都能在命令行里用,也都支持非交互模式:不用人坐在那一问一答,直接把任务描述丢给它,它自己去读文件、跑命令、调用工具,跑完把结果和日志留下来。

自己写的调度程序,把当前要分析的固件、目标、之前攒下的经验整理成一段任务描述,用非交互模式启动 Claude Code 或 Codex,把这段描述交给它;它在后台自己分析、验证、记录;调度程序只需要盯着输出,把关键信息存下来、更新任务状态、最后生成报告。

自己的调度程序
     │
     │  整理好这次要分析什么、目标是什么
     ▼
非交互方式启动 Claude Code 或 Codex
     │
     │  它自己读文件、跑命令、做分析
     ▼
把过程和结论记下来 ──▶ 更新任务状态、写报告

同一个任务,既可以用 Claude Code 跑,也可以换 Codex 跑,两边可以互相验证,也能当备用通道。这两个工具都支持接入外部工具、固化经验的机制,能让它们具备比普通聊天助手更强的专业分析能力,不用每次都从头解释一遍该怎么做。

自己动手做的部分,不是重新造一个会推理、会用工具的 AI,而是搭一套流程,把这些已经很强的现成 Agent 安排到合适的位置上,负责调度它们、记录它们干出来的东西、把零散结果整理成一份有用的报告。

入门先跑起来:用 DeepSeek 的 API 练手

Claude Code、Codex 这些工具默认接的都是自家的模型,正经用起来不便宜。如果只是想先体验一下 AI 自己读文件、跑命令、干活这套流程是什么感觉,不想一上来就投入太多,一个常见做法是把 Claude Code 之类的工具接到 DeepSeek 的 API 上去跑。这些 Agent CLI 大多支持换模型来源,配置好之后,命令行里用的还是同一套 Claude Code,界面、用法、能调用的工具都没变,只是背后真正干活、给出判断的模型换成了 DeepSeek。

推荐拿它练手,主要两个原因:一是便宜,跑一遍完整的分析流程,Agent 少不了来回读文件、跑命令、反复调用模型,调用次数很容易上百上千次,DeepSeek 的价格比很多主流大模型便宜不少,练手阶段可以放开了跑;二是能力够用,拿来读代码、总结日志、判断一个函数像不像危险调用,效果完全够,不会因为模型能力跟不上卡住入门阶段的体验。

等对这套流程、这些工具的用法都摸熟了,再看要不要换成能力更强的模型去啃更难的目标,心里也更有数,知道自己是在为更强的推理能力付钱,还是纯粹在为练手交学费。

固件安全的几个环节,Agent 具体在做什么

前面讲的都是比较抽象的道理,这里落回到固件安全本身,简单说说解密、静态分析、模拟这几个常见环节,Agent 大致是怎么把它们跑起来的。

解密、解包

固件包到手,通常是一个压缩过的二进制文件,里面可能嵌套了好几层:外层是升级包格式,剥开之后是文件系统镜像,镜像里才是真正的程序和配置。有些厂商还会在外面再加一层加密或者签名校验。

这一步大部分是体力活:先用工具识别文件头、猜测格式,再一层层剥开,直到拿到里面完整的文件系统目录。遇到加密的情况,常见做法是找厂商公开的升级工具或者别的固件里带的密钥,试着解开,解不开就换下一种已知方法试。Agent 在这里做的事,主要是按顺序调用这些现成的解包工具,一层一层往下剥,剥开一层就检查一下结果对不对,不对就换个参数或者换个工具再试,剥到能看见完整的文件系统目录为止。判断某种解密方法对不对、要不要换下一种,这部分是 AI 在判断,真正做解压、解密运算的还是那些工具。

真要让 Agent 开始干这一步,交代给它的任务描述可以很简单,比如:

这里有一个固件文件 xxx.bin,帮我把它解包出来,如果外层有加密或者签名校验,先尝试常见的几种解密方式,都解不开就把已经试过的方法和失败原因记下来,最后告诉我文件系统目录在哪。

剩下识别格式、选工具、试参数这些具体操作,交给 Agent 自己按前面说的逻辑去试就行,不需要人再手把手教它每一步该用什么命令。

静态分析

文件系统拿到手之后,下一步是在不运行程序的情况下,先看代码本身能看出什么问题。这一步通常分两层:先粗筛,再细看。

粗筛阶段,用工具在所有二进制文件里搜索一些经验上容易出问题的函数调用,比如拼命令行的、拷贝内存的、处理用户输入的。这一步搜出来的东西数量不小,大部分是没问题的正常调用,只是先都记下来当候选。细看阶段,才是 AI 真正发挥作用的地方:把每个候选点反编译成能读的代码,逐个判断这个函数被调用时传进来的参数,到底是不是来自外部用户能控制的地方,中间有没有做长度检查或者过滤。这一步筛下来,候选点通常会少掉一大截,剩下的才是真正值得往下追的。

对应的任务描述大概是这样:

在这个固件的文件系统里,找出所有调用了危险函数的地方,按照参数是否可能被外部输入影响排一下优先级,前几个高优先级的,反编译看一下具体逻辑,判断是不是误报,把结论和理由整理成一份候选列表。

这条任务里没有具体规定先用哪个工具搜、怎么反编译,这些细节留给 Agent 自己安排,人只需要说清楚要筛选的标准和最后想要的结果。

模拟运行

前两步都是纸面上的分析,看着像问题,不代表真的能触发。要确认,还是得让程序实际跑起来,发一个请求过去看反应。

固件里的程序大多是给特定芯片架构编译的,不能直接在电脑上跑,需要借助模拟器把这颗芯片的运行环境模拟出来,再把固件里的文件系统放进去,把对应的服务进程启动起来。这一步经常会遇到各种环境问题:程序启动时要读一些原本由硬件或者厂商私有模块提供的东西,模拟环境里没有,直接就崩了。要让服务跑起来,得先把这些缺失的依赖一个个补上,缺什么就想办法补什么,实在补不上就换一种方式绕过去,比如换个别的入口来触发同一段逻辑。这部分环境问题层出不穷、没有固定套路,全靠 AI 一步步试错和判断该往哪个方向绕;一旦服务真的跑起来了,剩下的就是把之前怀疑的输入发过去,看程序有没有按预想的方式出问题,这时候才算是有了站得住的证据。

这一步交给 Agent 的任务描述,通常是接着上一步的候选列表往下延伸:

把这个固件的 web 服务在模拟环境里跑起来,如果启动过程中报错或者卡住,先自己排查原因、尝试修复,跑起来之后针对候选列表里的第一项,构造一个请求发过去,记录服务端的实际反应,判断这个问题是不是真的存在。

这一步最费时间的往往是环境问题的排查,任务描述里不需要预判会遇到什么问题,只要说清楚目标是把服务跑起来并验证候选问题,中间具体卡在哪、怎么解决,交给 Agent 自己一步步试。

延伸阅读

本文只讲到入门阶段该怎么想、怎么搭起第一版。如果想看固件安全 Agent 真正能做到什么程度、别人是怎么把这套流程落地的,推荐看下面两篇文章。

《FirmVulnFlow:AI 驱动的 IoT 固件漏洞挖掘管线》(unisec.vip):https://unisec.vip/blog/firmvulnflow-ai-iot-firmware-vuln-pipeline

这篇讲的是一套用 MCP 工具串起来的固件分析管线。先下载固件、解包,找出可执行文件和 CGI 入口;用 radare2 粗筛一遍,看看哪些函数调用了 system、strcpy 这类危险函数,攒出一批候选点;再拿候选点去反编译细看,判断用户输入能不能真正传到那个危险函数上,筛掉误报;确认下来的问题先去比对已有的 CVE 库;最后一步是动态验证,用 QEMU 把固件的文件系统跑起来。文章花了不少篇幅讲怎么处理路由器固件里那个很难搞的 NVRAM 依赖——很多服务一启动就要读这块配置存储,读不到直接崩溃,需要专门写一层拦截库把读写调用接管掉,服务才能正常跑起来,跑起来之后才能真正发包测试、确认漏洞是否存在。工具负责干体力活,AI 负责在遇到不确定、没有文档可查的情况时做判断。

《智能体驱动的漏洞挖掘实践》(安全内参):https://www.secrss.com/articles/89993

这篇讲的是三个角色分工的流程:一个负责侦察,把整个固件反编译一遍,摸清楚有哪些程序、接口,画出大致的结构;一个负责分析,从外部能传入数据的地方开始,顺着代码追踪数据最后流到了哪里,同时也反过来从危险操作往回查参数来源,两个方向对照是为了减少看错、看漏;最后一个负责验证,把环境搭起来,自动生成一个触发问题的脚本,丢到隔离环境里跑一遍,看日志、看有没有真的触发,而不是分析完就直接下结论。文章提到用这套流程测了一批路由器、摄像头、录像机之类的真实固件,从固件上传到出报告平均只要 2 到 5 小时,报告里确认为真实漏洞的比例在七成左右。

最后说一句

上面两篇文章的流程看着挺完整,但不用照抄。固件安全 Agent 说到底是个人工具,做成什么样很大程度上取决于自己平时是怎么分析固件的、习惯先看哪一步、又在哪些地方踩过坑。这些习惯没有标准答案,别人的管线设计得再合理,也是别人的思路,拿过来最多算个参考,不是范本。AI相关的工具概念迭代非常快速,相关技术文章的时效性可能转瞬即逝,需要保持自己的理解。

也正因为是自己写的东西,改起来没什么心理负担。这一步做得不顺手,就换个顺序;某个环节暂时用不上,就先砍掉;某天遇到一种新的固件、新的场景,发现现有流程接不住,也可以随时加一块进去。要不要支持仿真、要不要接入 CVE 库、报告要写成什么格式,全看自己觉得哪些东西真正有用,不需要谁来批准。

这也是自己动手做 Agent 和直接用别人做好的产品最大的不同:产品是别人替你想好了流程,只能照着用;自己写的 Agent,流程就是自己的思考方式本身,怎么改、改成什么样都是自己说了算,能跟着自己对固件分析的理解一起慢慢往前迭代。

还有一点值得说清楚:Agent 本质上还是一种人在回路里的东西,只是这个人在回路的方式,跟每一步都要人盯着、每一次运行都要人点头才能继续的狭义做法不太一样。前面讲的整套流程——先查什么、危险函数怎么筛、什么时候动用 IDA、什么时候算验证过关、报告怎么写、遇到解不开的问题要不要绕过去——这些判断标准是人事先想清楚、写进流程和经验规则里的,Agent 拿着这套标准去跑,而不是自己长出一套判断方式。跑的时候可以不用人盯着,但流程本身从头到尾是人的思路在起作用,效果不好、判断跑偏了,还是需要人回头去改流程、改经验规则,而不是指望 Agent 自己进化。人不用一直守在旁边,但一直在这套系统里起作用。

分享到

参与评论

0 / 200

全部评论 0

暂无人评论
投稿
签到
联系我们
关于我们