植物大战僵尸曾经是一款火爆全球的游戏,本次使用 CE 以及 OllyDbg,分析一些功能,并且对其进行修改,最后编写代码改写阳光值,注入dll。

0x10 内存和汇编代码分析

Cheat Engine(CE):Cheat Engine 是一款开源的内存修改工具 ,它允许你修改游戏或软件内存数据,以达到各种非常规目的。它包括16进制编辑,反汇编程序,内存查找工具。与同类修改工具相比,它具有强大的反汇编功能,且自身附带了外挂制作工具,可以用它直接生成外挂。

使用 CE 分析植物大战僵尸的内存分布
在这里插入图片描述

0x10 寻找存储游戏暂停和开始状态的内存单元地址

对于植物大战僵尸这款游戏,当用户的鼠标离开游戏窗口时,游戏会暂停。当鼠标点击“继续游戏”,游戏继续。我们就以这个为例,怎么找到游戏暂停和开始,在内存中的具体位置?

一般来说,游戏开发者,通常使用 0/1 来表示开和关的两种状态。所以,当鼠标离开游戏窗口时,也就是游戏暂停的时候,在 CE 的搜索框中,写入数字 0,Value Type 选择字节,点击 “First Scan”
在这里插入图片描述
也就是说,当游戏暂停的时候,找到 151… 个字节的内存,存储的都是 0。这么多内存地址存放的都是 0???那我们该怎么办呢?这时,就需要在点击 “继续游戏” 的时候,点击 “Next Scan”,再次搜索数字 1,进行内存筛选。

Tips:为了达到玩游戏的时候,继续用 CE 搜索,需要设置快捷键,在setting选项里,将 Next Scan - Exact Value 随便设置一个快捷键,方便我们在玩游戏时,搜索 1。
在这里插入图片描述
所以,不停的使用 Next Scan - Exact Value ,不停的暂停和开始(暂停时选择继续搜索0,开始时选择继续搜索1),若干次筛选以后,发现如下很多个内存地址都是随游戏状态的改变而改变。这时候,就需要使用 CE 的内存修改功能了。将这些地址依次修改为 1,如果游戏由暂停变为继续,说明我们找到了该地址
在这里插入图片描述
但是事实上,你会发现,把上面所以地址的值都改为 1,游戏还是没办法继续。这里推断我们可能从一开始就猜错了,也就是说,游戏暂停的内存值为 1,游戏继续的内存值为 0。重复上述的筛选过程。最终,我们成功找到了该地址,如下图所示

在这里插入图片描述

题外话:还可以通过观察内存值的动态变化,判断该内存的功能。如下图,鼠标移动到游戏窗口时,0x026CC10C 的值就变为 1,说明该值用来检测鼠标的位置。而用鼠标点击整个 “游戏暂停” 窗口时,0x00AE2A04~0x027E0D50 都变为 1,说明是用来检测是否点击该窗口的
在这里插入图片描述

0x12 寻找修改特定内存单元的指令

在找到存放游戏暂停状态的内存单元之后,我们需要定位到相应的代码,即是哪一段代码修改该值。右击该地址,选择 “Find out what writes to this address”。此时,我们要手动修改该地址的值,就会发现,下面的窗口多了两行指令,这两个汇编指令就是用来修改游戏状态的。
在这里插入图片描述
记录下来

0042837D - 88 9E 7C010000  - mov [esi+0000017C],bl <<
// 修改游戏状态为0,游戏就会继续

00472B8B - C6 86 7C010000 01 - mov byte ptr [esi+0000017C],01 <<
// 修改游戏状态为1,游戏就会暂停

0x13 拦截游戏暂停函数

这里,需要用到另一款工具,OllyDbg。OllyDbg 是一种具有可视化界面的32位汇编分析调试器,是一个新的动态追踪工具,将IDA 与 SoftICE 结合起来的思想,Ring3 级调试器,非常容易上手,己代替 SoftICE 成为当今最为流行的调试解密工具了。同时还支持插件扩展功能,是目前最强大的调试工具。

关闭 CE,打开 OllyDbg,附加进程植物大战僵尸,在汇编窗口,右击,Go to -> Expression (也可以直接使用快捷键 Ctrl + G),可直接复制地址,找到我们刚刚找到的更改游戏状态的代码。
在这里插入图片描述
找到该代码所在函数的起始位置,即上图中的最上面几行代码,push ebp mov ebp, esp 明显是函数的起始处。将

00472B50    55    push ebp

修改为返回指令

retn 4

点击Olly的运行按钮,并且手动点击继续游戏,这个时候,无论鼠标是否离开游戏界面,游戏都不会暂停。
在这里插入图片描述

0x14 寻找阳光值

撤销刚刚修改的汇编代码
重新打开 CE,有了刚刚的经验,现在搜索阳光值就比较简单了。直接在 CE 中,搜索阳光值,当阳光值发生变化的时候,在上次搜索的基础上,再次搜索新的阳光值。搜索到的阳光值存储单元如下

1C6E3DB0

在这里插入图片描述

0x20 寻找三级指针定位基地址

现代操作系统都引入了一个概念 ASLR(Address Space Layout Randomization,地址空间布局随机化),程序每次加载进内存的地址都是不一样的。我们在上面介绍了怎么使用 CE 和 Olly 更改游戏的内存和代码,不过,一旦游戏重启,我们的修改就失效了。

对于植物大战僵尸这款游戏来说, 由于其是由 C/C++ 代码编写的,避免不了使用多级指针,举个例子来说

--> 游戏指针 --> 向日葵指针 --> 向日葵个数
		   |
		   |-> 僵尸数组指针

     p    --> *(*p + 1)  --> *(*(p + 1) + 1)

同样,利用 CE 找到修改阳光值的汇编代码

0044BA45 - 01 87 78550000  - add [edi+00005578],eax <<  /* 第三层指针 */
0044BA4B - 8B 87 78550000  - mov eax,[edi+00005578]
0044BA51 - 3D 06270000 - cmp eax,00002706

这里的 0x5578 就是偏移地址,edi 的值是多少呢?关闭 CE ,打开 Olly,使用 Olly 进行调试,Ctrl + G,搜索到地址所在的汇编代码,双击这一行,设置断点

F9 运行,并且点击游戏界面的 “继续游戏”,会发现,汇编代码停留在设置的断点处(也就是修改阳光值的代码),分析堆栈,我们的目的是找到谁给 edi 赋值了。这次,更换吾爱破解版本的 Olly,修复了不少 bug,添加了一些新功能
在这里插入图片描述
记录下 EDI = 0x1C50DF90,这里要找到 EDI 赋值的地方,即要找到哪个函数给 EDI 赋值了。我们在堆栈区,找到 EDI 第一次出现的位置(从下往上找,堆是向上生长),该值所在的函数,有两个返回地址,我们都跟随到反汇编窗口,在CALL指令设置一下断点,F9 运行多次,观察 EDI 是否变化成 0x1C50DF90,最后找到调用给 EDI 赋值的函数
在这里插入图片描述
在该函数中,并没有发现修改EDI的地方,只能再往上回溯,找到调用该函数的函数,依次跟随
在这里插入图片描述
最终,在第三层调用出,发现了给 EDI 赋值的汇编代码
在这里插入图片描述
记录下来

004753F0    8BBE 68080000   mov edi,dword ptr ds:[esi+0x868]  /* 第二层指针 */

紧接着,需要找到是谁给 esi 赋值,请注意:这里要在上面的这条汇编指令处设置断点,并运行,得到 esi 的值,利用相同的方法即可(这里较难查找,再次使用 CE 查找 esi)
在这里插入图片描述
绿色地址代表每次程序加载都不会发生变化,就可以理解为基地址,实际上就是一级指针的值,四个绿色地址任选其一即可,那么到此,我们已经完成三级指针的查找,也就找到基地址了。

  • p = 0x007794f8
  • *p + 0x868
  • *(*p + 0x868) +0x5578

0x30 代码实现

使用 Vistual Studio 新建一个项目,应用程序类型选择 DLL,其他默认即可,可不勾选微软的 SDL,代码逻辑可以直接写在 dllmain.cpp

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"

int ***p = (int ***)0x007794f8;

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		*(*(*p + 0x868 / 4) + 0x5578 / 4) = 9999;
		MessageBox(0, "Success!", 0, 0);
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

随便找到一款dll注入工具,将我们生成的dll注入即可
在这里插入图片描述

0x40 总结

本篇文章只是初步介绍植物大战僵尸这款游戏WG制作的基本知识,希望能够带领大家入门,更多好玩有趣的玩法,有待进一步验证,这款游戏能够更改的功能还有很多,如果最终都能够利用代码来实现,是最好不过的。在这里,希望大家能够看到软件制作中还是要有安全意识的,不然你的游戏只能称为别人的炮灰!

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐