4

我正在尝试开始学习如何用 C++ 编写游戏秘籍。但目前我想了解内存的布局等 - 我有几个问题要问,并将使用游戏Assault Cube作为参考。请帮助我并以简单的形式解释任何事情。我是新的。

1)假设图像基地址ac_client.exe位于0x4000000- 这是否仅仅意味着进程的开头分配在该内存地址?

2) 接下来是 Image Base + Offset ( &ac_client.exe + 0x10F4F4) - 偏移是否意味着它将您从起点带到流程内的某个位置或功能?

3) 在作弊引擎中,我加载了 Assault Cube。我寻找我的健康价值。我找到了健康的动态地址。现在我需要找到静态地址,因为没有直接指向健康的指针,我点击“查找访问此地址的内容”选项 - 这是否意味着我正在尝试查找正在使用或传递我的动态健康的函数多变的?

4)找到健康值的静态地址后。我找到了偏移量0xF8。另外ac_client.exe + 0x10F4F4-> 0x50F4F4-人们说这0x50F4F4是本地播放器基类,但是如果我没有被告知,我怎么知道呢?这是否也意味着所有游戏变量都在类中?

仍然有点困惑,有人可以解释这一切是如何在视觉上工作的。

4

1 回答 1

8

1) 假设 ac_client.exe 的映像基址位于 0x4000000 - 这是否仅仅意味着进程的开头分配在该内存地址?

是的,但更具体地说,它是一旦映射到内存中的 PE(可移植可执行文件)的基地址。所以在地址基础上,你有 PE 头,然后是很多结构,然后是可执行文件的部分,等等。

2) 接下来是 Image Base + Offset (ac_client.exe + 0x10F4F4) - 偏移是否意味着它将您从起点带到进程内的某个位置或函数?

从技术上讲,这称为 RVA(相对虚拟地址;它相对于模块的基地址):偏移量(适用于磁盘上的平面文件)和 RVA(适用于映射后的文件)之间存在差异在记忆中)。一旦可执行文件被映射到内存中(尽管称为 OS 加载程序),它的“形状”就与磁盘上的不同,因此偏移量与 RVA 不同。

要回答您的问题,是的,它指向名为ac_client.exe.

3) 在作弊引擎中,我加载了 Assault Cube。我寻找我的健康价值。我找到了健康的动态地址。现在我需要找到静态地址,因为没有直接指向健康的指针,所以我点击“查找访问此地址的内容”选项 - 这是否意味着我正在尝试查找正在使用或传递我的动态健康的函数多变的?

确切地。

我不熟悉作弊引擎,但这可以通过多种方式完成:

  1. 静态:通过反汇编代码并搜索任何指向感兴趣位置的交叉引用。基本上,当代码访问您正在搜索的值时,它会通过一些指令来完成,这些指令有一个内存操作数直接(或不是很远)指向感兴趣的位置。

  2. 内存扫描:引擎直接在进程地址空间中搜索指向(或不是很远)感兴趣位置的任何内容。如果它恰好在代码部分中,则您有匹配项。否则(例如在数据部分或堆中的其他地方)尝试找到指向这个新位置的任何代码位置。重复并重复,直到你找到一些东西。

  3. 以上混合。

4)找到健康值的静态地址后。我找到了0xF8的偏移量。还有 ac_client.exe + 0x10F4F4 -> 0x50F4F4 - 人们说 0x50F4F4 是本地播放器基类,但如果我没有被告知,我怎么知道呢?这是否也意味着所有游戏变量都在类中?

如果游戏是封闭源代码,您必须对其进行逆向工程以了解游戏的来龙去脉才能说出这一点。这需要很多时间,很困难,而且你永远不会拥有与最初程序员想要的相同的“名字”。“名称”(类名、函数名、变量名等)不会出现在最终的二进制文件中:您失去了查看类名及其位置的能力。

仍然有一些情况下您可以恢复这些名称,至少在 C++ 中(例如,当您有一些称为RTTI的东西时)或者如果符号信息可用(游戏开发人员从不提供调试信息,除非在少数情况下)。

在您的情况下(据我所知,该游戏是开源的并且使用 C++),您可以通过调试支持为自己编译游戏(从技术上讲,对于 Windows,这意味着通过在链接可执行文件时生成PDB来进行符号支持)。然后将游戏放入符号调试器(例如 Windbg)或反汇编器中,然后询问工具在此精确偏移量/RVA 处的函数/类是什么。当你有符号信息时,它真的很简单。

某些语言(例如 C#、Java)可以反编译(!= 反汇编),并且您可以直接检索所有名称(类、函数、变量等),除非最终的二进制文件受到反编译保护。

这是否也意味着所有游戏变量都在类中?

这是一个相当棘手的问题,具有很多影响:首先,它取决于所使用的语言。如果它是一种面向对象语言,那么可能是的,除了全局、静态和局部变量。有些语言没有类的概念,因此游戏操作的对象的内存布局可能在 C 游戏和 C++ 游戏之间完全不同。

另一个重要的一点是,您也可能没有直接在类中的内容,而是由类的成员指向的。

假设您有一个游戏,其中玩家有一个库存(因此类“玩家”有一个名为“库存”的变量成员),它可能由某种复杂的结构(例如关联容器甚至更多的东西)管理复杂的)。由于这些复杂的结构是由游戏动态分配的(例如c++ 中的新结构),库存中的所有对象最终都在堆上,但不直接在类本身中。“库存”成员(不一定直接)指向分配,但库存中的对象位于内存中的其他位置。

于 2019-09-27T01:57:31.310 回答