Lea*_*ner 4 reverse-engineering cheat-engine
我正在尝试开始学习如何用 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是本地玩家基类,但如果我没有被告知,我怎么知道这一点?这是否也意味着所有游戏变量都在类中?
仍然有点困惑,有人可以解释一下它是如何在视觉上工作的。
1) 假设 ac_client.exe 的图像基址在 0x4000000 - 这是否仅仅意味着进程的开头分配在该内存地址?
是的,但更具体地说,它是映射到内存中的 PE(可移植可执行文件)的基地址。所以在地址基础上,你有 PE 头,然后是很多结构,然后是可执行文件的部分,等等。
2) 接下来是 Image Base + Offset (ac_client.exe + 0x10F4F4) - 偏移量是否意味着它将您从起点带到进程内的某个位置或函数?
从技术上讲,这称为 RVA(相对虚拟地址;它相对于模块的基址):偏移量(适用于磁盘上的平面文件)和 RVA(适用于映射后的文件)之间存在差异在记忆中)。一旦可执行文件被映射到内存中(虽然称为操作系统加载程序),它的“形状”与磁盘上的不同,因此偏移量与 RVA 不同。
要回答您的问题,是的,它指向名为ac_client.exe.
3) 在作弊引擎中,我加载了 Assault Cube。我寻找我的健康价值。我找到了健康的动态地址。现在我需要找到静态地址,因为没有直接指向健康的指针,我点击“查找访问此地址的内容”选项 - 这是否意味着我正在尝试找到一个正在使用或传递我的动态健康的函数多变的?
确切地。
我不熟悉作弊引擎,但这可以通过多种方式完成:
静态:通过反汇编代码并搜索指向感兴趣位置的任何交叉引用。基本上,当代码访问您正在搜索的值时,它通过一些指令来完成,这些指令具有直接(或不很远)指向感兴趣位置的内存操作数。
内存扫描:引擎直接在进程地址空间中搜索指向(或不是很远)感兴趣位置的任何内容。如果它恰好在代码部分中,那么您就有匹配项。否则(例如在数据部分或堆中的其他地方)尝试找到指向这个新位置的任何代码位置。rince 并重复,直到你找到一些东西。
以上的混合。
4) 找到健康值的静态地址后。我找到了 0xF8 的偏移量。还有 ac_client.exe + 0x10F4F4 -> 0x50F4F4 - 人们说 0x50F4F4 是本地播放器基类,但如果我没有被告知,我怎么知道这一点?这是否也意味着所有游戏变量都在类中?
如果游戏是闭源的,您必须对其进行逆向工程以了解游戏的来龙去脉,才能说出这一点。这需要很多时间,很困难,而且您永远不会拥有与原始程序员想要的相同的“名称”。“名称”(类名、函数名、变量名等)不会进入最终的二进制文件:您无法查看类名及其位置。
在某些情况下,您可以恢复这些名称,至少在 C++ 中(例如,当您拥有称为RTTI 的东西时)或者符号信息可用时(游戏开发人员从不提供调试信息,除非在少数情况下)。
在您的情况下(据我所知,该游戏是开源的 C++),您可以通过调试支持为自己编译游戏(从技术上讲,对于 Windows,这意味着通过在链接可执行文件时生成PDB来获得符号支持)。然后将游戏放入符号调试器(例如 Windbg)或反汇编器中,然后询问工具在此精确偏移量/RVA 处的函数/类是什么。当您拥有符号信息时,这真的很简单。
某些语言(例如 C#、Java)可以反编译(!= 反汇编),您可以直接检索所有名称(类、函数、变量等),除非最终的二进制文件受到反编译保护。
这是否也意味着所有游戏变量都在类中?
这是一个相当棘手的问题,会产生很多影响:首先,这取决于所使用的语言。如果它是面向对象的语言,那么可能是的,除了全局、静态和局部变量。有些语言没有类的概念,所以游戏操作的对象的内存布局在 C 游戏和 C++ 游戏之间可能完全不同。
另一个重要的一点是,您可能也没有直接在类中拥有内容,而是由类的成员指向。
假设您有一个游戏,其中玩家有一个库存(因此“玩家”类有一个名为“库存”的变量成员),它可能由某种复杂结构(例如关联容器或什至更多)管理复杂的)。由于这些复杂的结构是由游戏动态分配的(例如c++ 中的 new),因此清单中的所有对象最终都在堆中,而不是直接在类本身中。分配由“库存”成员指向(不一定直接),但库存中的对象在内存中的其他地方。