07-逆向工程
逆向工程论——从二进制还原出设计与机制
逆向工程不是「看汇编」,也不是「照着抄」——它是一套与软件工程平行的工程化流程:从可运行的二进制/程序出发,逐层还原出结构、行为与设计推断。核心是「从机器状态还原人类意图」。这一条线讲:逆向工程是什么(与调试/静态分析的区别)、记什么(对象关系>地址)、怎么证明(证据链)、怎么工程化(三大流程 + 26 步)。
一、逆向工程是什么:从实现反推设计
软件工程与逆向工程是两条方向相反的构造/还原链:
1 | 软件工程:人类意图 → 需求 → 设计 → 实现 → 机器状态(构造) |
逆向工程的核心问题只有一个:
这个东西是怎么做出来的?
输入是已有软件/二进制,输出是:结构、行为、设计推断——原程序的行为模型 + 结构模型 + 数据模型。
例如拿一个 Windows .exe:
1 | EXE |
逆向工程本质上很像:从实现反推设计。
二、逆向 / 调试 / 静态分析:三套平行的工程流程
逆向、调试、静态分析,是和软件工程平行的三套工程化流程:
| 工程 | 核心问题 | 输入 | 输出 |
|---|---|---|---|
| 软件工程 | 怎么把目标做出来? | 需求 | 软件 |
| 逆向工程 | 这个东西是怎么做出来的? | 已有软件/二进制 | 结构、行为、设计推断 |
| 调试工程 | 它为什么在这里出错? | 可运行程序 + 异常现象 | 根因、修复方案 |
| 静态分析工程 | 不运行它,能推断出什么? | 源码/二进制 | 结构、数据流、控制流、缺陷、规则结果 |
它们不是完全独立的流程,而是可以互相嵌套。可以看成三种「观察程序」的方法:
1 | 程序 |
- 静态分析回答:程序里面有什么?(代码 → 结构 → 控制流 → 数据流 → 依赖关系)
- 调试回答:程序现在发生了什么?(运行 → 状态 → 事件 → 异常 → 原因)
- 逆向回答:这个程序实际上是怎么工作的?——它会同时使用静态分析 + 动态分析 + 调试 + 人工推理
逆向工程的范围实际上比静态分析和调试更大。 调试的核心是「通过运行时证据不断缩小故障范围」(现象→证据→定位→假设→验证→根因);静态分析的核心是「把程序转换成适合分析的模型,然后在模型上推理」。逆向则把两者都当作手段。
三、记什么:对象关系 > 地址
逆向里最值钱的不是地址和偏移,而是对象之间的关系,以及怎么证明这个关系存在。
新手找血量:搜一个数值,得到地址 Player+0x10,记下来。几天后版本更新,地址全变。
高手不记地址,记的是:
1 | HP 属于 Player 对象 |
偏移会变,逻辑关系几年不变。 偏移是编译结果(字段顺序/对齐/编译器优化/版本更新/继承都会改变),记语义位置不记数字。
真正要记的是三层文档:
1 | 对象地图(对象树,最重要) Player 有哪些成员、怎么得到 Player |
四、怎么证明:证据链
逆向的每个结论都要有证据链:
1 | 发现 → 证据 → 推测 → 验证 → 结论 |
例子:
1 | 「改几就是几倍攻击力」 |
证据链让逆向结论可检验——不是「我觉得是这样」,而是「有这些证据支持,且验证过」。
五、怎么工程化:逆向工程流程与 26 步
逆向工程可以建立成类似软件工程的细化流程:
1 | 目标确定 → 样本获取 → 环境识别 → 文件/程序识别 → 程序结构分析 |
逆向的主干是逐层还原:
1 | 观察 → 数据 → 地址 → 对象 → 状态 → 指令 → 函数 |
每一步都有明确的输入/输出/判定/失败回退——把「从机器状态还原人类意图」变成可复现的工程。逆向工程产出五类资产:知识资产、关系资产、行为资产、操作资产、验证资产。
统一的工程单元:
1 | 输入 → 操作 → 证据/输出 → 判断 → 下一阶段 |
六、与「复刻软件」的区别
逆向工程经常和「复刻软件」混在一起,但它们是两条不同的线:
1 | 逆向工程(本线): |
关键区分:复刻软件是「产品层面的逆向设计、重新实现」(不碰二进制);逆向工程是「二进制层面的机制还原」(必须碰二进制)。 复刻软件用黑盒观察成品行为反推设计;逆向工程用灰盒/白盒手段从二进制还原机制。
七、收束
1 | 逆向工程 = 从机器状态还原人类意图(与软件工程方向相反) |
逆向工程不是「看汇编」,而是一套知识生产工程——从机器状态逐层还原人类意图,每个结论有证据链,最终沉淀成可复用的资产。
