AI 自动化逆向(三十四)自建指令缓存:把分钟级查询压到秒级
本文是「AI 自动化逆向」系列第 34 篇。上一篇:换一个「驱动器」,覆盖率跳了一个量级;下一篇预告:假设空间枚举的完备性是假设出来的。
前言
上一篇的收尾说:所有这些"当场重跑、当场对账"的纪律,要有一件东西付得起------这一篇就讲它。
它是一件自建的基础设施:指令缓存 。作用一句话:把"分钟级"的查询压到"秒级"。听起来像纯粹的工程优化------不是。它是纪律的地基。
(同前几篇:文中"AI"指执行分析的模型,"我"指设定目标、审结果的人;内容均已脱敏。)
一、AI 在这里踩的坑:没有缓存,纪律就"贵"
先看没有它的日子:想查"某个字符串被谁引用"(一次交叉引用)、想看"某段地址附近的几条指令"(一次窗口反汇编)------每一个小问题,都要从头把整个二进制扫一遍,分钟级。
一天里这样的查询要发生几十次。于是出现两件坏事:
- 时间被烧掉------这个可见;
- 更隐蔽的:纪律变贵了 。"当场重跑""当场对账"在分钟级的成本面前,很容易被绕过一句"这次就算了"------第 18 篇的账:纪律如果比违反它更贵,它就形同虚设。
所以缓存的定位不是"更快",是让正确的工作方式变成最省力的方式。
二、过程:缓存怎么造
三步,每一步都带着前面的教训。
第一步:重同步扫描------先把"扫全"这件事做对
不能用"从起点顺着读"的老办法(第 1 篇的老坑:流式解码遇到解不动的字节就安静地停)。重同步扫描的规则是:逐字节尝试解码,遇到坏字节就退一个字节重新起步 ------并且报告覆盖率("扫完了"还是"半路停了",必须分得开)。
第二步:存成"已对齐校验"的指令清单
扫描产出的是每条指令的地址、字节、助记符 ------近九十万条,存成一个紧凑文件。特点:加载即用 ;重扫一遍只要十秒级(可以接受),但没必要每次都做------缓存的意义就在这里:一次扫描,长期受益。
第三步:把查询暴露成"一次调用"
缓存之上开两个口子:
- 反查"引用某个立即数的指令"(交叉引用)------一次调用,秒级返回;
- 取"某地址附近的窗口反汇编"------同样一次调用。
到这一步,"查一下"从"一个工程任务"变成"一个随手动作"------上游的一切验证纪律,从此付得起。
三、判据与验证:缓存自己的两条纪律
缓存是工具,但工具也要被纪律管------而且是两条它特有的。
纪律一:缓存必须与"另一条独立路径"互相校验
缓存是"一种扫描的产物",它不是从天上掉下来的真源。这个项目里的做法是:
- 这个缓存(近九十万条)由两套独立实现 分别重扫,得到完全相同的总数 ------互证;
- 同时它还要和线性反汇编对得上:两条路径、两份读数,一致的部分才当作可信(这正是第 20 篇"闭环"思路在工具层的应用);
- 反过来的收益更妙:当"缓存与线性解码双证一致 "时,它就能当新结论的证据 ------这个项目里有一次判定"这段字节真的是垃圾",就是靠双证一致钉死的。
缓存不是唯一真源,是"与线性解码互为裁判"的第二读数。
纪律二:缓存文件之间的"类型约定",不可迁移
这一条是血的教训。这个项目的缓存有个特性很容易出事:同一个批次里,有的文件把地址存成整数、有的存成字符串;甚至同一份缓存在不同代码路径上的形态都不一样。而 AI 已经为"字段名/类型"栽过四次(第 10 篇的账)。
于是纪律两条:
- 用之前,每个文件各测一次 :
print(type(x), repr(x)); - 不许跨文件推断类型 ------"上一个缓存里它是整数"这个知识,对下一个缓存没有效力。
为什么缓存特别容易这样?因为它是多轮工作的"遗产" :每一个生成者都按自己的理解存字段,而缓存很少被回头看 。遗产要验明正身------"看起来是个熟悉的文件"不是"和上次那个一样的文件"。
(还有一条通用版:缓存要让"当场重跑"变便宜,才算完成使命------别把它做成又一件"不敢动、也懒得验"的老物件。)
四、结论
一句话:缓存是把纪律从"贵"变"便宜"的设施。
它不产出结论------它让验证结论 这件事变得随手可做;而它的可信,来自它自己那两条纪律:与独立路径互证、类型逐个验。设施越基础,越值得被纪律管------因为它一旦"看起来权威",全项目都会跟着它一起错。
五、边界声明
- 本文只讨论AI 自动化逆向中的判据设计与审核方法,不涉及任何具体产品、厂商或服务的分析结论。
- 文中所有地址、偏移、常量、字段名一律为占位符或示意值 ,
不代表任何真实目标中的取值;示例代码为说明判据而编写,不构成可运行的针对特定目标的工具。 - 文中提到的比例与数字均来自作者项目内的测量记录,仅用于说明方法失效的方式。
- 请勿将本文内容用于未授权的用途。
六、收尾
工具讲完了。下一篇去协议战场,讲一个"自信的穷举"是怎么错的:两万多种组合全部失败------不是因为敌人太强,是因为假设空间本身漏了一种形态。
下一篇计划聊:假设空间枚举的完备性是假设出来的。

转载请注明出处: