逆向工程第006篇:简易游戏辅助的实现

前言

从本文开始,我会为大家介绍游戏辅助工具的实现,涉及到逆向以及Windows程序设计等知识。本文所研究的游戏选自于【日】爱甲健二编著的《有趣的二进制》,本文中游戏介绍部分的内容,也是源于该书。

射击游戏规则介绍

 我们首先来看一下本次的示例游戏,运行shooting文件夹中的shooting.exe即可:

这个游戏的规则如下:

       ● 空格键:射击

       ←键:向左移动

       ● →键:向右移动

       ● ↑键:填充能量(以当前得分为上限)

       ● ↓键:时间停止(消费能量)

用左右键移动,用空格键射击,这些操作和一般的射击游戏一模一样。通过按上下键可以使用能够让时间停止的特殊能力。其中↑键用来填充能量,↓键则用来消费能量并让时间停止。能量的上限是当前得分,因此随着游戏的进行,能够填充的能量也会增加。击中敌人可以增加得分,被敌人击中则减少得分。得分越高,敌人越强,子弹的追踪性能也会提高。

大家可以先玩玩看,一般来说能玩到500~1000分,不过,当超过1000分之后,游戏的难度就会大大增加,要想达到2000分可以说是相当困难的。

 

修改内存数据就能得高分

得2000分虽然难,但其实我们只要修改内存中的数据就可以轻松实现了。为了修改内存数据,我们这里要用到编写游戏辅助最常用的一款工具“Cheat Engine” 。在运行游戏的同时,打开“Cheat Engine”,然后从进程列表中选择shooting.exe:

接下来我们尝试让分数“SCORE”发生变化,比如击中对手一次,我们的分数就会变成“29”,此时将29输入“Cheat Engine”中Value下面的输入条内,点击“New Scan”:

可以看到这里找到了1290条结果,但究竟哪个才是我们要找的“SCORE”呢?目前还不好判断,因此我们需要再让分数发生变化,比如再击中对手一次。此时我们的分数变成了58分,回到CE,将刚才的 29修改为58,然后点击“Next Scan”,此时就只剩下一个结果了:

我们可以先记住它的地址(Address),即0x0019FD48,一会编程需要用到。这里我们可以直接通过CE修改分数,也就是双击这个结果,它会显示在CE下方的列表框中,然后双击下面列表框中Value下面的58,在新弹出的对话框中进行修改:

将其修改成2000,点击OK即可。此时回到游戏,我们就可以发现分数已经变成2000了。

 

编写游戏辅助

利用上述方法可以对游戏的内存进行修改,但是每次仅能修改一处数值,并且重启游戏以后,还需要重新将CE与游戏挂载,重新搜索内存数据,这就很不方便了,因此我们这里研究一下如何编写一个简易的游戏辅助,这样每当我们想修改的时候,只要运行游戏辅助就可以了,并且还能按照自己的喜好进行编辑和修改。

本程序在Visual Studio 2013环境中编程实现,使用C++语言。首先启动VS2013,我们新建一个工程文件:

这里我们选择的是Win32控制台应用,注意在创建设置对话框里面,我们选择创建一个空的工程:

创建成功以后,我们为这个工程新增一个cpp文件,在VS窗口的右侧找到Solution Explorer,右键点击Source Files,选择添加一个新的项目:

接下来选择添加cpp文件即可:

cpp文件创建成功以后,就需要编写代码了。对于本程序,修改分数为2000的完整代码如下:

#include <stdio.h>
#include <windows.h>
int main() {
	DWORD Pid;
	HANDLE hProcess = 0;
	DWORD Address = 0x0019FD48;
	DWORD Score = 2000;
	DWORD result;
	HWND hWnd = FindWindow(NULL, L"shooting");
	if (hWnd != 0) {
		GetWindowThreadProcessId(hWnd, &Pid);
		hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid);
		if (hProcess == 0) {
			printf("Open process failed.");
			return 0;
		}
		result = WriteProcessMemory(hProcess, (LPVOID)Address, &Score, 4, 0);
		if (result == 0) {
			printf("Modify failed.");
		} else {
			printf("Modify Success.");
		}
	} else {
		printf("Failed");
	}
	return 0;
}

对于上述程序,有两个地方的数据需要说明一下。首先是调用FindWindow函数获取窗口句柄时,最后一个参数是窗口的名称。当然,我们启动游戏后,是可以在游戏窗口的左上角看到游戏窗口名称叫做“shooting”的。但实际上,为了严谨起见,我们一般是使用一款名为Spy++的工具来获取窗口名称的。该工具已经被集成到了我们的VS开发环境里面,只要选择菜单栏中的TOOLS,就可以找到Spy++了:

我们选择菜单栏中的“Search”,再点击“Find Window”,就会弹出名为“Window Search”的对话框。我们将对话框中的Finder Tool后面的准心拖到游戏窗口里面,这样该工具就能够帮我们识别到窗口的真实标题内容了,即Caption的值:

我们把这个值当作FindWindow函数的最后一个参数即可。

第二个需要说明的地方是程序开始位置的Address值,这个值在程序中是0x0019FD48,也就是我们之前使用CE所发现的用于保存分数的地址。不同版本的游戏的这个值往往是不一样的,因此为了严谨起见,就如同我们刚才获取窗口名称一样,每次都应该使用CE确认一下这个地址到底是多少。

编译通过后运行游戏,再运行本程序,就可以发现分数被修改为2000了。

 

其它有意思的修改

当我们把分数修改为2000以后,可以发现游戏难度呈几何级提升,一方面是对手的子弹有了跟踪的效果,我们很难躲避;另一方面是对手本体在躲避我方的子弹方面更加地智能,我们很难击中对手。针对于这两种情况,我们可以使用一些简单的小技巧来攻克。

首先是对手子弹的跟踪效果。我们这里不妨把自己设置成“无敌”的模式。当然,“无敌”可以考虑通过修改源代码实现,但是换一个角度来看这个问题,对手之所以会击中我们,就是由于绿色子弹的存在,而这个绿色子弹其实就是一个图片文件,位于shooting文件夹,文件名是EShot.png,那么我们不妨将这个文件删掉。再次回到游戏后就能发现,对手只会左右移动,不会发射子弹了,于是“无敌”功能实现。

可现在尽管无敌了,但我们还是很难击中对手,因此不妨使用同样的思维,在我们的黄色子弹上面做文章。使用画图软件对Shot.png进行编辑,比如将其拉伸变宽,然后保存,再进入游戏就能发现我们的子弹宽了很多:

如此一来,即便对方身手再好,也不可能躲避掉我们的子弹了。

发布了122 篇原创文章 · 获赞 672 · 访问量 65万+

猜你喜欢

转载自blog.csdn.net/ioio_jy/article/details/90576720
今日推荐