Plants vs. Zombies 是大家喜欢的一个游戏,但是存档在C盘C:\ProgramData\PopCap Games\PlantsVsZombies\userdata目录,没有备份重装后,档案就丢失了。因此,改造下,让游戏把存档放在程序目录下,这样重装系统,存档不至于因忘记备份而丢失。
以1.2.0.1073英文原版为基础处理。
原主程序和修改好的主程序放在了附件,因未对主程序目录下userdata目录新建部分代码处理,请提前在主程序目录下新建userdata目录。
最开始我是直接把软件目录中获取C:\ProgramData\PopCap Games\PlantsVsZombies目录的相关代码进行了屏蔽,这样会导致cached也跑到了主程序目录,明显我们不需要把cached也放在主程序目录下,这样也显示我们程序目录过于庸肿。
相关处理过程我不多说了,大家可以自己尝试。
这时换第二种思路,劫持文件打开函数,如果遇到读取存档,则处理打开函数参数中的文件名,即将C:\ProgramData\PopCap Games\PlantsVsZombies\userdata\users.dat类似的处理为userdata\users.dat,其他文件名不处理。
游戏是C++编程,使用fopen打开文件
[Asm] 纯文本查看 复制代码 FILE *fopen(const char *filename, const char *mode);
参数
filename-- 这是 C 字符串,包含了要打开的文件名称。
mode-- 这是 C 字符串,包含了文件访问模式。
功能
使用给定的模式mode打开filename所指向的文件。
查找wb字符
[Asm] 纯文本查看 复制代码 Text strings referenced in PlantsVs:.text, item 3487
Address=005F94C0
Disassembly=PUSH PlantsVs.006E64D0
Text string=ASCII "wb"
定位到代码 可以基本断定0069B0E1 为文件处理函数我们改掉这个函数即可。
[Asm] 纯文本查看 复制代码 005F94C0 |. 68 D0646E00 |PUSH PlantsVs.006E64D0 ; ASCII "wb"
005F94C5 |. 8D4D C4 |LEA ECX,DWORD PTR SS:[EBP-0x3C]
005F94C8 |. E8 93BBE0FF |CALL <PlantsVs.unknown_libname_1>
005F94CD |. 50 |PUSH EAX ; |Arg1
005F94CE |. E8 0E1C0A00 |CALL PlantsVs.0069B0E1 ; \PlantsVs.0069B0E1
代码空间小,我们需要在程序里找个空白位置
[Asm] 纯文本查看 复制代码 0069B0E1 8BFF MOV EDI,EDI
0069B0E3 55 PUSH EBP
0069B0E4 8BEC MOV EBP,ESP
0069B0E6 6A 40 PUSH 0x40
0069B0E8 |. FF75 0C PUSH DWORD PTR SS:[EBP+0xC]
0069B0EB |. FF75 08 PUSH DWORD PTR SS:[EBP+0x8]
0069B0EE |. E8 2AFFFFFF CALL <PlantsVs.__fsopen>
0069B0F3 |. 83C4 0C ADD ESP,0xC
0069B0F6 |. 5D POP EBP
0069B0F7 \. C3 RETN
006CD910 处空白,既将代码跳转到空白处。
[Asm] 纯文本查看 复制代码 0069B0E1 E9 2A280300 JMP PlantsVs.006CD910
先恢复我们刚才占用的代码
[Asm] 纯文本查看 复制代码 006CD910 55 PUSH EBP
006CD911 8BEC MOV EBP,ESP
接下来把文件名放进eax,并不断将eax与userdata字串比较,如果相符,则把前面的C:\ProgramData\PopCap Games\PlantsVsZombies\截除,使用当前目录,最后再跳转回原来0069B0E6,继续执行主程序。
[Asm] 纯文本查看 复制代码 006CD913 8B45 08 MOV EAX,DWORD PTR SS:[EBP+0x8]
006CD916 EB 17 JMP SHORT PlantsVs.006CD92F
006CD918 8138 75736572 CMP DWORD PTR DS:[EAX],0x72657375
006CD91E 75 0E JNZ SHORT PlantsVs.006CD92E
006CD920 8178 04 646174>CMP DWORD PTR DS:[EAX+0x4],0x61746164
006CD927 75 05 JNZ SHORT PlantsVs.006CD92E
006CD929 8945 08 MOV DWORD PTR SS:[EBP+0x8],EAX
006CD92C EB 06 JMP SHORT PlantsVs.006CD934
006CD92E 40 INC EAX
006CD92F 8038 00 CMP BYTE PTR DS:[EAX],0x0
006CD932 ^75 E4 JNZ SHORT PlantsVs.006CD918
006CD934 ^E9 ADD7FCFF JMP PlantsVs.0069B0E6
小技巧,比较代码跳转较多,直接在od里编程较麻烦,可以用radasm新建个空白工程,编译好后,再把相关代码复制回我们要破解的程序里,非常方便。下面是我在radasm里的代码。
[Asm] 纯文本查看 复制代码 .while byte ptr [eax]
.if dword ptr [eax]==72647375h && dword ptr [eax+4]==61746164h
mov [ebp+8],eax
.break
.endif
inc eax
.endw
PlantsVsZombies.exe为原程序,PlantsVsZombies7.exe为改好的程序,大家可以自行尝试。
文章简单,但是尝试过程是十分麻烦的。方便了给个热心,非常感谢。 |