植物大战僵尸(汉化第一版)CE修改后台运行
windows10系统下实现植物大战僵尸后台运行。
修改的思路:游戏运行时植物冷却正常进行,游戏暂停时冷却暂停。
-
找到卡槽冷却时间的数据地址
选择冷却时间比较长的土豆地雷,双子向日葵,和坚果进行游戏。
冷却计时器初始未知,CE中选择4字节未知数值(可能是毫秒表示)。不知道计数值是增加还是减少的话推荐都试一下。
游戏开始搜索未知的4字节数据,游戏运行一段时间,尝试查找增加的数据。
搜索到一堆数据,运行一段时间,再次查找增加的数据。结合范围(推测是大于0的数据,冷却时间小于一分钟)搜索和未变动帮助确定数据。
我这里选择土豆地雷的冷却时间。冷却好之后重新种下计时器数值会减小。
找到一个很有可能的值,加入到变量栏中,改大一些,土豆雷的冷却时间减少,那就是正确的变量了,寻找什么改写了这个地址。 -
寻找决定冷却进行的关键值。
在寻找改写指令窗口运行时,多暂停几次游戏,观察到一个写入非常频繁的指令,游戏暂停时不再执行,确定是我们希望得到的指令。
查看内存,在该指令处下断点,右键选择当前函数,分析0048728C的写入指令,推测edi寄存器保存某个指针,而且很有可能就是土豆雷卡片槽的指针。
edi是从上层函数传进来的,按F8寻找上层函数,在004131F4回到函数调用的地方。
发现一个循环,执行这个循环,每次esi都会加1,esi达到0A即10此后退出循环,不进入循环的jle 0041320A指令比较 ebp与 [eax+24],循环退出处jl 004131F0比较esi和[eax+24],格式很像,通过打断点可知ebp恒为0,eax+24很有可能保存游戏中的卡槽数目,不进入循环的跳转可能不是由暂停变量决定。找到程序入口设置断点,游戏一旦暂停不再中断,因此这段代码不是我们要找。
继续查找上层函数。
更上一层没有跳转,嗯,继续回溯。找到调用该段代码地址0041601E。
向上找到一条语句00415F70:jg 00416064,跳转的目的地址大于调用子程序的地址,在00415DF7:je 00415E2E有一分支ret,找到代码入口00415D40设置断点。
令人高兴的一幕出现了,游戏暂停窗口时也发生了中断。
按F8单步执行,发现程序在00415DF7进入含有ret的短代码分支,分支由cmp byte ptr [ebp+00000164],00指令决定。将ebp+00000164加入变量表。需要注意以0019开头是栈内存,无法直接加入地址列表。此处ebp为16353E88,我们可以直接加入列表。 -
发现此地址内存数值游戏暂停变为1,游戏继续变为0
那么是不是找到正确变量地址了呢?查找改写此处值的指令。
第一条在游戏继续时触发,第二条在鼠标点击窗口外部的时候触发,第三条在点击菜单暂停的时候触发。显然我们要找第二条。
按照刚才的方法分析,004502F2有一处跳转,nop掉跳转,游戏仍会暂停,很可惜不是要找的决定暂停的代码。但是可以推断此代码为暂停操作的调用函数,因为断点只有在暂停时才会触发。去上层函数寻找。
这段暂停的调用函数很长,看来做了很多工作。一路F8。来到上层调用的地方,可以看到一条对系统API的调用,此API和释放鼠标有关。上面一条call edx就是刚才的子程序了。
分析此段代码,跳转很多,入口在0054EB80处,果断设置断点。我们先看它是不是只和暂停有关。发现无论是暂停还是返回游戏(鼠标点击),都会断在这里,即使鼠标点击的不是“回到游戏”按钮。说明这里是决定暂停还是继续的混合代码。游戏暂停后或者在游戏内点击鼠标(状态不变)就不会触发。我们找找是哪个变量决定了分支走向。
代码一共有4个最可能的判断变量,所幸变量都不在栈内。将用到的变量加入变量地址表:esi+4CE,esi+4CF,esi+4D2和esi+431。
不调试断点的时候发现esi+4CE和esi+4D2的值与窗口的焦点状态同步。窗口获得焦点时两个值同为1,窗口失去焦点时两个值同为0。推测这个函数在windows消息队列处理循环中调用。
鼠标窗口外点击->失去焦点事件->游戏暂停。这个过程中,只要解决任何一环就可以实现游戏不暂停。
多次调试断点寻找规律,窗口状态变化调用这段代码时,esi+4CE已经发生了变化,esi+4D2尚未变化。当这两个变量的值相反时,由al的值决定0054EBA8处的跳转,并且al的值会赋给esi+4D2。分析代码可知,若esi+4CF为0,那么al的运算结果恒等于esi+4CE。而esi+4CF和esi+431的值多次运行重启未发生变化。
那么我们得出esi+4CE的值很可能是当前窗口焦点状态,esi+4D2保存上一次状态。两次状态不一致,就会触发游戏暂停或恢复。若两次状态一致,经调试发现直接跳出此段代码。
查找哪里修改了esi+4CE,确实有一个地址在窗口焦点变化时改写了它。
在该处地址下断点,猜测此处断点的触发会遭遇上一次分析的代码,确实也如此。
只要esi+4CE(要写入的状态值)恒为1(获得焦点),游戏就不会暂停。
那么有两种方法验证我们的猜测。
一是修改esi+4CE处的代码改为常量 1。
二是将esi+4CE和0的cmp指令改为与1的or指令。
推荐第二种方法。因为第一种方法目标指令只有6字节,而将更改后的指令需要10个字节。第二种方法前后字节数相等。
如果游戏后台运行成功了,那么先前的分析都认定正确。 -
验证
后台运行是否成功了呢?无法录制gif,只能用其他窗口遮挡截图了。(PS:不成功我还会发出来吗)
现在就是保存成果啦。
菜单栏,工具->自动汇编或者Ctrl+A快捷键。可以使用模块地址。
大功告成。
PS:知道了这段代码的用处,可以尝试多种方式实现后台运行,不仅仅是更改焦点状态变量。
经典的植物大战僵尸辅助工具V3.1就是修改跳转指令实现的。