您的位置:首页 > 编程语言 > C语言/C++

游戏辅助原理与制作第八课--------植物大战僵尸种植植物CALL的寻找思路

2018-03-01 01:09 726 查看
    从本节课开始,就开始讲解CALL调用挂的内容了。首先我们了解一下什么是CALL。CALL是一个汇编的指令,你可以使用他来调用执行某个子程序。在高级语言里,我们把CALL称做函数/方法调用。在植物大战僵尸里,当我们种植一棵植物的时候,肯定会调用某个函数,那么当我们找到这个函数时,我们就可以直接在外挂上实现种植某种植物的功能。
    那么我们怎么去寻找种植植物的CALL呢?当我们点击植物面板上点击某个植物,并种植到地面上时,它就会调用种植植物CALL,调用这个CALL时,他会读取所选中的植物作为参数。所以,我们得先找到标记所选中植物的变量的地址。我们先打开游戏,并用CE进行加载:
    首先,我们搜索未知初始化的数值。接着我们点击一棵植物,但是不要种下,这时候我们已经选中了某种植物,搜改变的数值。然后我们再重新选择这个植物,然后搜索未改变的数值,持续几次操作,排除一些不符合条件的结果。接着,我们选择另一棵植物,然后搜索改变的数值,然后同之前操作,重新选择这个植物,搜索未改变的数值,连续几次。然后我们搜索另一棵植物,搜索改变的数值,持续该操作,一直排除到只有几个结果为止:



我们发现,最后有12个结果排除不掉。首先前面五个地址的值作为植物序号数值太大,不太符合,我们优先考虑后面的。我们持续选择不同的植物:豌豆射手,向日葵,樱桃炸弹,发现有两个地址是从0、1、2有顺序的变化的,比较符合我们期望的值,我们先把他们拉下来。我们发现,这两个地址的值变化都一模一样,我们选取其中一个进行分析。
    我们选中一个地址,右键,查找访问该地址的代码(调用植物CALL时,需要得到已选中的植物作为参数),这是我们发现已经有一条代码在不断对它进行访问,可是这时候我们还没有开始种植,所以这条代码不是我们需要的。这时,我们把选中的植物种下去,就会发现有三个结果多了出来,而且访问次数只有一次(我们调用CALL的时候它才进行访问),符合我们的预期:



我们把这三条代码的信息,分别都记录下来:







首先,对于这三条指令,前面两条都是把这个地址的值赋值给寄存器,也就是读取这个地址的值。最后一条是把寄存器赋值给这个地址的值,也就是把值写入寄存器。所以,最后一条并不是我们需要的,我们可以直接排除。
    我们开始分析前面两条代码。这时我们可以关闭CE,打开OD了。我们先看到第一个代码所在的地址:
    


我们看到,这条代码,下面有一个CALL,那这是我们需要的植物CALL地址吗?我们看到,调用这个CALL,并没有传入任何参数。而对于一个植物CALL,我们调用它时,除了需要传入所选中的植物之外,还需要传入所种植的坐标。所以,这个并不是我们需要的植物CALL。我们查看下一条代码:



在这句代码下面,我们看到了一个CALL,且调用这个CALL之前,至少传入了五个参数(这里push四个,有一个是用寄存器进行传递的:mov eax,dword ptr [local.35])。所以,这很可能就是我们要找的CALL。我们在第一个PUSH处打上断点,开始调试。当我们种下一棵植物的时候,OD就会断下来,所以我们在第一行第二列这里种一棵豌豆射手。这时我们可以按F8(单步步过)进行逐句调试,并记录下寄存器的值:
push    edx    ;edx=-1
push    eax    ;eax=0
mov    eax,    dword ptr    [local.35]    ;执行完后,eax=1
push   edi,    ;edi  = 1
push   ebp,   ;ebp = 1E639900
这时,我们让程序跑起来,这次我们还是种植同一个位置,只不过我们换一种植物:向日葵进行种植。(如果你没有铲子铲掉原来的植物的话,就重新开始吧)。种植完后,我们再次记录下参数的值:

push    edx    ;edx=-1
push    eax    ;eax=1
mov    eax,    dword ptr    [local.35]    ;执行完后,eax=1
push   edi,    ;edi  = 1
push   ebp,   ;ebp = 1E639900
这时,我们对比之后发现,在push eax时,前者的eax是0,后者的eax是1,而我们这两次的唯一变动的量就是所选中的植物。所以我们可以发现:push eax就是在传入所选中的植物这个参数,且0代表豌豆射手,1代表向日葵。这样看来,游戏的植物序号应该是连续的,2就应该是樱桃炸弹。为了验证我们的结果,我们让程序跑起来,再次种下向日葵,不过这时我们把push eax时的eax值修改成3,一个我们植物列表中没有出现过的植物,看看会怎样:





然后,我们让游戏跑起来,看看效果:



我们看到,它种下了土豆墙,而我们的植物列表里都没有这种植物。所以,这也就验证了我们的猜想,push eax是传入所选中的植物作为参数。我们继续研究其它代码。这时我们在第一行第三列里面种下向日葵,并记录参数的值:

push    edx    ;edx=-1
push    eax    ;eax=1
mov    eax,    dword ptr    [local.35]    ;执行完后,eax=1
push   edi,    ;edi  = 2

push   ebp,   ;ebp = 1E639900
对比上一次我们记录的值,我们发现,push edi时,前者的值是1,这次的值是2。前者我们是在第一行第二列里面种植,这次我们是在第一行第三列里面进行种植,所以我们猜想,push edi是传入你要种植的列坐标作为参数。为了验证我们的猜想,我们在第一行第五列继续种植向日葵,只不过我们在push edi的时候,把它的值改成0,看看结果会怎样:



我们看看效果:



我们看到,向日葵被种到了第一列这里,所以,push edi的确是传入我们要种植的列坐标作为参数,且这个值是从0开始的。同理,用同样的方法,你们可以推测的出,mov eax dword ptr[local.35]是传入我们要种植的行坐标作为参数,这里由于文章篇幅的原因,我就不演示了。这样,所选中的植物,行坐标,列坐标我们都搞清楚了。就只剩两个参数我们没有搞清楚。一个时候push edx,一个是push ebp,我们发现,这两个参数在每次调用前值都是一样的,但我们重启之后值是否还一样呢?我们不得而知。为了验证,我们需要将游戏重启,并用OD重新加载:




ba2a
时我们看到,edx还是-1,而ebp是1E244888,和之前的1E639900已经不同了。到这里,我们就知道,edx的值应该是不变的,恒为-1,而ebp的值应该是一个动态地址。所以,为了能动态解析ebp的值,我们应该使用基址加偏移的方式去得到。我们关掉OD,重新打开游戏,用CE进行加载。这里在搜索框里搜索一下这个值。看看它来源于哪个地址:



这里看到有很多结果,我们先选取第一个来研究,我们查找访问该地址的代码:



这时我们看到,有一条代码push ebp和我们的刚才在OD看到的是同一段代码,地址也一样,然而我们现在要找基址,这段代码对我们没用处(有的话我们就在OD找了,何必关了它来到CE呢)。我们需要找的是那种mov ,add,sub那类的指令,而且还是有基址加偏移的。这时我们回到游戏,种一下植物,看看会多出什么结果:



这时我们看到,结果中的确是有一条mov [esp+14],eax的这种指令,但他所处的地址明显不是我们游戏程序里的代码地址。所以,第一个结果不是我们想要的。我们看第二条把,也就是这条:


我们仍旧是查找访问该地址的代码:



我们看到,这里有几条mov指令而且是带偏移的了,但这些地址一直在不断的访问,我们还是想回到游戏中,种植一棵向日葵,看看会不会出现只和这个行为有关的代码:



这时我们看到,多出来的很多结果也全都是偏移量加上768的,那我们就选取其中的一个吧:mov eax,[edx+768]这一条:



edx的值是02A39FD8,我们搜索一下这个值:



我们看到,这里有很多结果,但在结果的下面一点,我们看到几条绿色的地址,这些才是我们要找的。我们看到第一条的地址是006a9ec0,是不是感觉很熟悉?没错,这就是我们找阳光基址时找到的那条地址。所以,其实我们要找的动态地址就是这么来的:[[006a9ec0]+768]。这样,我们就把植物种植CALL的所有参数都弄清了。为了验证是否正确,我们使用代码注入器看看效果,我们打开代码注入器,加载进程,然后写入代码,注入远程代码,看看效果:



我们看到,的确可以调用植物种植CALL了,而且重启后也有效果。然而我们还发现一见有趣的事,我们可以让植物种植在外面,甚至在同一个地方种多个植物,这时为什么呢?因为,检查植物是否可以种植的这些代码并不在这个种植CALL里面,可能在调用它的子程序里,然而它并不管这些,也不管你够不够阳光,就直接帮你把植物种上了。最后,我再总结一下这个CALL的参数:
       push    edx  ;恒为-1
       push    eax  ;要安放的植物种类
       mov     eax,dword ptr [local.35]  ;要安放植物位置的Y坐标
       push    edi   ;要安放植物位置的X坐标
       push    ebp  ;[[006a9ec0]+768]
       call       0040D120  ;调用植物CALL

    到此,我们就分析完了植物CALL,下节课,我们将动手用代码去实现种植植物。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  外挂 辅助 C语言
相关文章推荐