如何定位动态指令?

逆向工程 拆卸 部件 dll 动态链接 抵消
2021-06-27 12:19:11

我正在尝试进行游戏破解,并且需要一些说明来获取地址nop但是,当查看 Cheat Engine 中的指令时,它们没有与任何模块(DLL 或基础 exe)的静态偏移量。我不知道如何找到动态指令。任何帮助都会非常好。

3个回答

作为一个狂热的作弊引擎用户和游戏黑客,我可以向您介绍一个具体的例子,它应该能让您清晰明了。

首先,我们将使用这段任意的代码来处理:

7A1A7A162 - 55                    - push rbp
7A1A7A163 - 00 6E 00              - add [rsi+00],ch
7A1A7A166 - 69 00 74000000        - imul eax,[rax],00000074 { 116 }
7A1A7A16C - 00 00                 - add [rax],al
7A1A7A16E - 00 00                 - add [rax],al
7A1A7A170 - EB C3                 - jmp 7A1A7A135
7A1A7A172 - C3                    - ret 

假设您想要 nop 的两个字节是EB C3,但7A1A7A170不是静态地址。您现在要做的是构建一个独特的字节签名,然后您可以对其进行扫描。你在这里打赌的是,虽然内存地址可能会改变,但指令保持不变。这为您提供了一致的扫描内容。最终,您只需要扫描的一个结果,这样您就不会发现——然后修改——误报。

在 Cheat Engine 中,与签名扫描相关的所有内容都称为 AOB(字节数组)扫描。本质上是一回事。让我们使用上面示例例程中的字节构建我们希望的唯一 AOB:

55 00 6E 00 69 00 74 00 00 00 00 00 00 00 EB C3 C3

现在你可以在 Cheat Engine 中做的是从Value Type下拉框中选择“Array of byte” ,然后确保Writeable复选框有实心黑色方块选择(即,不仅仅是一个复选标记而不是空的)意味着 CE 将扫描读/写内存,最后将这些字节粘贴到搜索框中并进行搜索。

如果您只有一个结果,那么您就可以开始了。您的扫描将返回第一个内存地址(无论它是什么),然后您可以根据该结果的偏移量进行注入,即0x0E. 作弊引擎(或您用来扫描该字节模式的任何东西)从内存 address 开始找到结果7A1A7A162,然后从那里开始,您的字节0x0E在 address 处7A1A7A170

如果您有多个结果,那么您需要开始做的是在签名的开头或结尾添加字节。使用我们的示例,这意味着开始合并来自 之前7A1A7A162和/或之后的指令的字节7A1A7A172

是的,有时您最终会遇到大量 AOB——尤其是在您处理反作弊软件的情况下,这些软件会复制某些代码块以关闭模式扫描。在这些情况下,您可以尝试在附近查找与要修改的字节无关的字节数组,然后根据扫描结果的偏移量进行注入。

例如,也许有一个来自7A1A70000to的唯一字节签名7A1A7001C,然后您可以引用结果扫描(这将是7A1A70000)+ 的偏移量A170使您到达7A1A7A170这有时也不起作用,例如在运行时编译游戏指令时(这在基于 Java 的游戏中很常见——Minecraft 就是这样的游戏;查看JIT 编译),但这是一个很好的例子来展示您如何绕过常见的反模式扫描技术。

随意询问您是否需要对此进行额外说明,但最终目标是找到一个您可以扫描的唯一字节签名,然后以此为基础进行注入。这允许您独立于内存地址工作。=)

如果他们没有符号,您可以使用签名扫描。

签名扫描

如果您的程序以任何方式使用此代码,则此位置必须存储在某个地方以供二进制文件的“静态”部分使用。所以通常你想要做的是找到指向目标代码的指针链。您可以通过反转二进制地址或从目标开始的盲目内存搜索地址来找到这样的链。