游戏辅助原理与制作02

您所在的位置:网站首页 植物大战僵尸内存基址 游戏辅助原理与制作02

游戏辅助原理与制作02

2024-07-12 13:33| 来源: 网络整理| 查看: 265

一、分析思路

    当我们种下一棵植物的时候,通常需要等待一段时间才能再种下一棵。在游戏开发中实现这一过程的,往往是使用一个定时器的变量。对于定时器的变量,一般有两种,一种是递减的,即从某个数开始逐渐减到0;另一种是递增的,即从0开始一直加到某个数。

二、分析过程

对于一开始,游戏的植物没有种植,所以计时器肯定是不变的,所以这时我们用CE搜未知初始化的值“Unknow initial value”,发现搜出很多值。

然后,种下一棵向日葵,计时器开始计时,这时计时器开始变化了。但我们不知道它是递增型的还是递减型的,我们只知道它变化了,所以我们搜变化了的值“Changed value”(注意:游戏暂停时,Changed value只能搜索一次),还是有很多值。

此时,由于游戏暂停,向日葵的冷却时间也暂停了,因此可以搜索未变化的值“Unchanged value”,可以多次点击进行搜索。

回到游戏,让计时器走一下,然后继续搜【一次】变化的值,仍有很多结果,这时我们已经暂停游戏了,所以计时器未变化,我们搜未变化的值。

我们看到,结果少了一半,但还是有很多。我们选择直接让计时器走完,然后搜变化的值,还是有很多结果,这时冷却已经完成了,定时器是不会变了,所以我们搜未变化的值,不过在此之前我们先玩一下游戏,排除一下干扰,我们看到,结果也少了很多,我们继续这种思路,玩一下搜未变化的值。我们尝试几次后,发现它也不怎么管用了,能排除的值也越来越少,这时,我们把向日葵种下去,这样定时器就开始走了,接着我们搜改变的值,我们看到,结果又少了很多,我们继续这种搜索,一直搜索,直到结果只有几个为止。

最后,我们搜到六个结果。我们继续原来的办法进行排除时,发现只能排除两个,剩下四个怎么都排除不掉。但是我们不断种植向日葵的时候发现,最后一个地址的数值是比较小的,其它的几个也太大了(当然,不排除这个计时器变量是一个浮点或者双精度)。而且这个地址的值是逐渐增加的。

总之,在这几个地址里,我们最喜欢的就是这个了,不过我们还是得先验证一下。我们重新种下一棵向日葵,发现它的值在不断增加,这时我们直接把它的值改成三千,发现向日葵的冷却一下子就好了,这也就证明了,它是我们要找的计时器的变量。

向日葵冷却地址(动态)0x0E0B0F0C,上限750

要去掉这个时间,改的不是当前的冷却时间,而是要改与之比较(cmp)的上限值。

cmp 当前冷却时间计数,冷却时间上限

在该地址上右键,选择 Find out what accesses to this address(谁访问了这个地址),弹出的窗口里面是空白的

 此时玩一下游戏,让向日葵冷却时间走动,在看这个窗口

找到一个inc指令,选中这行,点击右边的“Show disassembler”按钮,显示“Memory Viewer”窗口

在下方不远处有一行指令 cmp eax,[edi+28],可能为当前冷却时间与冷却时间上限比较。

比较之后进行跳转 “jle 植物大战僵尸.exe+B3007”

将 “jle 植物大战僵尸.exe+B3007” 指令 nop 掉进行测试

右键选择“Replace with code that does nothing”(使用空指令替换)

此时,再游戏中种植植物,发现所有的冷却时间都已去除。

另外一种方法:去掉某一种植物的冷却时间,需要对冷却时间上限进行进一步分析。

找冷却时间基址 ★★★★★★

004B2FE5 - 38 5F 49 - cmp [edi+49],bl

004B2FE8 - 74 1D - je 植物大战僵尸.exe+B3007

004B2FEA - FF 47 24 - inc [edi+24]

= 0)

在OD上0x00428E50处下个断点,找到EDI值为0x183A1018,并运行游戏

向日葵冷却动态地址:

0x0E0B0F0C = [edi+24] = [eax+24]

= [ebx+eax+0x28+24]

= [ebx+[edi+0x15C]+0x28+24]

= [[0x183A1018+0x15C] + n* 0x50 + 0x28 + 24] (n >= 0)

验证,在OD的命令窗口输入 dd [0x183A1018+0x15C] + n* 0x50 + 0x28 + 24 并回车

(注意:下图测试 EDI= 17FA6838)

dd [0x17FA6838+0x15C] + n* 0x50 + 0x28 + 24 当前植物冷却时间

dd [0x17FA6838+0x15C] + n* 0x50 + 0x28 + 28 当前植物冷却时间上限

(n=0...当前植物卡槽总数 [eax+0x24])

在CE中搜这个EDI的值0x183A1018,找到大量的地址

图中看到0012开头的地址为堆栈中的地址,因此可以排除

其他,各地址段的地址随机取一个(当发现一个地址找不到基址时,换另外一个地址试)

下面以0x01089BA0为例来分析:

现在CE中搜索0x01089BA0这个地址 ,发现并未找到

在OD中用 dd 01089BA0 命令找到01089BA0 在内存中的位置,并下一个内存访问断点

这是,会找到一个偏移 eax+0x868, EAX = 0x01089338

向日葵冷却动态地址:

0x0E0B0F0C = [edi+24] = [eax+24]

= [ebx+eax+0x28+24]

= [ebx+[edi+0x15C]+0x28+24]

= [[[eax+0x868]+0x15C] + n* 0x50 + 0x28 + 24] (n >= 0)

在CE中搜索EAX=0x01089338,找到4个绿色的地址,都为基址

向日葵冷却动态地址:

0x0E0B0F0C = [edi+24] = [eax+24]

= [ebx+eax+0x28+24]

= [ebx+[edi+0x15C]+0x28+24]

= [[[[0x007794F8]+0x868]+0x15C] + n* 0x50 + 0x28 + 24] (n >= 0)

dd [[[0x007794F8]+0x868]+0x15C] + n* 0x50 + 0x28 + 0x24 植物当前CD时间

dd [[[0x007794F8]+0x868]+0x15C] + n* 0x50 + 0x28 + 0x28 植物CD时间上限

dd [[[0x007794F8]+0x868]+0x15C] + n* 0x50 + 0x28 + 0x48

dd [[[0x007794F8]+0x868]+0x15C] + n* 0x50 + 0x28 + 0x49

简化

dd [[[0x007794F8]+0x868]+0x15C] + n* 0x50 + 0x4C

dd [[[0x007794F8]+0x868]+0x15C] + n* 0x50 + 0x50

在OD中输入 dd [[[0x007794F8]+0x868]+0x15C] + 4C,

查看地址值 0x0E0B0F0C 即为向日葵的当前冷却时间,

查看地址值 0x0E0B0F10 即为向日葵的冷却时间上线,0x2EE = 十进制750

[[[0x007794F8]+0x868]+0x15C] + n* 0x50 + 0x28 + 0x24 为当前冷却时间

[[[0x007794F8]+0x868]+0x15C] + n* 0x50 + 0x28 + 0x28 为冷却时间上限

CE中验证:

注意:

冷却时间需要结合这2个标志位进行,请自行分析:

 edi+24 当前CD时间

edi+28 CD时间上限

edi+48 byte 0

edi+49 byte 1 CD计数开始

48 word 00 01 表示 开始CD计时,卡片不可选

48 word 01 00 表示未开始CD计时,卡片可选中

 

三、代码实现 // 禁用CD void CFZ_PlantsVsZombiesDlg::OnBnClickedCheckCd() { UpdateData(true); // 更新窗口状态至变量 UCHAR buf[2]; if(m_b_cd == true) { // 去掉冷却时间 //004B2FE8 - 74 1D - je 植物大战僵尸.exe+B3007 //90 90 buf[0] = 0x90; buf[1] = 0x90; } else { // 启用冷却时间 //004B2FE8 - 74 1D - je 植物大战僵尸.exe+B3007 buf[0] = 0x74; buf[1] = 0x1D; } //把buf内数据写入地址 0x004B2FE8 HANDLE hp = GetGameProcessHandle(); DWORD bywrite; if(hp == NULL) { MessageBox("打开进程出错", "提示", MB_OK); return ; } ::WriteProcessMemory(hp, (LPVOID)0x004B2FE8, buf, sizeof(buf), &bywrite); ::CloseHandle(hp); // 释放句柄 } // 获取当前关卡植物卡片总数 DWORD GetPlantsCardCount() { HANDLE hp = GetGameProcessHandle(); DWORD buf = 0, byread, bywrite; // 007794F8 +868 +15C + 24 ::ReadProcessMemory(hp, (PVOID)0x007794F8, &buf, sizeof(buf), &byread); ::ReadProcessMemory(hp, (PVOID)(buf + 0x868), &buf, sizeof(buf), &byread); ::ReadProcessMemory(hp, (PVOID)(buf + 0x15C), &buf, sizeof(buf), &byread); ::ReadProcessMemory(hp, (PVOID)(buf + 0x24), &buf, sizeof(buf), &byread); ::CloseHandle(hp); // 释放句柄 return buf; } // CD时卡片可选 void CFZ_PlantsVsZombiesDlg::OnBnClickedCheckCdcard() { UpdateData(true); // 更新窗口状态至变量 UCHAR data[2]; if(m_b_cdcard == true) { data[0] = 0x01; data[1] = 0x00; } else { data[0] = 0x00; data[1] = 0x01; } HANDLE hp = GetGameProcessHandle(); // 当前关卡植物卡片总数 DWORD iPlantCardCount = GetPlantsCardCount(); DWORD buf = 0, byread, bywrite; // dd [[[0x007794F8]+0x868]+0x15C] + n* 0x50 + 0x28 + 0x48 ::ReadProcessMemory(hp, (PVOID)0x007794F8, &buf, sizeof(buf), &byread); ::ReadProcessMemory(hp, (PVOID)(buf + 0x868), &buf, sizeof(buf), &byread); ::ReadProcessMemory(hp, (PVOID)(buf + 0x15C), &buf, sizeof(buf), &byread); UpdateData(true); for(int i = 0; i < iPlantCardCount; i++) { ::WriteProcessMemory(hp, (PVOID)(buf + i * 0x50 + 0x28 + 0x48 ), data, sizeof(data), &byread); } ::CloseHandle(hp); // 释放句柄 }

四、延伸分析

根据上面的分析,可以得到植物卡片在内存的数组数据

 第一个卡片的地址:

起始地址: [[[0x007794F8]+0x868]+0x15C] + 0* 0x50 + 0x28 (图中为0DCBB3D8)

当前CD: [[[0x007794F8]+0x868]+0x15C] + 0* 0x50 + 0x28 + 0x24 (图中为0DCBB3FC)

CD上限: [[[0x007794F8]+0x868]+0x15C] + 0* 0x50 + 0x28 + 0x28 (图中为0DCBB400)

48、49: [[[0x007794F8]+0x868]+0x15C] + 0* 0x50 + 0x28 + 0x48 (图中为0DCBB420)

第二个卡片的地址:

起始地址: [[[0x007794F8]+0x868]+0x15C] + 1* 0x50 (图中为0DCBB428)

当前CD: [[[0x007794F8]+0x868]+0x15C] + 1* 0x50 + 0x28 + 0x24 (图中为0DCBB44C)

CD上限: [[[0x007794F8]+0x868]+0x15C] + 1* 0x50 + 0x28 + 0x28 (图中为0DCBB450)

48、49: [[[0x007794F8]+0x868]+0x15C] + 1* 0x50 + 0x28 + 0x48 (图中为0DCBB470)



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3