[安全攻防进阶篇] 三.OllyDbg和Cheat Engine工具逆向分析植物大战僵尸游戏

从2019年7月开始,我来到了一个陌生的专业——网络空间安全。初入安全领域,是非常痛苦和难受的,要学的东西太多、涉及面太广,但好在自己通过分享100篇“网络安全自学”系列文章,艰难前行着。感恩这一年相识、相知、相趣的安全大佬和朋友们,如果写得不好或不足之处,还请大家海涵!

    推荐前文:

声明:本人坚决反对利用教学方法进行犯罪的行为,一切犯罪行为必将受到严惩,绿色网络需要我们共同维护,更推荐大家了解它们背后的原理,更好地进行防护。(参考文献见后)

前文回顾:



一.VS内存地址查看

在讲解OllyDbg和Cheat Engine工具逆向分析游戏之前,我想先给大家普及下内存地址的基础概念,以及通过创建项目来讲解下内存、地址、值它们的关系。

第一步,打开VS2019创建空项目“RE_ZWDZJS01”,然后添加main.cpp源文件。

如下图所示,选中项目右键“添加”->“新建项”,然后创建main.cpp文件。


第二步,添加代码如下所示,我们尝试在内存中查看变量的位置。 其中%#表示输出提示方式,如果是8进制在前面加0,如果是十进制不加任何字符,如果是十六进制会加上0x。

#include "stdio.h"

int main()
{
          
   
	int x = 1000;

	//内存中查看值得位置
	printf("%#X
", &x);

	//暂停
	getchar();
	return 0;
}

我们尝试添加个断点,然后运行程序。


第三步,按下F5调试,输出结果为0x12FFCDC。

    0x12FFCDC

第四步,接着我们需要在内存中查看这个值,选择“调试”->“窗口”->“内存”,然后随便选择一个“内存”。

输入地址“0x12FFCDC”即可。

接着我们打开程序员型计算机,可以看到1000对应的十六进制就是3E8,刚好和上面的 E8 03 00 00 一致。

    E8 03 00 00

注意这里仅显示了一个字节,我们如果右键选中转换为4字节,则可以显示完整的数值,如下图所示。

    0x000003e8

写到这里,VS简单查看内存的方法就介绍完毕了,其原理类比为:

    内存 --> 旅馆 地址 --> 门牌号 值 --> 旅客A

那么,我们怎么将“旅客A”换成“旅客B”呢?这就需要通过门牌号在旅馆中找到“旅客A”再替换,但之前需要进行权限提升,才能进行后续的操作。同样,在游戏中,如果我们想在内存中修改值,也是通过地址访问这个值再进行修改,修改前也需要提升权限。具体操作主要包括四个步骤:

    第一步,找到游戏窗口 第二步,通过窗口找到进程ID 第三步,通过进程ID打开进程 第四步,通过打开的进程完成内容修改

讲解完这个基础知识,接着我们开始植物大战僵尸的逆向吧!



二.Cheat Engine逆向修改阳光值

修改阳光值其实就是修改游戏的分数、能量、血量、攻击力之类的,其原理是通过地址修改内存中的值,这里主要使用的是Cheat Engine工具。


第一步,通过Cheat Engine工具打开运行着的植物大战僵尸游戏。


第二步,输入数字“100”,点击“首次扫描”。

返回结果为762个。


第三步,接着反复玩游戏,并输入对应的数字进行“再次扫描”,比如输入数字“150”,点击“再次扫描”。

最终我们得到了一个结果,其地址为:

    0x207FB5A0

第四步,打开任务管理器,然后选中植物大战僵尸游戏,右键选择“转到详细信息”按钮。

显示结果如下图所示,这里获取了植物大战僵尸的进程ID。

    PID:3256

原理搞懂之后,接下来就需要编写代码完成阳光值的修改。


第五步,在编写C语言代码修改阳关的参数前,先讲解Spy++的查找窗口功能和FindWindow函数。 我们在VS中可以看到查找窗口函数FindWindow包括两个参数,即窗口的类型和窗口的标题。

FindWindow(
  lpClassName,        {
          
   窗口的类名}
  lpWindowName: PChar {
          
   窗口的标题}
);

这里我们可以通过Spy++来进行辅助讲解。

在弹出的界面中选择这个查找窗口(从左数第五个)按钮。

然后移动选择游戏窗口,查看对应的信息,它包括窗口句柄,如下图所示。所以接下来我们可以通过标题和类进行查找。

    标题:植物大战僵尸中文版 类:MainWindow

第六步,编写核心C语言代码,实现相关游戏修改功能。

通过GetWindowThreadProcessld函数找到进程ID。

DWORD GetWindowThreadProcessld(
	HWND hwnd,                   //窗口句柄
	LPDWORD lpdwProcessld        //接收进程标识的32位值的地址
);

通过OpenProcess函数打开一个已存在的进程对象,并返回进程的句柄。

HANDLE OpenProcess(
	DWORD dwDesiredAccess,   //渴望得到的访问权限(标志)
	BOOL bInheritHandle,     //是否继承句柄
	DWORD dwProcessId        //进程标示符
);

通过WriteProcessMemory函数写入某一进程的内存区域。注意,直接写入会出Access Violation错误,故需此函数入口区必须可以访问,否则操作将失败。

BOOL WriteProcessMemory(
	HANDLE hProcess,                 //由OpenProcess返回的进程句柄
	LPVOID lpBaseAddress,            //要写的内存首地址
	LPVOID lpBuffer,                 //指向要写的数据的指针
	DWORD nSize,                     //要写入的字节数
	LPDWORD lpNumberOfBytesWritten
);

完整代码如下:

#include "stdio.h"
#include "windows.h"

int main()
{
          
   
	//输入值作为修改阳光参数
	int x;
	scanf("%d", &x);

	//进程ID
	DWORD pid;

	//1.找到游戏窗口 窗口类型、窗口标题
	HWND hwnd = FindWindow(NULL,L"植物大战僵尸中文版");

	//2.通过窗口找到进程ID
	GetWindowThreadProcessId(hwnd,&pid);

	//3.通过进程ip打开进程
	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);

	//4.通过打开进程修改游戏内容
	WriteProcessMemory(hProcess, (LPVOID)0x207FB5A0, 
		               (LPVOID)&x,sizeof(x),&pid);

	return 0;
}

第七步,当我们进行数值修改时,我们的植物大战僵尸阳光也就行对应的修改。 先设置为“0”,如下图所示修改成功,哈哈!是不是完成了一个简单的游戏辅助器呢?

接着我们修改成10086,如果360提示警告(识别远程线程注入),我们点击“允许本次修改”即可,最终成功将阳光值修改为“10086”。我们终于可以愉快的玩耍了,妈妈再也不用担心我的阳光!

同样第二关我们也可以进行修改,但此时的窗口地址会有变化,它变为了0x2099AE60,修改核心函数:

    WriteProcessMemory(hProcess, (LPVOID)0x2099AE60, (LPVOID)&x,sizeof(x),&pid);

注意,如果游戏存在地址保护的情况,我们可以尝试注入进行修改。本系列文章仅分析经典的本地游戏,至于网络游戏一律禁止大家去修改或破坏,原理普及安全防护为主。


第八步,编程中遇到的错误一定要学会独立百度、谷歌解决,这是至关重要的一种能力提升。 注意,如果提示错误“error C4996: ‘scanf’: This function or variable may be unsafe. ”,则因为VS认为scanf函数是不安全的,进行安全开发生命周期SDL检查设置即可。



三.OllyDbg逆向自动拾取阳光

自动捡取的关键是点击鼠标,如果你点击到了阳光上它才会增加。所以我们希望在阳光下落的时候触发点击阳光事件,然后阳光地址会增加,初步预测涉及两个CALL函数。

    阳光出现call 判断是否点击到阳光然后增加阳光的call

第一步,当我们使用Cheat Engine定位到阳光的地址后,可以选中该地址右键设置“找出是什么修改了这个地址”。

首先,植物大战僵尸此时定位的地址为:0x2099AE60;然后选中改地址右键,设置“找出是什么修改了这个地址”。

    0x2099AE60

第二步,等待下一个阳光捡起后,可以在下图所示窗口中获取新产生的值,即0x00430A11。接着点击0x00430A11地址,将扩展信息记录下来,方便接下来的自动拾取功能。

    0x00430A11

第三步,利用OllyDbg软件打开“PlantsVsZombies.exe”游戏。


第四步,前面我们已经定位到了阳光的窗口地址0x00430A11,接着按下Ctrl+G或者右键“转到”->“表达式”,然后跳转到指定位置。

跳转0x00430A11如下图所示:


第五步,按下F2给它增加个断点以及注释,游戏运行到点击阳光增加数值时就会断到这里。 我们可以查看ECX数值,它应该是19,对应十进制的25,所以猜测这里是增加阳关值。

运行程序直到捡起阳光,它会自动停到断点位置,并且ECX修改为0x19,对应的阳光值增加25分。观察汇编代码,发现它是一个增加语句,即验证了它是阳光的增加语句。

    0x00430A11 ADD DWORD PTR DS:[EAX+5560],ECX

第六步,点击“调试”->“执行到返回”按钮(快捷键Ctrl+F9)。

接着跳转到0x00430AB4位置,如下图所示,注意返回到0x004314FD位置。

    返回地址:0x004314FD

第七步,在RETN返回处按下F7,执行单步步入,会看到CALL函数执行完毕。我们不难推测这个函数就是增加阳光的函数。

    0x004313F8 CALL PlantsVs.004309D0

接着我们给它增加一个断点,然后再次运行程序,点击拾取阳光后会自动定位到该位置。


接着选中0x004313F8该行,右键“汇编”,然后在弹出的窗口中设置为nop即可。

如下图所示,设置之后0x004313F8位置变成了NOP空指令。我们可以把这个语句NOP设置后,发现点击阳光数值是不增加的,从而确定了增加函数。


第九步,然后右键撤销修改,接着分析汇编代码JNZ操作。

这时可以看到,在CALL函数之前有一个JNZ操作,也就是说它可能需要判断值才会进入增加阳光的函数,我们在这个JNZ下断点,再进入游戏点击阳光。

    JNZ:jump if not zero,结果不为零(或不相等)则转移。

多次运行程序放行之后会发现,当我们点击阳光之后,阳光会往上走,只有当阳光完全到达指定位置(左上角)之后,才会执行call增加阳光值,由此得知这个JNZ主要是判断阳关是否到位。


第十步,继续执行程序定位点击函数。 在增加阳光的CALL函数(0x0043159B)前有个跳转,当JNZ执行成功之后才会增加这个CALL。我们在JNZ处下断点调试它的执行流程。

当我们在JNZ处下断点后,运行游戏会突然跳转到断点处停止,如下图所示,并且游戏屏幕没有任何操作,接着按下F7运行发现阳光即将出现。

阳光出现如下图所示。

由于JNZ断点会让游戏很卡,接着我们将该处断点取消,而在0x0043159B位置CALL增加断点,执行程序后会发现当我们点击阳光的时候会被断下,所以判断它是阳光采集函数。这是个很典型的if-else语句, 如果没有被点击就会一直执行动画CALL,如果被点击那么就会执行增加阳光的CALL。


第十一步,最重要的步骤出现,我们将jnz修改为jmp,从而实现自动捡取阳光。

当我们修改完成之后,会发现阳光一出现就自动增加,根本不需要手动去点击,最终完成了该辅助功能。同样,我们可以尝试编写C语言实现相关自动化修改,这里不再进行讲解。

    JNZ:jump if not zero,结果不为零(或不相等)则转移。 JMP:汇编无条件跳转指令。

注意,CMP BYTE PTR DS:[EBX+50],0 是判断是否收集阳光的标志,然后才执行JNZ或JMP操作。当我们点击一个植物时,程序断了下来,可以看到赋值0,JNZ是不会跳转的;当我们点击阳光的时候才会赋值1,调用函数采集阳光。



三.总结

写到这里,这篇文章就介绍完毕,希望对您有所帮助,最后进行简单的总结下。

    VS内存地址查看 Cheat Engine逆向修改阳光值 OllyDbg逆向自动拾取阳光

很多朋友问我如何学逆向分析? 下面给出推荐的学习路线和安全书籍。软件逆行其实就是搬砖活,你需要的是任性和基本功。可能大佬们会有很多技巧,但我希望你能扎扎实实去躺过那些坑,会看懂代码,会写代码,然后IDA和OD工具(倚天屠龙)用好,每天泡在代码中,肯定能行的。你应该这样学习: 1.多敲代码,重视实战; 2.程序不是写出来的,是调出来的; 3.根据自己兴趣和市场需求做一定规模的项目。

下图开发和逆向项目非常推荐你去完成,开发远控软件有助于你分析木马,CAD软件能提升你C++分析能力,做一个调制器或许反调试就不再那么难,自制一个小操作系统、小编译器、任务管理器,或许逆向原理就懂了。

最后给出了这一年我在网络安全、系统安全和机器学习看过的书,如果你想把AI更好的融入安全领域,看看这些书籍还是挺不错,我也厚着脸皮把自己写的两本Python数据分析书放了进来,哈哈~

网络安全:

系统安全:

AI+安全:


编程没有捷径,逆向也没有捷径,它们都是搬砖活,少琢磨技巧,干就对了。什么时候你把攻击对手按在地上摩擦,你就赢了,也会慢慢形成了自己的安全经验和技巧。加油吧,少年希望这个路线对你有所帮助,共勉。



参考资料: [1] [2] [3] [4] [5] [6]

经验分享 程序员 微信小程序 职场和发展