[系统安全] 五.OllyDbg和Cheat Engine工具逆向分析植物大战僵尸游戏

假装没事ソ 提交于 2020-12-24 07:49:16

您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列。因此,我重新开设了这个专栏,准备系统整理和深入学习系统安全、逆向分析和恶意代码检测,“系统安全”系列文章会更加聚焦,更加系统,更加深入,也是作者的慢慢成长史。换专业确实挺难的,逆向分析也是块硬骨头,但我也试试,看看自己未来四年究竟能将它学到什么程度,漫漫长征路,偏向虎山行。享受过程,一起加油~

系统安全系列作者将深入研究恶意样本分析、逆向分析、攻防实战和Windows漏洞利用等,通过在线笔记和实践操作的形式分享与博友们学习,希望能与您一起进步。前文普及了OllyDbg的基础用法和CrakeMe案例;这篇文章将详细讲解OllyDbg和Cheat Engine工具逆向分析用法,完成植物大战僵尸的游戏辅助器,包括修改阳光值和自动拾取阳光两个功能,希望对入门的同学有帮助。

在这里插入图片描述

话不多说,让我们开始新的征程吧!您的点赞、评论、收藏将是对我最大的支持,感恩安全路上一路前行,如果有写得不好的地方,可以联系我修改。基础性文章,希望对您有所帮助,作者的目的是与安全人共同进步,加油~

作者的github资源:

前文分析:


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


一.VS内存地址查看

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

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述


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

#include "stdio.h"

int main()
{
   
      
	int x = 1000;

	//内存中查看值得位置
	printf("%#X\n", &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

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

在这里插入图片描述


第八步,选中该条语句进行nop操作。
NOP指令相当于空指令,不执行任何动作,对应16进制字节码为90。当我们的软件有广告弹窗时,我们可以通过nop设置过滤掉弹窗。

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述


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

在这里插入图片描述

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

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

在这里插入图片描述

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

在这里插入图片描述

注意,这里需要多次在0x004313F4处下断点再取消运行游戏,反复操作之后会发现实现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工具(倚天屠龙)用好,每天泡在代码中,肯定能行的。你应该这样学习:

  • 多敲代码,重视实战;
  • 程序不是写出来的,是调出来的;
  • 根据自己兴趣和市场需求做一定规模的项目。

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

在这里插入图片描述


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

2020年8月18新开的“娜璋AI安全之家”,主要围绕Python大数据分析、网络空间安全、人工智能、Web渗透及攻防技术进行讲解,同时分享论文的算法实现。娜璋之家会更加系统,并重构作者的所有文章,从零讲解Python和安全,写了近十年文章,真心想把自己所学所感所做分享出来,还请各位多多指教,真诚邀请您的关注!谢谢。

在这里插入图片描述

(By:Eastmount 2020-12-23 周三夜于武汉 https://blog.csdn.net/Eastmount)


参考资料:
[1] C语言逆向工程之游戏辅助开发 - C语言Plus
[2] 游戏辅助制作核心–植物大战僵尸逆向之召唤僵尸call(九)
[3] 游戏辅助制作核心–植物大战僵尸逆向之植物攻击加速(六)
[4] 植物大战僵尸自动拾取阳光 - TD.Jia
[5] 游戏逆向篇 - 星星向蓉
[6] [CE游戏逆向] Plants vs. zombies - Simpler_若离

































易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!