查找产生僵尸的CALL
使用CE搜索地图上僵尸的数量,找到保存僵尸数量的地址,然后CE附件找到增加僵尸数量的语句,因为产生僵尸后一定会增加僵尸的数量。
CE附加找访问该地址的代码
使用OD在 0043678F - 01 46 10 - add [esi+10],eax 下断点
产生僵尸时,断下,查看栈
在反汇编窗口中查看第一个CALL,返回这个CALL没有参数,产生僵尸的CALL应该是有参数的,例如僵尸的类型,坐标点等
继续查看第二个CALL,发现有2个参数,分析
00428C92 | 50 | push eax | eax:"0Zr"
00428C93 | 56 | push esi |
00428C94 | 8BC7 | mov eax,edi | eax:"0Zr", edi:"0Zr"
00428C96 | E8 35AAFFFF | call <plantsvszombies.sub_4236D0> |
在这个CALL下断,产生僵尸时断下,记录一下参数 push 2 push 0 eax=2399CA40
第二次断下也记录一下参数push 4 push 0 eax=2399CA40
分析先push (函数的第二个参数)的为行数也就是坐标,第一个参数为类型
这里注意以下call前面有一个eax,进入代码看一下发现是有用的,那就应该是寄存器传值,先用代码注入工具测试能不能实现产生僵尸的效果,发现可以实现
这个eax的值发现每次都是不变的,先用ce搜索一下这个值,找出基地址
[[7794f8]+868], 在用ce找的时候发现0019FD7C 附近的内存一直被写,如果在这里下访问断点程序会崩溃
调用代码如下
push 3
push 6
mov eax, [0x7794f8]
mov eax , [eax + 0x868]
call 0x004236D0
通过上面的僵尸数量还可以找出,僵尸数量的基址 [[7794f8]+868]+b8
查找阳光基址
1. 使用CE搜索到存储阳光的地址
2. OD附加游戏,在阳光地址下硬件访问断点,找到对阳光访问的代码,下面2个地方都是对阳光的读取
然后将断点改为,硬件写入断点
收集阳光时断下
种植时断下
3. 分析第一个访问断点,找出基址,重新下硬件访问断点,在00433FCB出断下时,记下edx的值然后找edx的来源,单步走出函数到调用该函数的地方
上面看见一句给,edx赋值的语句,先删除硬件断线,然后在这个CALl和上面的edx语句都下一个断点,F9运行发现不会走上面的edx赋值语句,继续往上找给edx赋值的语句,发现在该语句会断下而且[ebp+4] 和之前记录的edx的值相同,这里ebp和esp的相差较大所以判断这里ebp当成普通寄存器来使用,而没有当作栈底寄存器
004B4194 | 8B55 04 | mov edx,dword ptr ss:[ebp+4] | ebp == 2333E3A8
4. 接着找ebp,找到一条语句下断后,发现每次进来的值都不一样,我们就下条件断点[esp+0xB0]==2333E3A8 上面ebp的值
004B3FA0 <pla | 6A FF | push FFFFFFFF |
004B3FA2 | 68 9B4E7000 | push <plantsvszombies.sub_704E9B> |
004B3FA7 | 64:A1 00000000 | mov eax,dword ptr fs:[0] | fs:[0]为TEB的第一个成员SEH链指针
004B3FAD | 50 | push eax | 将SEH链指针压入栈中保存
004B3FAE | 64:8925 00000000 | mov dword ptr fs:[0],esp | 将esp的值保存到fs:[0]中
004B3FB5 | 81EC 98000000 | sub esp,98 | 开辟栈空间
004B3FBB | D9EE | fldz |
004B3FBD | 53 | push ebx |
004B3FBE | 55 | push ebp |
004B3FBF | D95424 0C | fst dword ptr ss:[esp+C],st(0) |
004B3FC3 | 8BAC24 B0000000 | mov ebp,dword ptr ss:[esp+B0] | 4+4+4+98+4+4 = AC [esp+AC]为CALL的返回地址 [esp+b0]为CALL的第一个参数
这里需要分析一下这个esp+b0 通过上面的几个push和sub esp,98 可以得出4+4+4+98+4+4 = AC [esp+AC]为CALL的返回地址 [esp+b0]为CALL的第一个参数 按出ctrl+f9跳到函数的结尾
5.
004B55DE | 56 | push esi |
004B55DF | 8D57 F8 | lea edx,dword ptr ds:[edi-8] |
004B55E2 | 52 | push edx |
004B55E3 | D846 08 | fadd st(0),dword ptr ds:[esi+8] |
004B55E6 | D95E 08 | fstp dword ptr ds:[esi+8],st(0) |
004B55E9 | DB47 04 | fild st(0),dword ptr ds:[edi+4] |
004B55EC | D846 0C | fadd st(0),dword ptr ds:[esi+C] |
004B55EF | D95E 0C | fstp dword ptr ds:[esi+C],st(0) |
004B55F2 | E8 A9E9FFFF | call <plantsvszombies.sub_4B3FA0> |
最后一个压入栈的是push edx下断点之后发现edx等于很多值的时候会断下,同样下条件断点
004B55C8 | 7E 47 | jle plantsvszombies.4B5611 |
004B55CA | 8D7D 30 | lea edi,dword ptr ss:[ebp+30] | 2333E290
004B55CD | 8D49 00 | lea ecx,dword ptr ds:[ecx] |
004B55D0 | 837F 2C FF | cmp dword ptr ds:[edi+2C],FFFFFFFF |
004B55D4 | 74 32 | je plantsvszombies.4B5608 |
004B55D6 | 807F 10 00 | cmp byte ptr ds:[edi+10],0 |
004B55DA | 74 2C | je plantsvszombies.4B5608 |
004B55DC | DB07 | fild st(0),dword ptr ds:[edi] |
004B55DE | 56 | push esi |
004B55DF | 8D57 F8 | lea edx,dword ptr ds:[edi-8] | edi == 2333E3B0
004B55E2 | 52 | push edx | edx == 2333E3A8
004B55E3 | D846 08 | fadd st(0),dword ptr ds:[esi+8] |
004B55E6 | D95E 08 | fstp dword ptr ds:[esi+8],st(0) |
004B55E9 | DB47 04 | fild st(0),dword ptr ds:[edi+4] |
004B55EC | D846 0C | fadd st(0),dword ptr ds:[esi+C] |
004B55EF | D95E 0C | fstp dword ptr ds:[esi+C],st(0) |
004B55F2 | E8 A9E9FFFF | call <plantsvszombies.sub_4B3FA0> |
004B55F7 | D946 08 | fld st(0),dword ptr ds:[esi+8] |
004B55FA | DA27 | fisub st(0),dword ptr ds:[edi] |
004B55FC | D95E 08 | fstp dword ptr ds:[esi+8],st(0) |
004B55FF | D946 0C | fld st(0),dword ptr ds:[esi+C] |
004B5602 | DA67 04 | fisub st(0),dword ptr ds:[edi+4] |
004B5605 | D95E 0C | fstp dword ptr ds:[esi+C],st(0) |
004B5608 | 43 | inc ebx |
004B5609 | 83C7 50 | add edi,50 |
004B560C | 3B5D 24 | cmp ebx,dword ptr ss:[ebp+24] |
004B560F | 7C BF | jl plantsvszombies.4B55D0 |
004B5611 | 8BCE | mov ecx,esi |
这里分析发现是一个循环,edi的值从这里开始
004B55CA | 8D7D 30 | lea edi,dword ptr ss:[ebp+30] | 2333E290
6.往上开始找ebp
004B549A | 8BAC24 88000000 | mov ebp,dword ptr ss:[esp+88] | 4+4+4+70+4+4 = 84 加上一个CALL的返回地址 所以[esp+88]为函数的最后一个参数
ctrl+f9跳到函数的结尾
最后分析的阳光基址为[[[[[[[[007794F8]+320]+4+14]]+8]+15c]+28+4]+5578]
查找种植CALL
在阳光地址下写入断点,种植后断下,查看调用栈,种植应该会有种植的坐标,分析CALL
阳光 最后一行 第0列
00427D70 | 51 | push ecx | 502 0x1f6
00427D71 | 52 | push edx | 89 0x59
00427D72 | 56 | push esi | 244B5B20
00427D73 | 8BCB | mov ecx,ebx | 1
00427D75 | E8 F6DAFFFF | call plantsvszombies.425870 | 种植CALL
土豆 第1行 第0列
00427D70 | 51 | push ecx | 210 0xD2
00427D71 | 52 | push edx | 96 0x60
00427D72 | 56 | push esi | 244B5B20
00427D73 | 8BCB | mov ecx,ebx | 1
00427D75 | E8 F6DAFFFF | call plantsvszombies.425870 | 种植CALL
豌豆 第2行 第1列
00427D70 | 51 | push ecx | 301 0x12d
00427D71 | 52 | push edx | 129 0x81
00427D72 | 56 | push esi | 244B5B20
00427D73 | 8BCB | mov ecx,ebx | 1
00427D75 | E8 F6DAFFFF | call plantsvszombies.425870 | 种植CALL
第一个相同
00427D70 | 51 | push ecx | 516
00427D71 | 52 | push edx | 74
00427D72 | 56 | push esi | 244B5B20
00427D73 | 8BCB | mov ecx,ebx | 1
00427D75 | E8 F6DAFFFF | call <plantsvszombies.sub_425870> | 种植CALL
找到一个形似的但是无法分析出坐标,下断点,种植时断下,不种植不断,思考种植CALL应该可能在扣除阳光的前面
在扣除阳光CALL的后面找到一个会push坐标的CALL经过分析为种植CALL
种植CALL 可以重复种植
mov eax,3
push 0xffffffff
push 2
push 2
push 0x238815B8 [[[[[007794F8]+320]+4+14]]+8]
call 0x00422610
mov eax,1
push 0xffffffff
push 2
push 0
mov ebx,7794F8
mov ebx, [ebx]
mov ebx,[ebx+320]
mov ebx,[ebx+18]
mov ebx,[ebx]
mov ebx,[ebx+8]
push ebx
call 0x00422610
004265BE | 8B4424 14 | mov eax,dword ptr ss:[esp+14] | eax=0 y
004265C2 | 51 | push ecx | ffffffff
004265C3 | 52 | push edx | 类型
004265C4 | 53 | push ebx | x
004265C5 | 57 | push edi | 238815B8
004265C6 | E8 45C0FFFF | call <plantsvszombies.sub_422610>
实验获取植物类型,只有已经获取到的植物可以种植不然会崩溃
0 豌豆射手 1 向日葵 2爆炸樱桃 3土豆 4地雷 5蓝色的豌豆 6吃人花 7快速豌豆射手 8小蘑菇
僵尸血量分析
用ce搜索僵尸的血量,查找访问的地址,有下面这一句可能是判断死亡的
00560D03 | 83BF C8000000 00 | cmp dword ptr ds:[edi+C8],0 | 24615F78
OD附加往上跟
00560940 | 8BFE | mov edi,esi |
00560819 | 8BF0 | mov esi,eax | 24615F78
发现这个esi是从一个函数里来的
00428D68 | 8D7424 08 | lea esi,dword ptr ss:[esp+8] |
00428D6C | 8BD7 | mov edx,edi |
00428D6E | 895C24 08 | mov dword ptr ss:[esp+8],ebx |
00428D72 | E8 F9C30000 | call <plantsvszombies.sub_435170> | 遍历
分析这个CALL
00435170 <pla | 57 | push edi | edx==2460FC58 这个地址是血量基址中来的
00435171 | BF 0000FFFF | mov edi,FFFF0000 |
00435176 | 8B06 | mov eax,dword ptr ds:[esi] |
00435178 | 85C0 | test eax,eax | 进行与运算
0043517A | 75 08 | jne plantsvszombies.435184 | eax不为0跳转
0043517C | 8B82 A8000000 | mov eax,dword ptr ds:[edx+A8] |
00435182 | EB 05 | jmp plantsvszombies.435189 |
00435184 | 05 68010000 | add eax,168 |
00435189 | 8B8A AC000000 | mov ecx,dword ptr ds:[edx+AC] | 9
0043518F | 69C9 68010000 | imul ecx,ecx,168 | ecx=ecx*168
00435195 | 038A A8000000 | add ecx,dword ptr ds:[edx+A8] |
0043519B | 3BC1 | cmp eax,ecx |
0043519D | 73 12 | jae plantsvszombies.4351B1 |
0043519F | 90 | nop |
004351A0 | 85B8 64010000 | test dword ptr ds:[eax+164],edi |
004351A6 | 75 13 | jne plantsvszombies.4351BB |
004351A8 | 05 68010000 | add eax,168 |
004351AD | 3BC1 | cmp eax,ecx |
004351AF | 72 EF | jb plantsvszombies.4351A0 |
004351B1 | C706 FFFFFFFF | mov dword ptr ds:[esi],FFFFFFFF |
004351B7 | 32C0 | xor al,al |
004351B9 | 5F | pop edi |
004351BA | C3 | ret |
004351BB | 8906 | mov dword ptr ds:[esi],eax | 1
004351BD | 80B8 EC000000 00 | cmp byte ptr ds:[eax+EC],0 |
004351C4 | 75 B0 | jne plantsvszombies.435176 |
004351C6 | B0 01 | mov al,1 |
004351C8 | 5F | pop edi |
004351C9 | C3 | ret |
分析
[px+c8] 僵尸血量
px y=2460fc58
i = 0xffff0000
if(*px == 0)
a= *(y+a8)
c = *(y+0xac)
c *= 0x168
c += *(y+0xa8)
if a >= c
return false
else
if *(a+0x164) == i
a += 0x168
if a < c
goto if *(a+0x164) == i
else
return fals5
else
*px = a
if(*(a+0xec) == 0)
goto if(*px == 0)
else
return true
得出 僵尸血量 [[[[[[[[[007794F8]+320]+4+14]]+8]+15c]+28+4]+a8]+168*0+c8] 0为僵尸的索引
c8当前血
cc最大血
8 x坐标
c y坐标
破除限制单开
在ExitProcess下断,往上跟,查看跳过当前退出CALL的跳转
005D2DE3 | 74 2F | je plantsvszombies.5D2E14 |
这里改成jmp
去除光标离开游戏暂停
搜索字符串发现 ,[GAME_PAUSED],在该字符串下断,一层层分析
00471A3A | 75 0F | jne plantsvszombies.471A4B |
改成jmp即可