【干货】C++游戏外挂开发教程18:游戏特征码查找

文摘   社会   2025-01-11 00:00   广西  


欢迎来到C++游戏外挂开发系列教程! 

游戏外挂开发是一个既有挑战性又充满乐趣的领域,它让我们有机会深入探索计算机程序设计和系统底层原理。本教程将带领你从零开始,逐步学习如何使用C++编程语言开发游戏外挂,包括各种常见游戏中的作弊功能,如自动射击、透视功能、无敌模式等。通过本系列教程,你将了解到游戏外挂的基本原理、常见开发工具、技术挑战和实际应用技巧,为你打造成一名优秀的游戏外挂开发者提供全面的指导。

本期我们来讲一下特征码的查找,这个东西。之前我们提到过这些坐标,就是游戏中的内存坐标,指的是某段地址的赋值字段。我们通过查找这段汇编代码,得到它的赋值方式,然后观察寄存器,得到了它的内存地址。在某些情况下,代码的地址是不变的,这样就方便我们获取。但如果地址变了怎么办?有些游戏的框架是随机加载的,这时我们需要分析这种变化的模块。
我们打开游戏,点击开始,然后搜索这个进程。观察体力值,比如100,我们可以推测它是用一个字节存储的。然后我们进行一些操作,比如翻跟头,观察值是否变化,然后继续寻找变动的数字。通过这种方式,我们可以确定某些地址,并观察到它们的变化。最后,我们可以查看汇编代码,观察赋值和变化的情况,以便进行修改和调试。
现在我们运行游戏,体力值肯定是80了,对吧,很好运。每次翻跟头,它都会变成80,这样可以判断出来e d i代表当前的体力值,单纯的体力值。但在网上一番搜索后,我们发现了这个ex加0x60的代码与某些地方有点耦合。我们可以猜测,这个可能是生命值。然而,我们需要注意的是,这个地址可能会变化。通常来说,一个程序的代码地址是不会变的,但这个游戏不是win 32程序,而是基于.NET框架的。因此,我们需要考虑使用特征码来进行查找。特征码是根据代码逻辑而不是地址来确定的,因此即使地址变化了,代码逻辑也不会变。所以,即使地址会变,特征码也是有效的。

那么我来问一下,汇编代码的特征是不会变的,这是我们三个杀毒软件经常做的事情,查特征码。如果你的代码特征和某个病毒的代码耦合,那么杀毒软件就会判断你是病毒,通过这个来判断。这个特征码是不会变的,好了,我们可以得出一个结论,我们可以通过扫描这个特征码来匹配,怎么匹配呢?

想想看,文件上的硬编码,文件是一个PE格式的文件,它的PE格式会加载到内存中,加载程序会加载到内存中。前提是这个程序没有加壳的话,杀软可以直接静态反编译。但有些程序为什么一放到电脑上就被杀了?他们没有加壳,杀软直接拿到了他们的代码。但是有一个问题,有的程序一放到电脑上没事,一打开就被杀了,为什么?因为它们的代码地址会变,但是它们的逻辑不会变。这是因为它们的代码地址会变,但是它们的逻辑不会变,因此通过特征码来匹配是有效的。

内存的一些基础知识,我们来简单介绍一下。内存就像一条线,从0一直乘到2G的用户层空间,也就是虚拟内存空间。每个内存都有一个地址,程序一般从0x4410开始,一直走到0x20x7 f f f f。这是内存的大致结构。每一段内存其实都是一段一段的下标,对应着不同的内存地址。但在实际分配内存时,并不是连续的,可能会有一些空的块,即没有提交的内存。

些红色的地方是已经被使用的,而白色的地方是未使用的。在读取内存时,我们一般会以4096字节为单位进行读取,因为Windows内存页是4096字节对齐的,这样可以提高运行速度。内存中的执行代码、存放变量等属性会影响我们读取的效率。我们可以先预判程序的代码空间大概在哪里,然后逐一取出内存块来进行处理。

我们先从200个内存块中判断哪些是可执行的。假设我们找到了160个可执行的内存块,这样就提高了查找效率。接下来,我们只需针对这160个内存块进行读取,只需进行160次读取。然后,我们使用拿到的特征码,从0x41000开始匹配内存段,找到可读可写可执行的区段。演示的过程中,我们发现了240个内存块,然后找到了匹配的地址。
这样,我们就通过内存块的匹配找到了我们需要的内存段,提高了效率。内存的属性有可读可写可执行,只读区段等。内存断点的原理是改变内存的属性,使得执行到相应区段时引发异常,然后由OD接管处理,从而实现程序断点的调试功能。在查找内存时,我们主要使用几种内存区段,如可读可写可执行等,可以根据需要调整区段属性。

变量的数据通常存储在可读区域,允许读写的数据一般在这个区域内。接下来,我们从200个内存块中过滤掉白色的区域,即不需要的区域。然后,将匹配内存属性的内存块加入到内存地址块中,并保存其起始地址和大小。内存区段的属性不需要改变,因为我们要查找的区段通常是可读可写可执行的。查找完毕后,我们进行一些后续处理,将特征码长度复制到保存区域中,然后开始查找。查找过程中,根据内存块数量开启相应数量的线程,将每个内存块的起始地址和大小传递到读取内存的线程中。

接着,从目标进程中读取内存块的数据,存储到临时缓存中,缓存的大小与内存块大小相同。读取完毕后,我们开始匹配特征码,这个匹配过程可能使用模糊匹配算法。匹配成功后,将查询到的内存地址存储到数组中,以便进一步处理。整个过程基本上按照这个模型进行,特征码的查找算法尽量不要改动,因为改动可能会导致不必要的问题。代码区域是可读可执行的,所以我们要找的就是可读可执行的地方。之前已经写过设置进程的部分,代码会提供给你们,你们可以自行封装。

今后的教程将重点讲解原理,而代码部分则留给你们自行分析。当然,我的代码支持64位程序,这意味着它适用于64位系统。当你需要读取64位程序时,只需将编译模式改为x64即可,因为这些代码完全支持64位系统。不存在无法读取的情况。64位程序的内存区段通常更大,可能会从0x40000000到0x7fffffff,所以在处理这些地址时,要用八字节的内存地址。
本期的教程就到这里,有没有什么问题?有问题欢迎给公众号留言,有疑难一定解答。当你查找到所需的内存块后,就可以使用吸尘器和钩子的方式来获取数据。至于线程池,我们会根据需要开启多个线程来查找内存,这样即使有一些线程执行完毕,其他线程仍然在运行,不会导致速度变慢。在游戏中,我们可能需要一些功能,比如自动接任务、自动跑路、自动交任务等。实现这些功能有两种方法,一种是使用鼠标点击,另一种是在鼠标屏幕上晃动,并在特定形状出现时进行点击。



暮色的狐
这是一只高强度上网冲浪、高质量输出内容的狐狸。主打ACGN杂谈、技术干货分享、第九艺术鉴赏、网梗百科解析、情感树洞鸡汤、正能量价值观~
 最新文章