教程
阳光数修改
通过CE找到基址,规律就是,第一步找到
mov eax,[]类型的,第二部是根据第一部中括号中的寄存器变量,寻找mov 括号中的寄存器名,[],后面以此类推,例如第一步是mov eax,[esi+00005560],那么第二步就寻找mov esi,[]。这里有一个规律就是,当静态地址和动态地址都在结果范围中时,优先查看静态基址。第一次查找到动态地址
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18EAX=0000004B
EBX=00000001
ECX=00000000
EDX=13DE97B0
ESI=1627F418
EDI=13D17888
EBP=0019FA98
ESP=00199790
EIP=0048982B
指针基址可能是 =1627F418
0048981D - test al,al
0048981F - jne 00489933
00489825 - mov eax,[esi+00005560]
0048982B - xor ecx,ecx
0048982D - test eax,eax第二次查找到动态地址
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18EAX=00452650
EBX=0019FD00
ECX=02BD1B08
EDX=00667BA0
ESI=1627F418
EDI=02BD1B08
EBP=00000001
ESP=0019FC60
EIP=00452679
指针基址可能是 =02BD1B08
0045266A - cmp byte ptr [edi+000004CF],00
00452671 - je 0045269B
00452673 - mov esi,[edi+00000768]
00452679 - test esi,esi
0045267B - je 0045269B第三次查找到基址(静态地址)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18EAX=00007022
EBX=FFFFFFFF
ECX=001996B0
EDX=7FFFFFFF
ESI=02BD1B08
EDI=FFFFFFFF
EBP=00000000
ESP=001995C8
EIP=00487F6B
指针基址可能是 =006A9EC0
00487F55 - mov byte ptr [esp+64],00
00487F5A - mov [esp+000000F0],00000001
00487F65 - mov esi,[006A9EC0]
00487F6B - mov eax,[esi+00000768]
00487F71 - test eax,eax
阳光静态基址。

这时无论代码什么时候运行,都能定位到对应的地址。修改对应地址的数据即可修改阳光数。
破解阳光增加减少事件
右键基址,查看是谁修改了了内存中阳光数量对应的数据。
阳光数减少事件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18EAX=0000004B
EBX=00000032
ECX=FFFFFFFF
EDX=189B3760
ESI=00000019
EDI=189B3760
EBP=189B3760
ESP=0019FB70
EIP=0041BA7C
指针基址可能是 =189B3760
0041BA72 - jg 0041BA80
0041BA74 - sub esi,ebx
0041BA76 - mov [edi+00005560],esi
0041BA7C - mov al,01
0041BA7E - pop esi阳光数增加事件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17EAX=189B3760
EBX=00000001
ECX=00000019
EDX=D5820009
ESI=191511F0
EDI=189B3760
EBP=0019F9D8
ESP=0019F968
EIP=00430A17
指针基址可能是 =189B3760
00430A0B - and ecx,32
00430A0E - mov eax,[esi+04]
00430A11 - add [eax+00005560],ecx
00430A17 - mov ecx,[eax+00005560]
00430A1D - cmp ecx,00002706
此时我们介入x64dbg,对对应位置的汇编进行分析。
附加到进程,点击符号标签页,找到植物大战僵尸符号位置,双击进入。使用
Ctrl+G跳转至汇编代码位置。先跳转至减少阳光的位置0041BA76,找到对应子函数的头,设置断点,回到游戏,使用阳光以触发断点。
可以看到目前所有阳光数为100,向日葵所需阳光数为50。

找到一处空白地址,写入原来的子程序中的指令,但是稍加修改,讲esi固定为0x2706也就是9990,为本游戏上限,当然也可以在增加阳光的子程序中解除此功能的判断,就可以做到阳光无上限。
1
2
3
4
5006510EB | BE 06270000 | mov esi,0x2706 |
006510F0 | 89B7 60550000 | mov dword ptr ds:[edi+0x5560],esi |
006510F6 | B0 01 | mov al,0x1 |
006510F8 | 5E | pop esi |
006510F9 | E9 81A9DCFF | jmp plantsvszombies.41BA7F |原汇编指令集修改为
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
250041BA60 | 56 | push esi |
0041BA61 | 8BB7 60550000 | mov esi,dword ptr ds:[edi+0x5560] | edi+5560:"P\"?"
0041BA67 | 8BD7 | mov edx,edi |
0041BA69 | E8 12FFFFFF | call <plantsvszombies.sub_41B980> |
0041BA6E | 03C6 | add eax,esi | 剩余阳光数
0041BA70 | 3BD8 | cmp ebx,eax | 消费阳光数
0041BA72 | 7F 0C | jg plantsvszombies.41BA80 |
0041BA74 | E9 72562300 | jmp plantsvszombies.6510EB |
0041BA79 | 90 | nop |
0041BA7A | 90 | nop |
0041BA7B | 90 | nop |
0041BA7C | 90 | nop |
0041BA7D | 90 | nop |
0041BA7E | 90 | nop |
0041BA7F | C3 | ret |
0041BA80 | 8B8F 8C000000 | mov ecx,dword ptr ds:[edi+0x8C] | 异常链,当阳光数小于植物消耗的阳光
0041BA86 | 8B01 | mov eax,dword ptr ds:[ecx] |
0041BA88 | 8B15 607B6A00 | mov edx,dword ptr ds:[0x6A7B60] |
0041BA8E | 8B80 D8000000 | mov eax,dword ptr ds:[eax+0xD8] |
0041BA94 | 52 | push edx |
0041BA95 | FFD0 | call eax |
0041BA97 | C787 78550000 46 | mov dword ptr ds:[edi+0x5578],0x46 | 46:'F'
0041BAA1 | 32C0 | xor al,al |
0041BAA3 | 5E | pop esi |
0041BAA4 | C3 | ret |这样,在阳光减少时的子函数已经破解完成。
将ecx设置为0x2706,阳光存储上限。
1
200430A11 | B9 06270000 | mov ecx,0x2706 |
00430A16 | 90 | nop |阳光增加子函数破解完成。
破解植物种植事件
- 通过监控植物数量的方式间接查找植物种植事件。因为植物数量会因为植物种植事件而发生变化,所以植物种植事件一定会修改植物种植数量。

