前言
阳光,CD都讲解过思路了,接下来我们来讲一下植物的种植条件移除。如不需要向日葵,直接种植双生向日葵,不需要玉米投手,直接种植加农炮。同时也将解除一格只能种一个植物的限制。
此篇是植物大战僵尸篇思路分析的最后一篇,下一篇就会将前面这些功能,通过易语言集成成一个修改器。
PS:我讲的是思路,植物大战僵尸,只是一个例子,大家可以把思路拓展到别的方面去,注重思维灵活。
欢迎文明转载,请注明出处 丸子de爸爸
本文所有技术资料仅供研究,不鼓励任何盗版商用行为
请大家支持正版,支持正版!支持正版!!!
上集传送门
工具
CheatEngine6.7
植物大战僵尸本体
PS:(我使用的是年度版,可以直接解锁所有物品,不然你就自己打到后面去吧)
本次基础概念
内存,一切皆内存,我们操作的全部都是内存。
所有地址相关的概念,都可以理解为坐标,用来给我们做标记的而已。
如果实在搞不明白,你想想指南针为啥指向北边,为啥叫南北,只是定义,只是公认
PS:上面这一段是重复了,但是我觉得还是有必要多重复一下,看多了,大家就印象深刻一点。
线程
可以简单理解为程序是你们公司,线程就是你们这些干活的人,每个人都会干自己手头的活。
想具体的了解,可以自己去看。
汇编知识
ZF(zero flag)
标志寄存器,用来纪录上一次判断的结果是不是为0。ZF=1时,代表上次结果为0。反之ZF=0,上次结果不为0。
JNE (jump not equal)
上一次判断如果不相等,则跳转。
标志位如何理解记忆:
由于汇编中的比较都是两个参数相减,所以不相等,就代表差不为0,也就是ZF=0。
所以ZF=0时候,跳转,ZF=1则不跳转。
add
将两值相加,结果放在前面那个内存中
例:add eax ,ebx 。 eax = 1 , ebx = 2
执行完之后,eax = 3,ebx = 2
setle
用在cmp之后,如果cmp的结果是<=,则赋值为1
例:cmp eax,ebx 。eax = 1,ebx = 2
setle ecx,此时由于eax<ebx,所以ecx = 1
test
两数进行与操作,不存储结果,更改标志位,主要和J**跳转配合使用。
例:test al,al。一般只是判断是不是为0。如果为0,ZF=1;不为0,ZF=0。
这一次就是通过test al,al。改变ZF,再根据ZF的值来决定跳不跳转。
实现步骤
植物种植条件去除
植物种植条件去除需要分为两个方面:
- 允许植物在条件不满足的情况下,被选取
- 允许植物在条件不满足的情况下,被种植下
思路流程图
之前在星际争霸的人口无限制作中,就有分析过思路。这种毫无数据可以作为判断的突破点,可以按照正常逻辑来分析。
根据流程图,发现仍然可以根据阳光是否足够切入,找到阳光的判断地址,继续向上查找,就可以找到相关逻辑。
明显在此处,我们可以先查找到阳光,然后根据阳光的逻辑向前后查找,就可以实现我们的目的。
植物选择条件去除
CE定位关键逻辑
先开一局游戏,随便选择一些植物(记得选几个需要种植条件的)
等出现一个阳光,先不拾取,切换到CE
在CE中先搜索“50”,得到大把结果。
回到游戏中,拾取一个阳光,待阳光数值增加后,再回到CE中搜索"75"
结果只有一条记录,说明成功找到了阳光的内存。
可以随便尝试修改一个数值试试,比如我们改为150。切换回游戏,发现两件事情
- 阳光值变为了150,说明我们找对了地址。
- 有植物变亮,说明植物变亮和阳光挂钩,但是不是由点击控制。推测是由一个线程一直在检测阳光变化。
PS:这里的判断依据是我们直接修改的内存,并没有执行正确的程序逻辑,如果他的变亮是放在获取阳光中判断,就只有在收集一个阳光的时候,会触发变亮。但是现在直接变亮,说明肯定是由一个线程持续监测阳光,一旦满足条件,就更变植物卡片的状态。
根据上面的推论,我们先右键阳光内存,选择“什么访问了地址”
记得上面说的么,一个线程循环监测,所以一定是一直访问,我们在访问里找。
发现只有两条纪录一直在访问,频率有点不一样,一个是很多次,一个很少。都有可能是我们需要的数据。
再次分析已知条件:
- 植物的CD和条件判断是分开的
- 目前植物卡片有10个,将这两个数字都除10,一个700多,一个70多,而且还是几秒钟的数据。
从及时性的理论上来说,我更倾向于第一条记录是我们需要找的逻辑附近。
选中第一条记录,点击“显示反汇编程序”
在选中这一行,按下F5,打断点,并会马上被断点,因为一直在循环嘛。
从add这一行逐行往下分析(因为上面是一个方法,先不看他,优先找最简单的解,找不到再慢慢深入)
5578这个数在之前找阳光基址的时候见过,所以[edx+5578]应该就是当前的阳光地址。
我们来验证一下这个[edx+5578]是不是当前局的阳光地址。
在CE中选择,手动添加地址,将edx+5578输入进去,发现就是150,而且确定之后,地址和我们刚查到的阳光地址是吻合的。
PS:这个值就在反汇编窗口的右边,兄弟们眼睛亮一点哈,双击那个值还能打开编辑框,可以复制。
于是刚才的代码变成了add eax,当前阳光。当前阳光和eax相加,结果放在eax中。
但是eax如果是0,相加没有意义,那eax的赋值在哪呢?看来前面那个方法,就是给eax赋值的。
再来分析,什么情况需要给当前阳光多一个额外值呢?应该都想到了吧,就是拾取阳光的时候。
当拾取阳光的时候,阳光还在向左上角阳光总数飞行的时候,并不会马上加入总数,于是便出现了一个阳光临时值eax。
再看下一行,cmd [esp+04],eax。就是比较阳光临时值和另外一个值,那简单,我们上面的方法,看看这个值是多少。
同样,将esp+04输入到手动添加地址中,发现等于150。那不是没意义,别着急,点确定看看。
因为他这里是和阳光比较,所以肯定不会是阳光,不然这比较就变成了阳光比阳光,闲的。
切换回反汇编窗口,按下F9,让程序再跑一次,发现值改变了,这一次变成了175。
继续重复F9的动作,发现在一组值中间改变:
[150,175,125,100,25,125,200,125,50,50]
观察一下就知道,这些值,就是我们植物卡种植需要的阳光数。
所以esp+04可以看成,种植植物需要的阳光数。
结合下一句setle al。(这个高低位不想解释太多,可以理解就是赋值eax就好,感兴趣自己去看看)
本次断点al的值一定会是0,因为是175(植物种植阳光)>150(当前阳光)
接着往下F8,发现来到了test al,al的逻辑。此时由于al=0,所以ZF=1(不懂翻到上面看看基础)
ZF=1时,下面的JNE的就不会跳转。
汇编流程图
根据上面的汇编分析,我们得到了这样的一个流程图
精简合并一下流程图,变成我们需要的部分
逻辑就很明了了,JNE跳转的部分,就是植物阳光数量满足种植的逻辑。
修改汇编(金钱限制去除)
回到汇编界面,双击,将jne改为jmp,让他一直跳转。即判断一直认为,种植植物的阳光是足够的。
多按几下F9(其实再按一轮就行了),回到游戏查看,发现虽然是卡住的,但是植物已经亮起来了。
说明我们找对了逻辑,也说明之前的推理都是正确的。
记得右键可以建书签,最好建一个,保存当前位置,后面有用哦。
接下来,ctrl+b,删除所有断点,按F9让程序跑起来。等植物的CD都跑好,或者你把无CD开了。
PS:我承认是多余的,但是没办法呀,植物CD都还没跑完,这时候很容易出现回混淆的逻辑。
好,等到CD都好了,我们继续开始,回到刚才打书签的位置。
主要看一下CE中之前手工的植物需要阳光,要符合可以种植哦,别选了那些有前置的。
一路F8,发现,有一行的jnp并没有跳转(这就是为啥前面要等CD跑完,没跑完CD这里会跳走)
由于上面的原因,大概可以确定,这下面的方法就是判断是否点亮的方法。
F8过去之后,F7进入方法(蓝色选中那一条)
去除植物选择限制
进入方法,发现一大堆判断和跳转,其实从代码结构大概就可以确定,这里是一系列的过滤。
如果没跳转,就会直接ret掉,说明这里是多重过滤。
按照以前的老方法,记录满足种植条件的植物的正确跳转,添加注释normal。
PS:其实这里一看就知道是跳到最后,明显都是过滤的,没啥赋值。
翻到最后,发现啥也没做,就单纯的是过滤,那没的说,全部PASS就行了。
最终跳转的地址为蓝标那一行,所以现在要做的,就是从第一个判断直接跳转过来就行了。
PS:这里的判断很草率,是因为其实我自己有做测试。正确的方法应该是,先用正常的植物跑一圈,测试一下逻辑。然后用不正常的植物跑一圈,对比有啥不同,定位到关键跳转,再忽略。
这里成功,只是根据经验和数据结构做的一个猜测,生效了,所以直接这么写了。
到最后一个跳转的位置,双击,记录下最终跳转的地址。
回到方法第一个跳转,将跳转改为"jmp 你最终的跳转地址",点确定。
ctrl+B,删除所有断点,F9使程序运行。瞬间全亮。
(别忘了回书签那把之前金钱那个jmp改回之前的jne,要不然钱不够也会亮的)
植物种下逻辑判断去除
CE定位关键逻辑
虽然已经变成亮的了,但当你选择并尝试种植时会提示如下。
接下来开始破解种下的逻辑判断。
根据最上面的流程图(不记得的目录可以跳过去)
可以得知我们还是需要根据金钱来查找这段逻辑,但是这一次,我们需要观察的,是"改写"。
因为植物种植成功的标志就是扣钱。
选择阳光地址,并选择“什么改写了这个地址”
回到游戏,随便种一个植物,需要种植成功的那一种,然后查看记录。只有一条,完美,点击显示反汇编。
反汇编界面,定位到这个位置。上一行代码,是一个sub...扣除阳光的逻辑。
在这里打一个断点,然后回到游戏,再种一个植物。
PS:这里直接把sub这行代码后面的ebx改为0,种植就不花钱了。试试看来一波AA脚本?
进入断点,按F8跑到ret。再按一下F8,返回上一层方法,就在蓝标位置,往上翻,发现有一个外层的jne,找到最外层的jne,断点。F9让程序运行起来。
为啥这么做,是因为我们的断点位置,是扣除金钱,然后扣除金钱已经是在判断都已经完成之后运行的,所以我们需要往前找。具体不懂,目录回到思路流程图去看看。
回到游戏,再种一颗植物。进入了jne的断点。
老方法,用normal标注出所有正常逻辑的跳转。结果发现,正常逻辑没有一个需要跳转的。那就按F9恢复游戏。
再种植一个需要条件才能种植的植物,结果居然连断点都没进,说明啥,说明这里还是在判断的后面。
于是再种植一颗正常的植物,进入jne断点之后,按下Shift+F8,执行到上一层的返回。
PS:如果第一下shift+F8到了第一个断点,再按一次就行
最终到的位置如图,运行的位置在蓝标,前面又有一个跳转je。给je打上断点。按F9恢复游戏
再次选择一个植物,发现一点选植物,马上就进入了断点,这次靠谱。
当前状态跳转是生效的,说明不执行下面这一段代码,然而之前我们的断点说明,里面的代码是会在扣除阳光之前执行。
所以能够说明,这个判断,是用来判断当前鼠标是按下还是释放,而下面这段的代码,就是植物种植的逻辑。
按下F9先让游戏运行起来,随便找一个地方,把植物种下。
发现再次进入了断点,而且这一次没有跳转,说明将会执行下面的逻辑,也说明了下面确实是种植的逻辑。
F8步进到第一个call方法,F7进入方法里查看。
在方法里,老方法,将每一个跳转的地方标注一下normal。
一直走到跳出方法,然后F9恢复游戏运行。再重新种植一颗不符合种植条件的植物,进行对比。
对比后发现,在蓝标处,正常种植会跳转,但是错误的植物没有跳转。
于是将这里改为jmp。让他一直跳转。再按F9运行起来。
回到游戏,发现已经成功种植了。说明我们修改成功。
PS:而且你会发现,已经可以多重种植了...
植物重叠种植
由于不是一天做的,我的游戏中的数据,植物会不一样,但是不影响。
按照上面的方法其实已经可以达到重叠种植的效果,但又会有副作用,你的植物仍然不受限制,这不是我们希望的。
那我们可以继续细化逻辑,来找到一个只打开重叠种植的判断位置。
PS:这一段是补充的,本来是没打算写这些,正好有个兄弟 @天空の幻象 提问,想着回复不如补充完整。
CE定位逻辑
前面我们将下图蓝标那一行,改为了jmp直接跳转。就已经实现了自由种植(植物又不受限制,又可以重叠种植)
原本的跳转是je,本来是有一个筛选功能的,那说明我们只需要让我们重复种植一直通过筛选,就可以了。同理,也可以将无限制种植和重复种植给区分开,你愿意细化可以慢慢细化。
那怎么要去通过筛选呢?往代码上面看,上一行是test eax,eax。判断eax是不是0,那eax肯定又有赋值了,再往上一行,一个方法。那思路很明显,就是这个红标的方法,通过一些判断,给eax赋值,然后根据eax的值来进行一个跳转。
所以我们只需要进入红标方法,然后找到跳转的分歧,就可以解决。
回到游戏,正常种植一颗植物。进入到红标方法(先F8,等运行到方法本身,按F7进入方法),还是老方法,每一个跳转的地方,都注释上normal,你想注释别的也行。一直F8最终会回到方法下一行。按下F9,让程序运行。
回到游戏,选择一颗植物,种在已经有植物的地方,会直接进入断点。比较红标方法中,和之前正常逻辑跳转不同的地方。
成功找到一个本应该跳转,但是没有跳转的地方。将他改为jmp,搞完收工。
同时也不会出现我随便种一个向日葵,可以到处乱种双生向日葵的情况了。
PS:你要是还能种下,代表之前去除种植限制的那个jmp,你没改回原本的je。
到此,植物重叠种植逻辑完成。
总结
在不知道如何入手的时候,可以先思考正常逻辑,从正常逻辑中,找到可以搜索到确定数据的判断,然后慢慢查找到自己想要做到的功能。
学习做一下AA脚本非常简单,而又非常实用,建议大家研究一下,具体方法第一篇中有详细介绍。
PS:因为太简单了, 真的不想再写一遍了,大家体谅哈,谢谢观看。
第一篇
下一集