植物大战僵尸变态辅助开发系列教程(E语言实现和VC6实现)(中)

news2024/11/17 21:23:27

植物大战僵尸变态辅助开发系列教程(E语言实现和VC6实现)(中)

    • 26、第一种方法实现变态加速功能
    • 27、第二种方法找出变态攻击加速的方法
    • 28、加快阳光、金币生产速度
    • 29、全屏僵尸
    • 29、全屏减速第一课
    • 30、全屏减速第二课
    • 31、全屏奶油的找法
    • 32、全屏减速的实现
    • 33、全屏奶油的找法
    • 34、全屏减速、奶酪的选择性实现
    • 35、CALL寻找植物攻击力


26、第一种方法实现变态加速功能

由于豌豆射手的攻击间隔不是很明显,所以咱们用西瓜来找植物攻击的间隔范围,当西瓜往下压的时候间隔值是最大的。

咱们得先把僵尸的血给找到,找到后把值改大一些,这样才不会很轻易的被植物灭掉。

在这里插入图片描述

先搜索270(这个值是僵尸的血量),当僵尸被豌豆射手打了以后,在搜索250:

在这里插入图片描述

咱们给它锁住。

在这里插入图片描述

在这里插入图片描述

减慢游戏速度,等西瓜往下压的时候间隔的数值肯定是最大的,先搜索未知的初始数值,然后回到游戏中在西瓜弹出来之前(有投掷的动作),搜索减少的数值:

在这里插入图片描述

不断回到游戏,再回到CE搜索减少的数值,反复这样操作:

在这里插入图片描述

在这里插入图片描述

但是,当西瓜投出来了以后,就不要搜索减少的数值了,这样分析出来的数据是不对的,等它准备再有下压投掷动作的时候,回到CE中搜索增加的数值:

在这里插入图片描述

在这里插入图片描述

咱们再过滤一下搜到的数值,植物攻击范围和植物攻击动作的范围一般是一样的,这个数值肯定不会很大,所以比3000小的数值都可以删除了:

在这里插入图片描述

然后回到游戏中,观察CE这几个地址的数值,看哪个不断减少接近0:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

上图选中的是攻击间隔,我们不要,删除它。

在这里插入图片描述

当这个数值是1的时候,炮弹投掷出去了,当西瓜一填弹、压了一个西瓜上来,这个数值就变成0了。

在这里插入图片描述

我们看到西瓜一往下压这个投掷器,这个数值就有值了,并开始倒数:

在这里插入图片描述

在这里插入图片描述

扔出去以后这个值就变为1了,等投掷器上一有西瓜,该值就变为0了:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

咱们把这个地址复制一下,解除CE附加,到OD中转到该地址:

在这里插入图片描述

按两下回车,让该命令生效,在内存窗口该地址处下一个硬件写入断点:

在这里插入图片描述

程序会断到:

在这里插入图片描述

如上图所示点击右上方的WBP按钮,把硬件断点删除。

在这里插入图片描述

我们看到EDI的值为0C9143D8,我们把这个值复制到CE中验证一下:

在这里插入图片描述

在这里插入图片描述

可以看到这两个地址是一样的。

在这里插入图片描述

咱们把这句指令改为:

在这里插入图片描述

在这里插入图片描述

可以发现它一直投不出来西瓜,这是怎么回事呢?
当eax为1的时候,执行到下面它会被减1,就变成0了,我们之前测试过,只有当它为1的时候这个西瓜才会投弹。

在这里插入图片描述

咱们给它如上修改,让eax的被下面指令减1后一直为1,然后我们再看一下效果:

在这里插入图片描述

但是有个问题就是它一直为1的话它就会不停的攻击,甭管有没有僵尸它都攻击,所以应该还有一个判断。

回到游戏,等出现僵尸后,在同一行上种植西瓜,然后回到OD中下断:

在这里插入图片描述

断下来了以后咱们按F8往下走:

在这里插入图片描述

这里有一个对比,判断这个倒计时是不是为1:

在这里插入图片描述

这个jnz跳转就是往上跳转到:

在这里插入图片描述

这就是这么一个攻击的循环,咱们怎么改呢?咱们先把断点删除:

在这里插入图片描述

在这里插入图片描述

咱们如果给它改成JMP的话,子弹还是发射不出来:

在这里插入图片描述

在这里插入图片描述

咱么就不让它往回跳了,给它NOP掉:

在这里插入图片描述

在这里插入图片描述

现在我们可以看到,这个动作只执行了一次,但是它一次发射了很多炮弹,这个就是一种更为变态的攻击加速。

在这里插入图片描述


27、第二种方法找出变态攻击加速的方法

在这里插入图片描述

在这里插入图片描述

咱们还是用老方法,在CE中分析这些CMP指令所在的地址:

在这里插入图片描述

在这里插入图片描述

改成JMP后发现子弹发射不出来了,还原回去后用NOP空指令替换:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

成功实现想要的效果了。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

复制该关键地址,到OD中转到该地址:

在这里插入图片描述

可以看到用这种方法找到的地址,正好也是上节课我们调试跟踪分析出来的地址。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


28、加快阳光、金币生产速度

在这里插入图片描述

咱们搜索产生的间隔,在OD里面把这个间隔倒数的时候给它加快就可以了。

在这里插入图片描述

然后这个时候它会进行倒数(等待产生阳光),然后咱们搜索减少的数值:

在这里插入图片描述

在这里插入图片描述

不断的进游戏,再切换回CE,点击再次扫描减少的数值,在阳光产生前反复进行这种操作:

在这里插入图片描述

等出现了一个阳光后,咱们再搜索增加的数值:

在这里插入图片描述

第一个地址的数值肯定不对,因为它是一个倒数的数值,不会那么大,所以只看下面两个地址:

在这里插入图片描述

第一个地址修改后没有效果,咱们改第二个的数值为1,发现立刻就会出现阳光:

在这里插入图片描述

在这里插入图片描述

咱们给它修改为1后锁定住,会发现出现了一大堆的阳光:

在这里插入图片描述

给它改成5或者10锁定也还产生一大堆阳光,改成100的话就不产生阳光了。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

咱们把这个地址先记录下来,从OD里面转到这个地址并下断:

在这里插入图片描述

它就是不停的减1,咱们把EDI的值复制下来到CE里面看看这是个什么数值:

在这里插入图片描述

在这里插入图片描述

这个地址跟我们刚才在CE中搜索到的地址一样,把它的数值改为1就立刻产生一个阳光,所以咱们可以在OD中把减去的数值1改大一些:

在这里插入图片描述

我们发现生产阳光的速度就比较快了,咱们再改大点:

在这里插入图片描述

发现不能这样改,字节数不对了,还原回去。

如果想把这个数值改大点的话(比如-100、-128),可以找一处空白位置,将该地址处的指令复制过去并将减数改为-128,并在后面加一条跳回去的指令,将该地址改为跳转到新位置的指令就可以了。

在这里插入图片描述

这里我们就改成0x64就够用了。

在这里插入图片描述

在这里插入图片描述

记录一下修改过的字节集。

在这里插入图片描述

并记录正常的字节集:

在这里插入图片描述


29、全屏僵尸

全屏僵尸就是让僵尸一下子全跑出来,那么这该怎么搜索呢?
咱们先搜索僵尸的数量,然后找到数量增加的关键指令,下断点找到创建僵尸的关键CALL,在这个CALL往上找,找到创建僵尸相关的判断,再做修改就可以了。

用CE将游戏速度设置为5加速进度,等出现一只僵尸后搜索数值1:

在这里插入图片描述

在这里插入图片描述

干掉一只僵尸后再搜索数值1:

在这里插入图片描述

在这里插入图片描述

现在出现3个僵尸,那肯定是第2个地址,保存当前僵尸数量的地址,它的数值肯定是动态的,不可能是静态的。

我们找阳光的地址来和僵尸数量这个地址对比一下:

在这里插入图片描述

在这里插入图片描述

可以看到这两个地址比较接近,都差不多,所以肯定就是僵尸的数量,右键附加CE的调试器找出是什么改写了这个地址:

在这里插入图片描述

咱们不要杀死僵尸,等待创建僵尸的时候得到的指令,又创建了2只僵尸:

在这里插入图片描述

在这里插入图片描述

这个地址就是僵尸数量增加的关键地址,记录一下:

在这里插入图片描述

咱们关掉CE,把OD打开,转到该地址:

在这里插入图片描述

点一下工具栏上的k键打开调用堆栈窗口:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

咱们把每个CALL都标记一下,并给它下个断点,并把僵尸数量增加的断点删除:

在这里插入图片描述

点击运行后直接就断下来的肯定不是,只有在僵尸增加的时候断下来的才是正确的地址。

第2、5、4都不是,现在就剩第3层了,然后咱们测试这一层CALL,咱们把CE打开,加速游戏,发现在僵尸增加的时候果然断到了这个CALL;
既然这个是创建僵尸的CALL的话,咱们给它NOP掉,应该就不会创建僵尸了;
我们发现过了好长时间也不增加僵尸,咱们给指令恢复一下,就又开始创建僵尸了。

咱们ctrl+A分析一下代码,然后继续往这个CALL上面分析,发现有一个jnz跳转,它上面有一个判断,当判断不为0的话就会跳转,直接就跳走了,就不会执行创建僵尸的CALL了,咱们要让它创建的话就不能让它跳转,所以咱们就把这个跳转给它NOP掉(用空指令填充),不让它跳走,然后发现僵尸就一下全出来了。

咱们记录一下修改后的字节集,恢复修改的代码后,再记录一下正常的字节集。


29、全屏减速第一课

在这里插入图片描述

找数据的话也有两个方法。

冰冻效果的这种减速,是一个倒计时,到一定程度以后才恢复正常的状态;
咱们先把僵尸的血量找到并给它锁定上。

在这里插入图片描述

回到游戏打一下僵尸后返回CE如下搜索(豌豆的攻击力是20):

在这里插入图片描述

在这里插入图片描述

回到游戏铲除冰冻豌豆,在僵尸仍处于冰冻状态时,回到CE中搜索未知的初始数值:

在这里插入图片描述

在这里插入图片描述

然后回到游戏,再返回CE,这是冰冻效果倒计时又减少,所以继续搜索减少的数值:

在这里插入图片描述

回到游戏,冰冻效果减少时间,再回到CE继续搜索减少的数值,这样反复操作:

在这里插入图片描述

如果冰冻效果消失了的话,再种上一个冰冻豌豆,让僵尸继续被冰冻,然后CE中只进行一次搜索增加的数值:

在这里插入图片描述

返回游戏,再返回CE,继续搜索减少的数值:

在这里插入图片描述

前面4个地址比00400000小,都是堆栈地址,删除它们;

在这里插入图片描述

在这里插入图片描述

我们发现改成1或者0,冰冻效果并没有消失,说明没找对(可能刚才僵尸已经恢复正常后,我多搜索了一次减少的数值导致的)。

我们还是按照刚才的方法再重新搜索一下。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

现在僵尸变了,咱们再搜索变动的数值:

在这里插入图片描述

铲除冰冻豌豆,返回CE搜索减少的数值:

在这里插入图片描述

还是之前的操作,返回游戏,等1、2秒,返回CE继续搜索减少的数值,重复这样操作:

在这里插入图片描述

在这里插入图片描述

多次这样操作后,估摸着冰冻效果快消失的时候,就要在游戏里等冰冻效果消失后,再种植一个冰冻豌豆,冰冻一下僵尸,然后返回CE搜索一次增加的数值:

在这里插入图片描述

咱们直接把上图这个883改成1看看:

在这里插入图片描述

我们发现冰冻效果立刻消失,而且数值变成了0,我们发现0的话就是正常的状态,如果我们给这个地址写入一个数值999的话:

在这里插入图片描述

在这里插入图片描述

这个数值就会倒数,就是冰冻状态的倒计时,当这个倒计时为0的时候,冰冻效果消失。

在这里插入图片描述

种一个冰冻豌豆,击中僵尸以后会出现两个指令:

在这里插入图片描述

在这里插入图片描述

我们观察发现,esi和edi的地址值都一样,而且我们看到这两条指令前面的计数,第一条指令是1,第二条指令是19,第二条指令是倒数的:

在这里插入图片描述

我们看到这两条指令前面的计数,说明第一条指令记录的是攻击了几次,第二条指令在倒数;
我们把找到的地址的数值改为500:

在这里插入图片描述

回到游戏中,我们观察到,在射出炮弹还没碰到僵尸的时候,这个500数值会不断地减少;
而当炮弹攻击到僵尸以后,这个数值会变成比500大的数值(从1000开始减少):

在这里插入图片描述

所以正常来说咱们应该选择第一条汇编指令,记录一下该指令的地址:

在这里插入图片描述

在CE中解除附加游戏,到OD中附加该游戏,转到该地址处:

在这里插入图片描述

实现功能我们在下节课再讲。


30、全屏减速第二课

在这里插入图片描述

在这里插入图片描述

咱们先搜索僵尸的血量,这种僵尸的血量是270:

在这里插入图片描述

种一个冰冻豌豆,打中了僵尸两下,还剩下230:

在这里插入图片描述

找到后锁住血量,然后右击该地址,附加CE调试器,找出是什么改写了这个地址:

在这里插入图片描述

然后回到游戏让炮弹打中僵尸,出现一条汇编指令:

在这里插入图片描述

这个是减血,我们看反汇编代码往上看,找到sub之类的减的指令:

在这里插入图片描述

在这里插入图片描述

EDI的值0xD2的十进制是210,正好是僵尸当前的血量(由于我们把血量锁定住了,所以需要先取消,才能更好的观察僵尸血量变化):

在这里插入图片描述

在这里插入图片描述

EDI的值0xBE的十进制是190,正好是这个僵尸当前的血量,而这个指令是mov传送指令,咱们把EBP的值0C561AE8复制,手动加入地址:

在这里插入图片描述

这个地址正好保存的是僵尸的血量。

在这里插入图片描述

把这条汇编指令的地址记录一下:

在这里插入图片描述

血量那个地址如果不加C8的话我们看看它是什么:

在这里插入图片描述

在这里插入图片描述

我们看到0C561AE8这个地址保存的数据跟基址006A9EC0保存的数据是一样的,所以0C561AE8这个地址可以作为这个数组的起始位置,可以暂时理解为僵尸的临时基址(当然这种说法是不正确的,暂时先这样理解);
咱们把0C561AE8这个地址作为内存扫描选项的起始地址:

在这里插入图片描述

在这里插入图片描述

观察这块内存区域的变化,跟之前操作是一样的:

在这里插入图片描述

给僵尸的血量改大一些:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

把这个地址复制一下,粘贴到内存扫描选项的结束那里:

在这里插入图片描述

在这里插入图片描述

然后回到游戏,在射出炮弹还没打住僵尸的时候,继续搜索未变动的数值;
再回到游戏,炮弹打住僵尸变成冰冻状态了以后,搜索变动的数值:

在这里插入图片描述

在这里插入图片描述

我们把它的数值改为1,僵尸的冰冻状态就消失了,恢复为正常状态了:

在这里插入图片描述

僵尸一挨冰冻炮弹,这个数值就又变为从1000开始倒数了:

在这里插入图片描述

如果我们把这个地址锁定了以后,它就永远是冰冻状态了;锁定为0的话,就是冰冻豌豆打中它,它也会立刻恢复为正常状态(CE不断的写入0)。

在这里插入图片描述

这种方法比较重要,在以后分析数据的时候,这种方法可以分析出很多相关的数据;
前面讲的自动收集阳光也是用这种方法来找到相关数据的;
包括玉米投手(投出的奶油打中僵尸以后,僵尸会不动了),打中以后它的数据也会一直减少,所以用这种范围搜索方法,根据僵尸的基址,找到这个范围,搜索变动的数值,也是一样。


31、全屏奶油的找法

这节课复习上节课讲过的范围搜索状态,找玉米投手的奶油定住僵尸的状态相关数据。
先找到僵尸的血量,等僵尸出现以后,搜索270,种植一个豌豆,打僵尸一下,再铲除这个豌豆,搜索250:

在这里插入图片描述

我们上节课说了,僵尸的那个临时基址加上C8就是僵尸的血量,咱们把僵尸血量的地址搜到了以后,直接减去C8就是僵尸临时的那个基址,可以作为数组的起始地址用来分析游戏数据;
所以咱们不必每次都附加CE调试器,找出是什么改写了这个地址,咱们只要记住偏移量就可以了,偏移量才是固定的。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

咱们把僵尸当前血锁定,并再复制一份,并将地址减C8,得到的就是当前这只僵尸的临时基址:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

现在变化的是上图这几个位置,然后咱们种植两个玉米投手,因为只有投出大个的奶油才能定住僵尸:

在这里插入图片描述

当大个的奶油投出去了以后,尤其当大个奶油定住了僵尸以后,咱们注意观察内存区域的变化:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

咱们把这个地址复制一下,然后把游戏中的玉米投手都铲除掉,然后粘贴到内存扫描选项中的结束那里,起始那里需要手动输入僵尸当前的临时基址:

在这里插入图片描述

在这里插入图片描述

在没种植玉米投手的时候,搜索未变动的数值,种植1个玉米投手后,再次搜索未变动的数值,再种植两个玉米投手,在投出大个奶油定住僵尸后,搜索变动的数值:

在这里插入图片描述

回到游戏中,铲除3个玉米投手,回到CE发现数值一直在不断地减少,直到为0,僵尸恢复正常:

在这里插入图片描述

咱们给数值改为555:

在这里插入图片描述

再改成999,这个僵尸就走不动了:

在这里插入图片描述

在这里插入图片描述

这个地址怎么来的呢?咱们用这个地址减去基址0C55DAE8,得到B0:

在这里插入图片描述

在这里插入图片描述

咱么可以再找另外一只僵尸:

在这里插入图片描述

回到游戏让豌豆打中它一下:

在这里插入图片描述

在这里插入图片描述

这个血量地址减去C8就是当前这只僵尸的基址,然后加上B0,就是当前僵尸是否被奶油击中状态的地址,咱们把这个数值改为999:

在这里插入图片描述

在这里插入图片描述

现在出现了一个撑杆跳僵尸,它的血量咱们不知道,可以先搜索未知的初始数值:

在这里插入图片描述

种植一个土豆挡住撑杆跳僵尸,种植一个豌豆(攻击力20)打中这个僵尸一下:

在这里插入图片描述

又打中了一下:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

这就实现了把一个僵尸定住的功能。


32、全屏减速的实现

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在游戏开始的时候,这局僵尸都给你列出来了,有一种方法,你可以把这些僵尸的基址都遍历出来,用循环把每只僵尸的基址都遍历出来,写入冰冻状态的数值,但这样的话比较麻烦,如果僵尸特别多的话,你的程序可能会不准,或者程序有可能崩溃掉,那怎么办呢?

第一步还得先找到冰冻状态的传送指令,僵尸的基址+AC就是冰冻状态。

在这里插入图片描述

在这里插入图片描述

这个基址加上C8就是这只僵尸当前的血量:

在这里插入图片描述

如果不加C8就是当前这只僵尸的临时基址,加上AC就是它的冰冻状态:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

复制这条指令的地址,剥离CE附加,到OD中转到该地址,这是一条传送指令,下个断点,看一下数据。

实现方法就是,找到这个僵尸的基址,然后加上AC,往这个地址写入一个数值,那么这个僵尸的状态就变成冰冻住了。

在OD中观察eax值的变化,如果这个数值不是很大,你又不是一直在写入的话,僵尸就会恢复正常状态了,那怎么办呢?
僵尸肯定会移动,它肯定有一个基址,加上有一定量的偏移能够得到僵尸当前的坐标,所以说只要僵尸移动,咱们就把这个基址记录下来,咱们跳转走,把这个基址加上AC,写入一个数据以后,咱们再给它跳回来就实现了冰冻。

用CE找到僵尸当前的坐标,未知的数值,一移动,就搜索减少(因为坐标原点是屏幕的左上角,从右往左移动坐标x的值肯定是减少),多次搜索后把00400000小的地址都删除,选那些大的数值,类型是float,僵尸的移动是在一条线上移动,找到后给它的数值改一下来测试;
右键找出是什么改写了这个坐标,找到僵尸坐标减少的关键指令,复制该指令地址,转到OD该地址处下断点;
我们可以看到,esi+2C就是当前僵尸的坐标的地址,咱们把esi的值复制到CE里验证一下,esi的地址值加上2C,可以看到这个就是当前僵尸的坐标,+c8就是血量,+ac就是冰冻状态(写入一个数值999)。

在这里插入图片描述

在这里插入图片描述

咱们怎么修改呢?
因为咱们在这个位置直接修改代码,写入数值999的话,位置不够,字节会超出;
所以咱们首先要找到一个空白位置,OD中的Strong插件有一个申请空白内存的,但是申请的内存都不可以使用,你只要游戏一关,这个地址就没了,要么有可能就被占用了,因为这些地址都是临时申请的;
咱就自己往下找一片空白的地址,或者程序开头(00400000)后面那里找一个空白位置。

  • 跳转到空白位置(将jnz改为jmp空白地址,记住勾选使用nop填充);这个空白位置要挂有物理页,否则会崩溃;
  • 在空白处写入冰冻状态;咱们第一个冰冻状态的基址是edi,咱们移动坐标的时候找到的它的基址是保存在esi,所以说这个位置不能使用edi了,edi加上2c偏移肯定不是僵尸当前的坐标,因为edi根本就不是僵尸的基址, 僵尸的基址是esi,所以第一个修改是esi;第二个修改是eax,把eax改成其他数值0x3E7(十进制为999);分析原地址处的指令执行逻辑,将相关指令搬到空白位置那里(原来是什么被修改了,在空白位置这里就写什么),并在最后jmp跳回原地址后面未修改指令那里;
    僵尸只要一移动就跳转到咱们空白位置,在空白位置写入999(十六进制是0x3E7)这么一个状态。

记录一下正常的字节集,以及修改后的字节集,空白位置的字节集也要记录。

在这里插入图片描述

僵尸一出现肯定会移动,移动了就得到了当前僵尸的基址esi,基址加2C就是僵尸坐标,只要一移动就跳到空白位置写入冰冻状态(数值999),原来是什么指令,该怎么写还怎么写,写完了以后,如果jnz跳走了就跳走了,如果没跳走就直接跳回原位置后面未修改的指令那里接着执行。
就相当于,这个jnz跳转和cmp之间多出了写入状态的这么一个指令,实现让僵尸一移动就是冰冻的状态。


33、全屏奶油的找法

在这里插入图片描述

在这里插入图片描述

实现方法都是先找到僵尸移动的坐标,然后跳转过去:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

僵尸就不会移动了,但是我们发现这个奶油并不是很好使,因为僵尸刚出来的话,最右边都看不到这些僵尸了(被定住了移动不了了),豌豆射手也不发射子弹了。

其实也可以改进这种情况,就是说当僵尸当前坐标读出来以后,当僵尸的坐标走过了某个坐标值的时候,咱们再让它写入冰冻数值就行了;
也就是空白位置的指令,加入一个条件判断逻辑就行了。


34、全屏减速、奶酪的选择性实现

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

咱们上次改的是这个位置,只要僵尸一移动就跳转到:

在这里插入图片描述

在这里插入图片描述

在这个空白位置写好功能了以后,原来是什么这还写什么:

在这里插入图片描述

然后再跳回之前的位置:

在这里插入图片描述

在这里插入图片描述

这里只是说一下,并没有写入任何的状态,只是演示一下上节课的方法。

在这里插入图片描述

在继续往下执行。

在这里插入图片描述

这里直接把相应指令写到空白位置看看效果:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

那么如何实现又能冰冻、又能奶油定住僵尸呢?在你关闭冰冻的同时,奶油仍在呢?
因为如果你把所有功能写在一起的话,要关就所有都关,要开就一起开:

在这里插入图片描述

怎么给它们分开实现呢?
不用死心眼,可以在下图选中位置继续修改(JMP跳到一个空白位置)(也可以再往下某个位置修改):

在这里插入图片描述

先把要修改的指令都复制并记录一下:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

再把之前原位置处复制的那个JE的指令写到这里:

在这里插入图片描述

这里要注意,如果je指令条件不满足、不跳的话,还得跳回原来位置fld那条指令那里,从fld指令往下继续执行,所以这里我们JMP到0052AB4E位置:

在这里插入图片描述

在这里插入图片描述

但是我们测试发现没有实现功能,这是怎么回事呢?
原来是上面减速那里,如果jnz条件满足就跳走了,跳到0052ABE8位置那里,把应该要执行的0052AB4D、0052AB4E那部分代码都跳过去了:

在这里插入图片描述

在这里插入图片描述

如果jnz条件没跳走的话,就会按照我们所想的继续执行改奶油的执行。

所以我们要在这里做个双保险,要在上图0052ABE8这里进行修改,先把上图选中部分复制记录下来:

在这里插入图片描述

当然你不能直接跳转到改奶油那里,那样又判断、又跳转回去的,程序就乱了;
所以你应该再找一片空白的位置:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

我们要修改0052ABE8位置处的指令(4个字节)为JMP 00400C08(5个字节),就会导致下面的jnz指令被破坏(0052ABF2位置处的fld指令完好无损):

在这里插入图片描述

在这里插入图片描述

所以要把上图的jnz指令也写到空白位置2那里:

在这里插入图片描述

在这里插入图片描述

现在程序的流程就是:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

这是正常的流程。

如果空白位置1那里减速的jnz指令生效跳走了的话:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

比如咱们如果不要减速,把代码恢复回去的话,也不影响改奶酪的功能:

在这里插入图片描述

这个看起来有点乱,就是说为什么跳了两次呢?原因就是当两个功能都实现的时候呢,关键是在下图选中的指令位置:

在这里插入图片描述

这个jnz指令这里要分两种情况,jnz是上面的cmp指令的结果不是0的话则跳走,它如果跳走的话就直接把咱们下面的改奶酪部分的指令都隔过去了,肯定就修改不了奶酪的状态了,如果没跳过去那么自然就执行咱们修改的指令了,可以正常修改;
所以说,如果跳走的话:

在这里插入图片描述

咱们还要跳到00400C08空白位置2那里改奶酪。

在这里插入图片描述

如上图所示,两个地方都是改奶酪(双保险),这样保证了jnz跳或不跳都可以执行到改奶酪。

如果让减速生效的话,流程为:

在这里插入图片描述

在这里插入图片描述

这里的jnz就是刚才所说的那条指令,分两种情况,所以要做双保险;
恢复的话也要注意这种跳转,也要恢复两处位置的指令。

这节课主要就是讲了一下两个功能的同时实现,和功能的分别实现。


35、CALL寻找植物攻击力

在这里插入图片描述

由于攻击力是不会变得,所以只能通过找CALL来找到植物攻击力,通过僵尸减血来找到关键CALL。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

复制减血指令所在的地址并记录下来,到OD中转到该地址处:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

我们看到这个CALL有3个参数,咱们进入到这个CALL里面看一下它的返回值:

在这里插入图片描述

所以第一层这个CALL不是,因为植物攻击力的话应该会压入一个参数。

咱们再看第二个CALL:

在这里插入图片描述

在这里插入图片描述

咱们看到第二个CALL只压入了1个参数,咱们直接进去看一下返回值:

在这里插入图片描述

这个4就说明第二层CALL压入了一个参数,标记一下第二层CALL:

在这里插入图片描述

再看第三层CALL:

在这里插入图片描述

在这里插入图片描述

这一层CALL没有返回值,所以肯定不是植物攻击相关的。

在这里插入图片描述

上图第四层CALL带有1个参数,也可能是。

在这里插入图片描述

上图带有问号的CALL,这种就可以直接不看。

没有返回值的CALL我们直接就过滤掉。

这样咱们把之前的断点删掉,在第2层和第3层CALL上面的push参数那里各下一个断点:

在这里插入图片描述

在这里插入图片描述

然后运行游戏后直接断下来了,我们要看一下压入了什么内容:

在这里插入图片描述

我们看到ebx是一个地址,这个CALL是把一个地址压进来了,这个CALL不是植物的攻击力;
回到游戏继续运行,当炮弹打中僵尸后OD断下:

在这里插入图片描述

edx的值0x14,它的十进制是20,所以这个就是植物攻击CALL;
咱们在这个CALL上下一个断点:

在这里插入图片描述

断下来以后,鼠标右击修改堆栈中所压入的数值0x14为0x128,让它的攻击力变成296,取消这个断点运行游戏,发现僵尸直接就被打死了,所以就可以认定这个所压入的edx里的数值就是植物攻击力;
然后我们要找edx的来源,我们看到[ecx*4+0x69F1C8]就是一个数组,在这里下个断点:

在这里插入图片描述

我们看到ecx的值是0,所以豌豆射手的攻击力就是直接把0x69F1C8地址里面的内容;
咱们打开CE直接搜0x69F1C8这个地址,发现搜不到,那么就把这个地址手工加入地址:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

我们看到这个地址是一个模块地址,所以这个地址是一个固定的地址,可以说这个地址保存的就是豌豆的攻击力。

咱们把OD解除附加,到CE里把僵尸血量的地址搜索到:

在这里插入图片描述

把豌豆攻击力改为1,这样就可以通过僵尸的血量观察到减少值。

在这里插入图片描述

可以看到打一下僵尸减1滴血,那么这个地址就是豌豆射手的攻击力,把这个数值改成比较大的数值1000的话,那么僵尸直接就被打死了;
所以通过这种方法就可以找到其他植物的攻击力。

后面我们还会讲全屏秒杀、聚怪(吸怪到一起)、种植CALL的查找与调用等等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/22472.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(Transferrin)TF-PEG-DBCO/TCO/tetrazine 转铁蛋白-聚乙二醇-二苯基环辛炔/反式环辛烯/四嗪

产品名称:转铁蛋白-聚乙二醇-二苯基环辛炔 英文名称:(Transferrin)TF-PEG-DBCO 质量控制:95% 原料分散系数PDI:≤1.05 存储条件:-20C,避光,避湿 用 途:仅供科研实验使用&#xff0c…

Android App开发动画特效中插值器和估值器的讲解以及利用估值器实现弹幕动画实战(附源码和演示视频 可直接使用)

需要图片集和源码请点赞关注收藏后评论区留言~~~ 一、插值器和估值器 插值器用来控制属性值的变化速率,也可以理解为动画播放的速度,默认是先加速再减速。若要给动画播放指定某种速率形式,调用setInterpolator方法设置对应的插值器实现类即可…

Spring Boot 分离配置文件的 N 种方式

今天聊一个小伙伴在星球上的提问: 问题不难,解决方案也有很多,因此我决定撸一篇文章和大家仔细说说这个问题。 1. 配置文件位置 首先小伙伴们要明白,Spring Boot 默认加载的配置文件是 application.properties 或者 application…

【云计算大数据_牛客_Hbase】选择/判断——Hbase

1.Hive 1.下面关于Hive metastore的三种模式的描述错误的是() Derby方式是内嵌的方式,也是默认的启动方式,一般用于单元测试local模式中,使用MySQL 本地部署实现metastoreremote模式为远程MySQLDerby方式在同一时间只能有多个进程连接使用数据库 2. 百度文库 2、代码sel…

Android App开发中集合动画和属性动画的讲解及实战演示(附源码 简单易懂 可直接使用)

需要图片集和源码请点赞关注收藏后评论区留言~~~ 一、集合动画 有时一个动画效果会加入多种动画,比如一个旋转一边缩放,这时便会用到集合动画AnimationSet把几个补间动画组装起来,实现让某视图同时呈现多种动画的效果 因为集合动画和补间动…

Jetson Orin使用Yolo5开源数据集训练模型检测口罩

软硬件环境: 乌班图 20.04 64位蟒蛇与 3.8.10英伟AGX Orin库达11.4PyTorch1.12YOLOv5-6.1感谢开源数据集下载地址 正常都是自己收集完了训练,今天就省略这个步骤了。 如果想自己制作看下面的流程。 软硬件环境搭建教程链接 刷机的话使用官方教程或者…

DNS协议

DNS服务器 人类更喜欢记忆主机名,而路由器更喜欢定长的、有结构层次的IP地址,DNS应运而生:DNS能进行主机名到IP地址转换的目录服务。 DSN是: (1)一个由分层的DNS服务器(DNS server)实…

元数据管理-解决方案调研二:元数据管理解决方案——Saas/内部解决方案(2)

Saas/内部解决方案 2.5、Azure Purview 地址:Azure Purview - Unified Data Governance Solution | Microsoft Azure 特点: 1、创建跨整个数据资产的统一数据地图,为有效的数据治理和使用奠定基础 1.1、自动化和管理混合源的元数据&#xf…

重打包实现frida持久化 笔记

修改Dex Using Frida on Android without root 修改so [翻译]在未root的设备上使用frida 2个方法本质都是通过重打包让app自己加载frida-gadget.so (但感觉没有谁家app会让人轻易重打包吧。。。) apktool d org.telegram.messenger_4.8.4-12207.apk -r…

Tomcat配置SSL证书别名tomcat无法识别密钥项

Tomcat配置SSL证书一直启动失败,主要问题如下: java.io.IOException: Alias name tomcat does not identify a key entry at org.apache.tomcat.util.net.jsse.JSSEUtil.getKeyManagers(JSSEUtil.java:280) 别名tomcat无法识别密钥项,是因…

STM32单片机远程控制大棚种植系统

想要更多项目私wo!!! 一、电路设计 ​​​​​系统示意图硬件系统 系统由五个单片机系统组成的,其中51系列的单片机四个,STM32F407单片机一个,各个子系统之间通过NRF24L01无线模块进行通信。 系统硬件组成框图​​​​主控制板主要由STM32…

【VuePress2.0】快速开始(不用)

文章目录VuePress2.x1.1 安装安装VuePress2.x(手动安装)1.2 VuePress2.x 基本操作VuePress2.x主题2.1 安装VuePress2.x主题(yarn)2.2 报错解决(没效果,不用看)2.3 VuePress2.x主题 基本操作VueP…

Java基础深化和提高-------IO流

目录 IO流技术介绍 什么是IO 什么是数据源 流的概念 第一个简单的IO流程序 IO流的经典写法 IO流新语法经典写法 Java中流的概念细分 按流的方向分类: 按处理的数据单元分类: 按处理对象不同分类: Java中IO流类的体系 Java中IO的四大抽象…

CleanMyMac X真正好用的Mac电脑系统优化软件应用工具

最用户友好的Mac问题修复程序。删除系统垃圾、不需要的应用程序和恶意软件,并调整您的Mac以获得最高速度。对于速度较慢的计算机,CleanMyMac就能立即使用。 CleanMyMac2023之所以能够获得众多Mac的老用户们的喜爱,是因为其有着非常强大功能提…

数据可视化之大数据平台可视化

一 前言 在简化数据量和降低大数据应用的复杂性中,大数据分析发挥着关键的作用。可视化是其中一个重要的途径,它能够帮助大数据获得完整的数据视图并挖掘数据的价值。大数据分析和可视化应该无缝连接,这样才能在大数据应用中发挥最大的功效。…

nodejs+mysql航空飞机票销售酒店预订系统vue

(1)对机票预订管理系统进行需求分析、确定所需要的模块;建立数据字典、数据流等;书写可行性分析和需求分析说明书。 (2)对机票预订管理系统进行概要设计:建立软件体系结构,画出用例图、E-R图等;书写数据要求说明书和各…

【雷达通信】阵列信号处理(Matlab代码实现)

👨‍🎓个人主页:研学社的博客 💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜…

聊聊Go里面的闭包

以前写 Java 的时候,听到前端同学谈论闭包,觉得甚是新奇,后面自己写了一小段时间 JS,虽只学到皮毛,也大概了解到闭包的概念,现在工作常用语言是 Go,很多优雅的代码中总是有闭包的身影&#xff0…

嵌入式图形开发框架Qt——让牙科手术开始迈入机器人时代

Neocis软件工程总监,Jim Tieman: “我们Neocis是一家致力于提高科医生能力和促进病人护理的牙科机器人公司。之前我们有一个Microsoft Foundations Class (MFC)的应用程序,由于现在团队擅长MFC开发的技术员并不多,维护起来也很费劲。之前这个…

AST 初探深浅,代码还能这样玩?

AST 听起来好像是个很新的东西,那么具体有什么用,好不好用就在这篇文章中找到答案吧~ 我们简单将这个词拆分抽象、语法、树,如果我们能够顺利将这个词拆分,那么我们也就掌握了其核心所在 抽象:抽象的反义词是具象&…