AI 自动化逆向(三十一)函数体不可读 ≠ 函数不可命名
本文是「AI 自动化逆向」系列第 31 篇。上一篇:片段级恢复:单位是片段,不是函数;下一篇预告:一次布 60 个点:怎么知道丢了几次命中。
前言
给一个函数命名,习惯上只有一条路:读它的函数体------进去看它做了什么、引用了什么、调用了谁。
夹层出现之后,这条路对一部分函数彻底堵死 :它们的体内根本没有原始代码,读无可读。于是"函数体不可读"很自然地滑向了下一句------"那它就没法命名了"。
这一篇讲的就是这句话为什么错,以及错在哪里。
(同前几篇:文中"AI"指执行分析的模型,"我"指设定目标、审结果的人;内容均已脱敏,例子一律用过抽象形态。)
一、AI 在这里踩的坑:"不可"这个词写得太早
AI 的默认推理链是三段式:
读不出函数体 → 提不出体内证据 → 命名不了 → 标"未解"。
前三步都对。问题在第四步的副作用 :一旦被标上"未解/不可命名",这批函数就被冻结 了------后来的每一轮工作都不再回头看它们,仿佛"未解"是一个结论,而不是一次证据缺失。
项目里就吃过这个亏:有一批函数被"不可命名"这句话长久地冻在那里;后来认真数了一遍才发现------其中大多数早就有名字或类型了 ,名字全部来自函数体以外的地方。
"不可读"描述的是证据链的一环断了,不是整条链没了。 在写"不可"之前,先问一句:还有没有别的账?
二、过程:三条绕行路
函数体是证据来源之一,不是唯一。项目里把"函数体之外"的账,收成了三条路(抽象形态如下)。
路一:指针恒等式------"表给的身份"
目标程序里常有一张绑定表 :名字和函数入口成对出现(脚本绑定表、命令表、导出表都属于此类)。
表里写着你叫什么,你就叫什么。 这条身份链不经过函数体一步。
判据也干脆:成对出现是事实;"表里的指针确实指向那个函数"可以单独复核。表定义身份,函数体只是个地址。
路二:调用者证据------"谁在叫你"
函数自己不说话,但调用它的地方在说话:调用点旁边的字符串、角色、行为模式。
命名形态是"语义@调用点 "------名字里就写着它的出身。判据:调用点的语义自洽,且多处调用互相一致。
路三:数据槽与 vtable------"你在哪张表里"
还有一类函数,身份由注册位置给出:它们被登记进事件表、回调表、或某张共享的虚表列里。
槽位本身就是语义------进了哪张表、排在哪一列,就说明了它是哪一类角色。
三条路的共同点一句话:身份来自"函数之外的账" ------表、调用者、注册处。函数体只是证据来源之一。
三、判据与验证:名字必须带"出身"
这一篇真正要立的规矩只有一条,但很硬:
每一个名字,都要标注它的证据来源层。 (其中有一层尤其要说清楚:"不是因为能读到它的函数体"------这句话要写进档案。)
为什么对"出身"这么较真?因为一种叫洗白的风险:
- 不同来源的名字如果混在同一张表里,读者会默认它们证据等级相同;
- 一个其实来自间接证据的名字,挂着"已命名"这个词,就悄悄搭上了强证据的便车------将来没人分得清哪条名字经得起推敲。
来源层不标注,"已命名"就变成一个没有下限的词。
配套的三条实践:
- 分层账本:名字按来源层归档,单一权威,各层各自成册;
- 只撤该层:某一层被推翻时,只撤回那一层,不连坐其他来源的名字(第 13 篇"撤回与断言同罪"的同款纪律);
- 分层带置信度:每一层按各自证据强度给档位(第 14 篇那把尺子)。
四、结论
"函数体不可读 ≠ 函数不可命名"------这句话的真正含义是:
"读"只是证据之一;而"不可"这个词,是 AI 最容易写得太早的一个词。
每一个"不可",都欠一次"还有没有别的账"的检查。
而这次翻案的实际价值也值得记全:翻案之后,那批被冻住的函数没有被继续硬啃------策略被改写成了"去套用已经在其他同类上成功过的三条路" 。这就是"证据分层"真正的用处:它不只是给名字标出身,它还能把下一轮的方向掰到对的地方。
五、边界声明
- 本文只讨论AI 自动化逆向中的判据设计与审核方法,不涉及任何具体产品、厂商或服务的分析结论。
- 文中所有地址、偏移、常量、字段名一律为占位符或示意值 ,
不代表任何真实目标中的取值;示例代码为说明判据而编写,不构成可运行的针对特定目标的工具。 - 文中提到的比例与数字均来自作者项目内的测量记录,仅用于说明方法失效的方式。
- 请勿将本文内容用于未授权的用途。
六、收尾
静态侧的答卷到这里交完。下一篇转到动态侧,讲一个小而漂亮的账本问题:一次布了 60 个观测点------怎么知道丢了几次命中? (提示:答案不是"数一遍",是对账。)
下一篇计划聊:一次布 60 个点:怎么知道丢了几次命中。

转载请注明出处: