經(jīng)過(guò)前邊的字庫(kù)改造,已經(jīng)完成了一半的工作,剩下最關(guān)鍵的顯示漢字部分了。字庫(kù)已經(jīng)是中文的了,但是能讓中文顯示出來(lái)卻不是件容易的事。不信現(xiàn)在進(jìn)游戲試試,看到的中文全是亂碼。為何?因?yàn)橹形氖请p字節(jié),兩個(gè)字節(jié)才代表一個(gè)漢字。游戲顯示英文字體的函數(shù)是為顯示單字節(jié)的英文設(shè)計(jì)的,是不適合顯示中文的,必須要修改。因?yàn)椴豢赡艿玫匠绦虻脑创a,修改方法只能采用比較極端的修改可執(zhí)行文件的方法了,即所謂的逆向工程。
于是操起常用的調(diào)試工具Ollydbg開(kāi)始調(diào)試游戲。經(jīng)過(guò)2天的不懈努力,終于找到了顯示字庫(kù)的函數(shù),以下列出讀取字符的函數(shù)部分代碼:
004AA909
004AA90B 40 inc eax
004AA
004AA90E 8BD6 mov edx,esi
004AA
004AA912 1BD2 sbb edx,edx
004AA914 23D0 and edx,eax
004AA916
004AA918 8917 mov dword ptr ds:[edi],edx
函數(shù)開(kāi)始Eax指向腳本文件grim.tab文件中某行腳本的第一個(gè)字符。例如主菜單”Control Help”中的C位置。004AA909一行的意圖很明顯,讀取字符串中當(dāng)前位置的的一個(gè)字符的ASCII碼到放到cl中,然后Eax加一,指向下一個(gè)字符。然后會(huì)將此cl中的字符當(dāng)作參數(shù),調(diào)用另外一個(gè)顯示字符的函數(shù),完成讀取字庫(kù)文件并顯示字符到屏幕的功能。
我們需要對(duì)此部分做改造。如當(dāng)前Eax指向一個(gè)英文字符,則還沿用程序原來(lái)的部分,讀取一個(gè)字節(jié)到cl,并使Eax增一;如當(dāng)前Eax指向一個(gè)中文漢字,則需要程序讀取2個(gè)字節(jié)到cx中,并使Eax增二,指向下一個(gè)字符的正確位置。那么如何判斷當(dāng)前Eax指向的是一個(gè)英文字符還是中文漢字呢,GB2312漢字的編碼有一個(gè)的特性:兩個(gè)字節(jié)編碼最高位(第8位)一定是1。每次讀取字符時(shí),先判斷第8位是0還是1,如果是1一定是中文,是0則是英文。
有了思路,對(duì)讀取字符的函數(shù)做如下修改,紅色為新增代碼:
004AA909
004AA90B 40 inc eax
f
7406 je 4aa
c1e108 shl ecx,08h
40 inc eax
004AA
004AA90E 8BD6 mov edx,esi
004AA
004AA912 1BD2 sbb edx,edx
004AA914 23D0 and edx,eax
004AA916
004AA918 8917 mov dword ptr ds:[edi],edx
先放Eax一個(gè)字節(jié)到cl中,然后判斷cl的第8位是否為1,如果是0,說(shuō)明是英文字符,則按程序原來(lái)的進(jìn)度跳轉(zhuǎn)到004AA
然后用Uedit打開(kāi)可執(zhí)行文件,找到一段nop(90)比較多的位置,最后將紅色部分的機(jī)器碼加到合適位置就OK了。
聯(lián)系客服