利用反汇编技术将游戏《英雄无敌3》修改为硬盘版

最近好不容易找到我最喜欢的游戏《英雄无敌3之埃拉西亚的光复》英文版,可惜是光盘版的,要用虚拟光驱来运行,感觉不爽,网上也找不到免CD补丁,于是决定自己动手。

首先感谢这篇文章的作者

http://bbs.pediy.com/showthread.php?t=101023

是他引领我进入反汇编的大门。这篇文章的第一步,就是找到GetDriveType的调用(GetDriveType就是判断某盘符是光驱、硬盘或网络磁盘等的API函数),于是我用C32Asm,对游戏主程序Heroes3.exe进行反汇编,再查找GetDriveType,结果还真有,如下:

::005A8437:: FF15 48A05B00 CALL [5BA048] >>>: KERNEL32.DLL:GetDriveTypeA

::005A843D:: 85C0 TEST EAX,EAX

::005A843F:: 74 0A JE SHORT 005A844B :JMPDOWN

::005A8441:: 83F8 01 CMP EAX,1

::005A8444:: 74 05 JE SHORT 005A844B :JMPDOWN

::005A8446:: 6A 01 PUSH 1 :BYJMP JmpBy:005A8420,

::005A8448:: 58 POP EAX

::005A8449:: 5D POP EBP

::005A844A:: C3 RETN

但是和文章中不一样啊,他在调用GetDriveTypeA之后,判断返回值是否为5(5是光驱),而我这里却是1

::005A8441:: 83F8 01 CMP EAX,1

后面的逻辑也不一样。而继续查找GetDriveType也找不到了。于是我再仔细看看上面的代码,发现“>>>: KERNEL32.DLL:GetDriveTypeA”这只是反汇编器加上的注释,真正调用的是5BA048这个地址的代码,于是又搜5BA048,结果又找到一处

::004E7B69:: 8B35 48A05B00 MOV ESI,[5BA048]

::004E7B6F:: 33ED XOR EBP,EBP

::004E7B71:: 8BF8 MOV EDI,EAX

::004E7B73:: 896C24 10 MOV [ESP+10],EBP

::004E7B77:: BB 02000000 MOV EBX,2

::004E7B7C:: BA 01000000 MOV EDX,1 :BYJMP JmpBy:004E7BAF,

::004E7B81:: 8BCB MOV ECX,EBX

::004E7B83:: D3E2 SHL EDX,CL

::004E7B85:: 85D7 TEST EDI,EDX

::004E7B87:: 74 22 JE SHORT 004E7BAB :JMPDOWN

::004E7B89:: 8AC3 MOV AL,BL

::004E7B8B:: 04 41 ADD AL,41

::004E7B8D:: 68 DC495E00 PUSH 5E49DC ->: A:\

::004E7B92:: A2 DC495E00 MOV [5E49DC],AL

::004E7B97:: FFD6 CALL ESI

::004E7B99:: 83F8 05 CMP EAX,5

原来它是把5BA048给了 ESI,然后在后面 CALL ESI。找到这里就可以改了,把 CMP EAX,5,也就是83F8 05改成83F8 03,汇编代码的地址是004E7B99,对应的十六进制代码地址就是000E7B99。改完之后保存运行,发现还是报告找不到光盘。我就继续参考上面那篇文章,发现他后面的逻辑又和我的对不上了,应该是两游戏的版本不同。接下来该怎么办呢?我只好硬着头皮,从CMP EAX,5接着往下看,发现有这么一段:

::004E7C8C:: BF 387D5E00 MOV EDI,5E7D38 ->: d;^kIwuL{<fomaokXvdbyhIEnb~

::004E7C91:: F2 REPNE SCASB

::004E7C92:: AE SCASB

::004E7C93:: F7D1 NOT ECX

::004E7C95:: 49 DEC ECX

::004E7C96:: 74 1A JE SHORT 004E7CB2 :JMPDOWN

::004E7C98:: 2892 387D5E00 SUB [EDX+5E7D38],DL :BYJMP JmpBy:004E7CB0,

::004E7C9E:: 83C9 FF OR ECX,FFFFFFFF

::004E7CA1:: 33C0 XOR EAX,EAX

::004E7CA3:: 42 INC EDX

::004E7CA4:: BF 387D5E00 MOV EDI,5E7D38 ->: d;^kIwuL{<fomaokXvdbyhIEnb~

::004E7CA9:: F2 REPNE SCASB

::004E7CAA:: AE SCASB

::004E7CAB:: F7D1 NOT ECX

::004E7CAD:: 49 DEC ECX

::004E7CAE:: 3BD1 CMP EDX,ECX

::004E7CB0:: 72 E6 JB SHORT 004E7C98 :JMPUP

::004E7CB2:: 68 00800000 PUSH 8000 :BYJMP JmpBy:004E7C96,

::004E7CB7:: 80C3 41 ADD BL,41

::004E7CBA:: 68 387D5E00 PUSH 5E7D38 ->: d;^kIwuL{<fomaokXvdbyhIEnb~

::004E7CBF:: 881D 387D5E00 MOV [5E7D38],BL

::004E7CC5:: E8 27960B00 CALL 005A12F1

这个5E7D38里面是什么东东,后面的代码貌似对它进行了加工(SUB [EDX+5E7D38],DL和MOV [5E7D38],BL),于是请出反汇编调试利器--Visual Studio!利用VS的F11单步调试,程序直接停在入口处(main函数对应的汇编代码),然后在004E7C8C处下断点,并且打开内存查看窗口,查看5E7D38处的内容,发现是一串奇怪的字符串“.;^kIwuL{<fomaokXvdbyhIEnb~”,怎么感觉眼熟呢?仔细一看,原来上面的代码后面的注释里就是这东东啊:->: d;^kIwuL{<fomaokXvdbyhIEnb~。于是F10单步执行,果然到SUB [EDX+5E7D38],DL这句时,这个字符串有变化。随着EDX和DL的值不断加1(INC EDX),以5E7D38为首地址的字符串中的每1个字符都要减去自已的索引值,这就是个简单的解密算法,就是把“.;^kIwuL{<fomaokXvdbyhIEnb~”改成“.:\hEroEs3\daTa\HeROeS3.VId”(我去,还大小写混合,生怕别人搜到啊),然后用MOV [5E7D38],BL,BL值是字符C,这就变成“C:\hEroEs3\daTa\HeROeS3.VId”,之后CALL 005A12F1就是判断C:\hEroEs3\daTa\HeROeS3.VId是否存在。存在就可以进游戏,不存在则在某处使用BL加1(C就变成D,这地方我没找到),继续查找HeROeS3.VId,直到找到方可进入游戏,或者到Z还找不到,就弹出提示说没有光盘无法进入游戏。

接下来就好办了,只要把光盘里的文件复制到游戏根目录下、把d;^kIwuL{<fomaokXvdbyhIEnb~改成相对路径、把解密算法去掉就可以了,具体操作如下:

1.用虚拟光驱打开游戏光盘的ISO文件,复制heroes3文件夹到硬盘上英雄无敌的根目录下。

2.用ASCII码转换工具,把d;^kIwuL{<fomaokXvdbyhIEnb~转换成十六进制码64 3b 5e 6b 49 77 75 4c 7b 3c 66 6f 6d 61 6f 6b 58 76 64 62 79 68 49 45 6e 62 7e,再用VS以二进制方式打开Heroes3.exe,查找上面的十六进制码,找到后,改成2e 5c 68 65 72 6f 65 73 33 5c 64 61 74 61 5c 68 65 72 6f 65 73 33 2e 76 69 64 00,即.\heroes3\data\heroes3.vid。

3.还是VS,找到004E7C8C所对应的十六进制地址000E7C8C(原来汇编地址和十六进制地址相差0x00400000),把从000E7C8C开始,到004E7CC5为止,所有的十六进制数都改成90,即空指令NOP,这样就把解密算法去掉了。

最后保存运行一下,直接进入了,大功告成!

全文完。

posted @ 2025-07-01 14:55  安联酋长  阅读(25)  评论(0)    收藏  举报