自动查找当前生命值和最大生命值¶
在第十九页「搜索汇编模式」和第二十一页「搜索字符串」中,我展示了一些 Cheat Engine Lua 脚本并解释了它们的工作原理。使用这些示例中的 findString() 函数,你可以让 Cheat Engine 自动定位我们刚才在 OllyDbg 中手动找到的格式字符串的地址。接下来,你可以编写一个小函数,在字节 0x68(PUSH 命令的字节,正如你在图 5-3 中 0x401030 旁边看到的)之后扫描这个地址,定位把它压入栈的代码地址。然后,你可以从 pushAddress - 5 和 pushAddress - 12 读取 4 字节,分别定位 currentHealth 和 maxHealth。
这看起来可能没什么用,因为我们已经找到了地址,但如果这是一款真实游戏,这些地址会在发布更新时改变。用这些知识自动化查找它们会非常有帮助。如果你愿意接受挑战,试试看吧!
由于持续的 bug 修复、内容改进和功能添加,网络游戏是进化最快的软件类型之一。有些游戏每周发布一次更新,游戏黑客经常花大部分时间逆向新的二进制,以便相应地更新他们的机器人。
如果你创建高级机器人,它们会越来越多地建立在内存地址的基础上。更新到来时,为大量值和函数确定新地址是你将面对的最耗时的必然事件。依靠「赢得更新竞赛的技巧」可能非常有益,但这些技巧不会帮你定位更新后的地址。你可以用 Cheat Engine 脚本自动定位一些地址,但这并不总是有效。有时你必须亲自动手做脏活。
如果你想重新发明轮子,用最初的方式找到这些地址,那是在浪费时间。不过,你实际上有一个巨大优势:旧二进制和地址本身。利用这两样东西,可以在原来一小部分时间内找到每一个需要更新的地址。
右边是以前的版本。我从一款真实游戏(不便透露名称)中截取了这张图,给你一个真实示例。

我的机器人修改了 0x047B542 处的代码(右侧),我需要在新的版本中找到对应的代码,最终在 0x047B672(左侧)发现了它。这个函数调用在收到数据包时调用数据包解析函数。为了最初找到这个地址(「最初」指约 100 次更新之前),我弄清了游戏网络协议的工作原理,在许多网络相关 API 调用上设置断点,单步执行,检查栈上的数据,直到根据我对协议的理解找到看起来类似的东西。
赢在饱和市场中,成为第一个发布稳定更新的机器人开发
得者对成功至关重要。竞赛在游戏更新的那一刻开始,决
更心成为最快的黑客会花数百小时准备。以下是最常见的
新保持领先的方法:
竞
赛
的
技
巧
(cid:127)创建更新警报:通过编写软件在游戏补丁发布时提醒你,你
可以尽快开始更新工作。
(cid:127)自动化机器人安装:游戏经常在在线玩家最少的时间安排预
期更新。机器人用户讨厌醒来后先下载新软件再开始挂机,但他们喜欢醒来发现它已在游戏修补时静默安装。
(cid:127)使用更少的地址:需要更新的越少越好。把相关数据合并到
结构中,消除不必要的内存地址使用,可以节省大量时间。
(cid:127)拥有出色的测试用例:数据会变化,黑客会犯错。能够快速
测试每个功能,是稳定机器人和随机崩溃、让用户丧命甚至导致角色被封禁的机器人之间的区别。
用这些做法应对更新会让你有相当大的领先优势,但它们可能并不总是足以让你获胜。最重要的是,尽量深入理解逆向工程,并利用这种理解为你服务。
我本可以在那之后对 100 多次更新都重复同样的步骤,但没有必要。代码多年来保持相对不变,这让我可以用旧代码的模式在新代码中找到那个函数调用的地址。
现在,考虑这段汇编代码:
PUSH EDI
PUSH EAX
LEA EAX,DWORD PTR SS:[EBP-C]
MOV DWORD PTR FS:[0],EAX
MOV DWORD PTR SS:[EBP-10],ESP
MOV DWORD PTR SS:[EBP-220],-1
MOV DWORD PTR SS:[EBP-4],0
看起来眼熟吗?把它与图 5-4 比较,你会看到这段代码正好存在于两个版本游戏中被高亮函数调用的上方。无论它做什么,操作组合看起来都相当独特;因为代码使用了大量相对于 EBP 的不同偏移量,二进制中其他任何地方都不太可能存在相同的一段代码。
每次我不得不更新这个地址时,我都会在 OllyDbg 中打开旧二进制,高亮这段操作,右键单击,选择「Asm2Clipboard→ 复制固定汇编到剪贴板」。然后,我在 OllyDbg 中打开新二进制,导航到 CPU 窗口,按 ctrl-S,粘贴汇编代码,点击「查找」。十次中有九次半,这会把我直接带到新版本中需要找到的函数调用上方。
更新到来时,你可以用同样的方法找到几乎所有已知地址。它应该适用于你能在汇编代码中轻松找到的每个地址。不过有几个注意事项:
(cid:127)OllyDbg 把搜索限制为八个操作,所以你必须找到这个大小
或更小的代码标记。
(cid:127)你使用的操作不能包含任何其他地址,因为这些地址很可能
已经改变。
(cid:127)如果游戏中使用你要找地址的部分发生了变化,代码可能不
同。
(cid:127)如果游戏更换编译器或切换优化设置,几乎所有的代码都会
完全不同。
正如第一百零二页「自动查找当前生命值和最大生命值」所讨论的,编写为你完成这些任务的脚本会带来好处。认真的游戏黑客非常努力地自动定位尽可能多的地址,一些最好的机器人被设计为每次都在运行时自动检测它们的地址。最初可能需要大量工作,但投入绝对会有回报。