好友
阅读权限10
听众
最后登录1970-1-1
|
本帖最后由 御坂00001号 于 2020-3-4 13:12 编辑
功能实现:子弹回旋
实现基础
1. 子弹x坐标可以增加,也可以反向减少
2. 子弹具有流程
击中僵尸:子弹产生 -> 子弹飞行 -> 子弹击中僵尸 -> 僵尸掉血 -> 子弹爆炸 -> 子弹消失
未击中僵尸:子弹产生 -> 子弹飞行 -> 检查边界 -> 子弹消失
3. 子弹可以穿透
实现分析
逻辑分析
1. 首先根据子弹产生,消失标志由1变0;子弹击中,消失标志由0变1 -> 可以得到修改此处代码 0046EB2B - C6 46 50 01 - mov byte ptr [esi+50],01 为0赋值,以使子弹在击中后不消失
2. 其次,找子弹飞行相关代码,这个可以根据子弹x坐标变化找到三处(飞行时、击中时、产生时),查看飞行时的相关代码,可以得到子弹x坐标减少和增加的代码段
[Asm] 纯文本查看 复制代码
0046DBD7 - D9 43 30 - fld dword ptr [ebx+30] { 子弹x坐标减少 }
0046DBDA - DC 25 A0966700 - fsub qword ptr [006796A0] { (3.33) }
0046DBE0 - D9 5B 30 - fstp dword ptr [ebx+30]
[Asm] 纯文本查看 复制代码
0046DBE8 - D9 43 30 - fld dword ptr [ebx+30] { 子弹x坐标增加 }
0046DBEB - DC 05 A0966700 - fadd qword ptr [006796A0] { (3.33) }
0046DBF1 - D9 5B 30 - fstp dword ptr [ebx+30]
3. 最后,找子弹边界检查相关代码,我们可以在这里实行代码注入(其实也可以在上面代码处注入),边界代码如下,见代码分析
[Asm] 纯文本查看 复制代码
0046CE9D - D9 45 30 - fld dword ptr [ebp+30] { 子弹x坐标 }
0046CEA0 - DC 1D 38976700 - fcomp qword ptr [00679738] { 左边界 }
0046CEA6 - DFE0 - fnstsw ax
0046CEA8 - F6 C4 41 - test ah,41 { 若 子弹x坐标 >= 左边界,则跳 }
0046CEAB - 0F84 96010000 - je 0046D047
0046CEB1 - DB 45 10 - fild dword ptr [ebp+10]
0046CEB4 - D8 45 30 - fadd dword ptr [ebp+30] { 子弹x坐标 }
0046CEB7 - DC 1D 98926700 - fcomp qword ptr [00679298] { 右边界 }
0046CEBD - DFE0 - fnstsw ax
0046CEBF - F6 C4 05 - test ah,05 { 若 子弹x坐标 < 右边界,则跳 }
0046CEC2 - 0F8B 7F010000 - jnp 0046D047
代码分析
[Asm] 纯文本查看 复制代码
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,2048)
label(returnhere)
label(originalcode)
label(exit)
// 代码逻辑:先开辟一段可用空间,用来存放方向标志;然后根据(当前子弹x坐标地址 - 首颗子弹x坐标地址) / 0x94(0x94为子弹x坐标的间隔) 可以得到当前是第几颗子弹,从而取到方向标志;
最后根据方向标志来决定子弹x坐标是增加还是减少,并对越过边界的子弹修改其方向标志
newmem: //this is allocated memory, you have read,write,execute access
//place your code here
push ecx
push ebx
push eax
push edx
xor edx,edx
mov ecx,[6A9EC0]
mov ecx,[ecx+768]
mov ecx,[ecx+c8] // 子弹x坐标首地址
lea eax,[ebx+30] // 子弹x坐标现地址
sub eax,ecx
mov ecx,94 // 子弹x坐标间隔(第1颗子弹与第2颗子弹)
div ecx // eax:第几个, 从0开始
xor edx,edx // 清零
add eax,00699000 // 00699000+index, 用来存放子弹的方向标志
mov ecx,eax
mov dl,[ecx] // 只存在低字节
cmp edx,0
pop edx
pop eax
pop ebx // 暂时不弹ecx, 因为ecx还有用
je addx
subx: // 子弹x坐标减少
fld dword ptr [ebp+30]
fsub qword ptr [006796A0]
fsub qword ptr [006796A0]
fstp dword ptr [ebp+30]
coml: // 左边界检查
push eax
fild dword ptr [ebp+10]
fadd dword ptr [ebp+30]
fcomp qword ptr [00679298]
fnstsw ax
test ah,05 // 若子弹x坐标 < 0, 则跳
jnp leftb
pop eax
pop ecx
jmp 0046CEC8
leftb: // 越过左边界, 则置相反标志
mov byte ptr [ecx],00
pop eax
pop ecx
jmp 0046CEC8
addx: // 子弹x坐标增加
fld dword ptr [ebp+30]
fadd qword ptr [006796A0]
fadd qword ptr [006796A0]
fstp dword ptr [ebp+30]
comr: // 右边界检查
push eax
fldpi
fld dword ptr [ebp+30]
fadd st(0),st(1)
fcomp qword ptr [00679738]
fnstsw ax
test ah,41 // 若子弹x坐标 >= 800, 则跳
je rightb
pop eax
pop ecx
jmp 0046CEC8
rightb: // 超出右边界, 则置相反标志
mov byte ptr [ecx],01
pop eax
pop ecx
jmp 0046CEC8
originalcode:
//fld dword ptr [ebp+30]
//fcomp qword ptr [00679738]
jmp newmem
exit:
jmp returnhere
"PlantsVsZombies.exe"+6CE9D:
jmp newmem
nop 4
returnhere:
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
"PlantsVsZombies.exe"+6CE9D:
fld dword ptr [ebp+30]
fcomp qword ptr [00679738]
fnstsw ax
test ah,41
je 0046D047
fild dword ptr [ebp+10]
fadd dword ptr [ebp+30]
fcomp qword ptr [00679298]
fnstsw ax
test ah,05
jnp 0046D047
//Alt: db D9 45 30 DC 1D 38 97 67 00
实际效果
最后总结
虽然代码上逻辑没啥大问题,但会产生几个bug:①下一关再开,可能植物/僵尸不会重绘 ②僵尸可以走第6行 ③某些僵尸过度重绘
到此为止,植物大战僵尸能改的都改了,可能超过子弹跟踪和子弹回旋的难度很难再有,前者为修改关键跳,后者为修改程序逻辑
此贴可能会继续更新,只是把一些bug解决。。。。。。
end |
免费评分
-
查看全部评分
|
发帖前要善用【论坛搜索】功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。 |
|
|
|
|