栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C语言程序(有一点pp)实现PVZ一代修改,探索记录 (正在更新)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C语言程序(有一点pp)实现PVZ一代修改,探索记录 (正在更新)

wscb 只用过CE

建议食用前先熟悉CE基本操作

游戏版本

Plants_Vs_Zombies_V1.0.0.1051_EN

0.找到PVZ进程

这一步是之后对内存操作的基础
导入windows.h头文件, 我们就可以使用winAPI,于是我们可以根据窗口标题找到游戏进程。

1.找到PVZ窗口的句柄(HWND类型)

使用winAPI FindWindow, 下方代码展现了他的一种用法

2.找到PVZ进程ID(DWORD类型)

DWORD即无符号int
使用API GetWindowThreadProcessId

3.找到进程句柄(HANDLE类型)

使用API OpenProcess

HANDLE CatchPvzProcessByTitle(LPCTSTR ProcessTitleName){
    HWND hwnd = FindWindow(NULL, ProcessTitleName);
    DWORD processID = 0;
    HANDLE PVZprocess = NULL;
    GetWindowThreadProcessId(hwnd, &processID);
    if(!processID) return NULL;
    PVZprocess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,processID);
    return PVZprocess;
}
1.修改阳光 1.找地址

使用CE精确数值搜索,可以轻易确定阳光地址
1.5 好的我们来寻找基址, 找基址的方法是直接莽(因为真不会找), 然后就找到了!

2.找基址+偏移

找到阳光的基址和偏移, 发现是
[ [ [ p o p c a p g a m e 1. e x e + 2 A 9 E C 0 ] + 768 ] + 5560 ] [[[popcapgame1.exe+2A9EC0] + 768] + 5560] [[[popcapgame1.exe+2A9EC0]+768]+5560]
而pvz起始申请的地址固定是0x400000, 所以起始地址是62A9EC0

3.修改内存内容

我们可以调用两个winAPI来读写内存: 这里意识流地介绍一点用法, 具体建议自己去查,因为作者也不会

WriteProcessMemory
ReadProcessMemory
参数:
(pvz进程句柄,地址,新值/读取值保存地址,数据大小,NULL)
返回值:
bool类型, 读写失败会返回0

先读地址,确定目标地址是否可以访问, 若成功读取,则修改之。
(如果在选择游戏模式界面, 显然不能修改阳光值, 或者你的地址写错了,也无法修改,所以要先读,如果读取能成功,可以排除一部分问题)

4.没什么用的总结

若正确开始了一句游戏,找到了正确的阳光基址以及偏移量,正确调用修改内存的函数,便可以成功修改阳光数值。

2. 卡片无冷却 一些探索 1.

刚开始根据网上搜索的思路,以1字节为单位搜索,可以找到卡片是否在冷却的标志位,1代表准备就绪,0代表正在冷却。

2.

当你点击卡片,卡片就会变暗,这说明你点击卡片的同时,游戏修改了标志位的数值。

3.

生成反汇编代码,把mov [标志位地址], 00 的改为 01,这样点击卡片时,即标志位数值不变,即可让卡片无冷却。
但这样会遇到一些问题, 这种操作只是“不让卡片从就绪状态进入冷却状态”, 如果你先使用卡片,在卡片冷却是修改代码,正在冷却的卡片是不会立刻准备就绪的。

4.

遇到了另一个问题,在寻找基址的过程中,有一个中间步骤为[edi + 24], 但查找edi的值时无匹配项, 寻找基址无果。好在后来通过一个等价地址[eax + ecx + 70]寻得,至于为何用到了两个寄存器做偏移, 当时未知, 之后探索出来了。

5.

后来经过玄学+盯代码+猜+不严谨证明,习得了部分卡槽机制。

  • 每个卡槽都有一个“已经冷却了多长时间”的计时(即反汇编代码中的[edi + 24]), 这个计时会从冷却开始时增加。
  • 每个卡槽都会根据所选植物不同有一个冷却时长(即反汇编代码中的[edi + 28]),当卡槽冷却计时达到了这个冷却时长,则冷却计时置0, 卡片进入就绪状态。
  • 相邻卡槽冷却标志位地址做差,可以得到80(0x50), 相邻卡槽冷却计时的地址做差,可以得到80(0x50), 且对于同一卡槽,其冷却计时地址相对其冷却标志位地址的偏移为-36
    .
  • 可以推测出,储存卡槽信息的是一系列连续的结构体,每个结构体占用0x50Byte的空间, 而经验证,双偏移中的[eax + ecx + 70]eax是50的倍数,即使第几个卡槽,可以直接通过ecx找到基址
卡片无冷却的修改方法

找到了许多种,但未能深入理解代码

在反汇编代码中, 冷却计时每次加1,通过不断的类似这样的循环,实现冷却恢复。只要冷却计时小于等于(jle)目标时间,循环就继续,游戏中的卡片冷却进度条也不断刷新。

冷却计时+1
mov, eax , 冷却计时
cmp eax,目标时间
把eax sub成0

1. 修改反汇编代码,固定地址0x487290处3个字节

每次冷却计时+1, 把对应mov [xxx] 01改为 00,即冷却计时一直是0,可以实现卡片无冷却(貌似计时置0后循环就会跳出)。

2. 修改反汇编代码,固定地址0x487296处1个字节

把jle 改成ja(判大于), 直接结束循环,之后卡片冷却标志位置1,实现无冷却

3.修改反汇编代码以及内存数据

先修改“使得卡片标志位变为00”的mov代码为01,使卡片不会从就绪状态进入冷却状态,然后通过时间计数+固定偏移36(0x28)修改所有卡槽的标志位为01,令正在冷却中的卡片刷新。

没用的东西

作者在CE中使用了这三种方法,但只选择方法2进行了代码实现

3.阳光自动收集 0.

进行4Byte搜索, 阳光会有一个标志判断是否被点击, 没点击时为0, 点击后为1。(不过点了阳光马上暂停好像找不出来,需要等一会)。

1.

找到阳光是否被点击的标志位后, 查看“什么访问了这个地址”, 发现一些有趣的数据,(节选):

若干个(cmp byte ptr [ebx+50],00 出现次数:非常非常多次)
cmp byte ptr [ebx+50],00 出现次数:x (后跟jne)
mov byte ptr [ebp+50],01 出现次数:x

其中下方两行,每点击一次阳光,出现次数都加一。猜测时点击阳光时先判断阳光点击标志位是否=1(等价于标志位是否!=0),如果不为0,则跳转, 否则进行第三行操作把标志位置1。

2.

然后联想到还有很多个出现非常多次的“cmp byte ptr [ebx+50],00”, 说明游戏会经常检验阳光是否被点击, 那么猜想,检测到阳光被点击后,游戏应该会进行收集操作,很可能有一个cmp后会跟收集阳光操作。
于是把其中一个“cmp byte ptr [ebx+50],00”后面的jne改为je(由if 标志位!=0-阳光被点击则跳转到收集操作 改为 if 标志位==0-阳光不被点击则跳转到收集操作), 或者改成jmp也行

3.

所以, 只要把popcapgame1.exe+3158F位置的jne改为je,即可实现阳光的自动收集

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/458237.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号