首页
论坛
专栏
课程

[调试逆向] [原创]植物大战僵尸自动拾取物品

ggsuper 2018-1-10 21:35 3789

植物大战僵尸自动拾取物品

一、实验目的

《植物大战僵尸更改阳光产出速度》一文中实现了阳光快速产出,但人工拾取的话手速跟不上产出速度,本文着手解决此问题。
效果图如下:

二、思路

找出游戏中拾取物品call,通过改变程序执行流程不断调用拾取物品call。以拾取阳光为例,当单击掉落阳光时,阳光被拾取,同时阳光收集数量增加。
那么游戏可能执行流程为:单击阳光—>拾取物品call—>增加阳光数量call。据此,先找出阳光数量地址,逆推找出拾取物品call。

三、实现

注:由于之前的植物大战僵尸2010年度版在游戏里取得某一个成就后莫名其妙的崩溃了,我换了个英文版的。
开始,先找出阳光数量地址(过程略)。

OD中数据窗口跟随阳光地址19207FB0,并下硬件写入断点,F9运行,拾取掉落阳光后,断下,取消硬件断点,代码清单如下。

0041E6E0    0188 78550000   add     dword ptr [eax+5578], ecx        ; 增加阳光
0041E6E6    8B88 78550000   mov     ecx, dword ptr [eax+5578]

OD中 Alt+k 显示调用堆栈。如下:

004336EA处调用为增加阳光call。00434188处call为增加阳光call上层call,可能为拾取物品call,同理,004342FF,00415B04均可能为拾取物品call。
先在00434188处下断,回到游戏捡个阳光,断在00434188处。如下:

00434184   /75 07           jnz     short 0043418D
00434186   |8BC6            mov     eax, esi
00434188   |E8 33F5FFFF     call    004336C0

说明此call跟拾取阳光有关,此call无参数,直接NOP掉,回到游戏,捡个阳光,发现阳光可以捡起,但阳光数据不再增加。此处不是拾取物品call。
然后改为在 004342FF处下断,回游戏捡阳光,断下,代码如下。

004342EE    807B 50 00      cmp     byte ptr [ebx+50], 0
004342F2    75 09           jnz     short 004342FD                   ; 捡物品关键跳转,取反后自动捡物品
004342F4    8BFB            mov     edi, ebx
004342F6    E8 55F5FFFF     call    00433850
004342FB    EB 07           jmp     short 00434304
004342FD    8BCB            mov     ecx, ebx
004342FF    E8 CCF8FFFF     call    00433BD0                         ; 捡物品call

此处call无参数,NOP掉,回到游戏,发现已经捡不起阳光了,此处call应该为拾取物品call。向上看, 此call由004342F2处跳转过来执行,将跳转语句取反,回到游戏后发现已经可以自动拾取阳光,经测试,所有掉落物品均可自动拾取。

谢谢各位的支持,祝论坛越办越好!!!

 ggsuper

2018.1.10






快讯:看雪智能设备漏洞挖掘公开课招生中!

最新回复 (13)
wo爱吃大白兔 2018-1-11 10:27
2
支持,可否分享一下给小白做参考呢?
ggsuper 2018-1-11 12:46
3
wo爱吃大白兔 支持,可否分享一下给小白做参考呢?
先学会简单使用CE、OD,然后应该就能看懂了。
wx_会飞的鱼_884364 2018-1-11 15:03
4
一个函数有一个堆栈,难道多个函数可以共用一个堆栈?     
我有点基础
ggsuper 2018-1-11 16:10
5
wx_会飞的鱼_884364 一个函数有一个堆栈,难道多个函数可以共用一个堆栈? 我有点基础
理解这个需要一些简单的汇编基础知识,文中的情况可以理解为在一个函数中调用另一个函数。
奈沙夜影 2018-1-11 18:36
6
wx_会飞的鱼_884364 一个函数有一个堆栈,难道多个函数可以共用一个堆栈? 我有点基础
每个函数有一个独立的栈帧,在x86中不会共用堆栈。
文中所指的是调用堆栈,跟函数所使用的栈帧是两码事。
调用堆栈是一个抽象的概念,你可以理解为每次调用函数就压入该函数,调用结束后就弹出来。
例如ABC表示此时在函数A中调用了函数B,B中调用了函数C
奈沙夜影 2018-1-11 18:39
7
感谢分享,学到了思路~
调用逻辑应该是遍历所有物品,发现谁被点击了就拾取吧。
我刚开始以为是每个物品有一个回调函数呢..._(:з」∠)_
ggsuper 2018-1-11 19:05
8
奈沙夜影 感谢分享,学到了思路~调用逻辑应该是遍历所有物品,发现谁被点击了就拾取吧。我刚开始以为是每个物品有一个回调函数呢..._(:з」∠)_
分析这个的乐趣就是可以不断的猜想,然后去证明猜想是对的。
wo爱吃大白兔 2018-1-11 20:51
9
多谢
热情的菜鸟 2018-1-11 23:00
10
dswkc 2018-1-13 13:18
11
只有周末有时间玩一会这些,楼主用OD和CE完成了此次工作,我试着用CE做了一次,也不算复杂,不再重新开贴,就回复在这里吧
1,取得阳光值的地址(非常简单,此处不赘述)
2,在此地址上用CE的" find out what writes to this addrss " 获得修改此地址的指令,然后进入游戏拾取阳光

3,我拾取阳光一次,得到修改地址如下

4,点击show disassembler 进入memory view,此时显示的就是修改阳光值的指令了。根据楼主贴出来的思路,《有阳光可拾取-拾取-增加阳光》我们应当对调用此指令的指令进行分析

5,分析代码

6,分析结果,此处已经和刚开始的memory view不一样了,在跳转和被call的地方已经有了标注

7,向上翻找到被call的地方,逐一下断,并回游戏拾取,判断出只有004313f8在捡取时被断下,双击004313F8进入(不要点错进到其他指令里)

8,对call语句下断,回游戏拾取,确定被断下


9,补充,call内的内容执行完会retn到调用它的位置,也就是增加完,会回到调用增加指令的位置,因此断下后执行debug内的execute till return 


10,程序回到了调用增加指令的位置,也就是拾取判断了,call xxx+30E40,向上追溯,发现cmp语句,取反后自动拾取



不用OD的原因是不会,哈哈,先学习一些基本的知识后再学习OD吧

贴上ce的脚本,有兴趣的朋友可以试验下(楼主的版本和我的版本不一样,所以有些地方有出入)
上传的附件:
ggsuper 2018-1-13 20:40
12
dswkc 只有周末有时间玩一会这些,楼主用OD和CE完成了此次工作,我试着用CE做了一次,也不算复杂,不再重新开贴,就回复在这里吧1,取得阳光值的地址(非常简单,此处不赘述)2,在此地址上用CE的" ...
OD、CE各有用武之地,我的游戏版本截图、CT文件附上。
上传的附件:
冷风Feng 2018-1-28 22:16
13
初学OD和CE,有时候CE会找不出基址,猜测OD可以找出基址,可是不会OD找基址,咋破
taizhong 2018-2-13 04:07
14
最近僵尸总是出没
返回