8、寻找游戏基址:什么是基址、为什么需要基址、使用 Cheat Engine 的“找出是什么改写了这个地址”功能、动态地址与静态地址

好,咱们进入第八章。这一章可以说是整个逆向工程的基石——基址。

你可能已经遇到过这种情况:用 Cheat Engine 搜到了血量地址,改得很爽。但游戏一重启,地址变了,血量的值也找不到了。是不是很崩溃?

嗯,这就是动态地址在搞鬼。而基址,就是解决这个问题的钥匙。

什么是基址?

说白了,基址就是一个不会变的地址。它由程序加载时由操作系统分配,但一旦分配好,在整个游戏运行期间都保持不变。

我习惯把基址比作「房子的地基」。你装修房子(修改数据),墙可以拆、门可以换,但地基不动。基址就是那个地基。

举个例子:

静态地址(基址):0x004A1F2C  → 每次启动都不变
动态地址:0x0A3F4B20        → 每次启动都可能变

在 Cheat Engine 里,基址通常显示为绿色。绿色的地址,就是静态地址。

为什么需要基址?

我刚开始做逆向时,觉得动态地址也能用啊,改完就完事了。直到有一次,我写了一个自动修改脚本,结果游戏更新后所有地址全废了。那叫一个惨。

基址的核心价值在于:

  • 持久性:游戏重启后,基址依然有效
  • 通用性:同一版本的游戏,基址在不同电脑上相同
  • 稳定性:基址不会因为游戏场景切换而改变
  • 可移植性:写 CT 文件或修改器时,只需要基址+偏移量

核心原则:所有动态地址,最终都能通过「基址 + 偏移量」的方式找到。这是逆向工程的黄金法则。

动态地址与静态地址

这两个概念必须分清楚。我见过不少新手在这上面栽跟头。

特性 静态地址(基址) 动态地址
稳定性 每次启动不变 每次启动可能变
颜色(CE中) 绿色 黑色
存储位置 代码段(.text)或数据段(.data) 堆(heap)或栈(stack)
修改方式 直接修改 需通过指针访问
适用场景 全局变量、常量 临时变量、动态分配的对象

为什么会这样?因为游戏引擎为了管理内存,会把大部分数据动态分配。比如你的血量,每次进游戏可能分配在不同的堆地址上。但指向这个堆地址的指针,往往存储在静态区。

说白了,我们要找的基址,就是那个「指向动态地址的静态指针」。

使用 Cheat Engine 的“找出是什么改写了这个地址”功能

这是 CE 最强大的功能之一。我个人觉得,学会这个功能,逆向水平直接上一个台阶。

操作步骤:

  1. 先找到你要修改的数据的动态地址(比如血量)
  2. 右键该地址 → 选择「找出是什么改写了这个地址」
  3. CE 会开始监控这个地址的写入操作
  4. 回到游戏,让血量发生变化(比如挨打、吃药)
  5. CE 会捕获到一条汇编指令,例如:mov [eax+0C], edx
  6. 这条指令就是修改血量的代码

小技巧:捕获到的指令中,[eax+0C] 这种形式就是「基址+偏移量」的雏形。eax 里存的就是基址,0C 就是偏移量。

我曾经遇到过一个坑:游戏用了多线程,血量被多个线程同时修改。CE 捕获到的指令有十几条。这时候不要慌,一条一条看,找到真正写入数值的那条。通常带有 movadd 指令的就是。

从动态地址到基址的完整流程

咱们用一张图来理清整个逻辑:

从动态地址到基址的逆向流程 步骤1 扫描找到动态地址 步骤2 找出改写指令 步骤3 分析汇编指令 指令中是否包含基址? (如 mov [eax+0C], edx) 是(有基址) 步骤4 追踪基址来源(指针扫描) 步骤4 继续向上追踪指针链 ✅ 找到基址(绿色地址)

这张图展示了完整的逆向流程。你想想看,从动态地址出发,一步步向上追踪,最终找到那个绿色的基址。这个过程就像剥洋葱,一层一层剥开。

实战:用 CE 追踪基址

咱们用一个经典例子来演示。假设你要找「玩家血量」的基址。

第一步:找到动态地址

扫描血量数值,找到当前地址。假设是 0x0A3F4B20

第二步:找出改写

右键 → 「找出是什么改写了这个地址」。挨打一下,CE 捕获到:

mov [eax+0C], edx

第三步:查看 eax 的值

在 CE 的寄存器面板里,看到 eax = 0x0A3F4B14。注意,这个值也是动态的。

第四步:找出 eax 的来源

右键 eax 的地址 → 「找出是什么改写了这个地址」。重复这个过程。

最终,你会找到一个绿色的地址,比如 0x004A1F2C。这就是基址。

注意:指针链可能很长,有的游戏有 5-6 层甚至更多。我曾经追踪过一个网游的坐标,指针链长达 8 层。耐心是关键。

指针扫描:批量找基址

手动追踪太慢?CE 提供了「指针扫描」功能。我个人习惯先用指针扫描扫一遍,再手动验证。

操作步骤:

  1. 找到动态地址后,右键 → 「指针扫描」
  2. 设置扫描参数(偏移量、层级深度等)
  3. 重启游戏,重新找到动态地址
  4. 再次指针扫描,对比两次结果
  5. 两次都出现的地址,就是基址

避坑指南:指针扫描结果中,绿色地址不一定都是基址。有些是模块基址(如 game.exe+0x1234),这种也是有效的。我一般优先选择带模块名的地址,因为它们更稳定。

基址的表示方式

在 CE 中,基址通常有两种表示方式:

方式一:绝对地址
0x004A1F2C

方式二:模块名+偏移
game.exe+0x1F2C

我个人更推荐第二种。因为如果游戏更新,模块基址可能会变,但偏移量通常不变。你只需要更新模块基址即可。

举个例子:

// 旧版本
game.exe+0x1F2C  → 实际地址 0x004A1F2C

// 新版本(模块基址变了)
game.exe+0x1F2C  → 实际地址 0x005B3F2C

看到了吗?偏移量 0x1F2C 没变,变的只是模块基址。这就是为什么 CT 文件里通常用「模块名+偏移」来保存地址。

总结

基址是逆向工程的基石。没有基址,你写的修改器就是一次性用品。有了基址,你才能做出真正可用的工具。

记住几个关键点:

  • 绿色地址 = 静态地址 = 基址
  • 黑色地址 = 动态地址 = 需要通过指针访问
  • 「找出是什么改写了这个地址」是找基址的核心功能
  • 指针扫描可以批量找基址,但需要手动验证
  • 模块名+偏移 的表示方式更稳定

嗯,这一章的内容就到这。基址的概念不难,但需要多练。找个游戏,自己动手走一遍流程,比看十遍教程都管用。


公众号:蓝海资料掘金营,微信deep3321