VOS1.0p字體補丁製作手記[noword]

VOS1.0p字體補丁製作手記

先說說我走的彎路,一開始我認爲VOS是在韓文狀態下編譯的,所以他的進程(thread )的Local也是韓文的,那我只要把進程的Local改成中文的就可以了。在MSDN中查找,發現 有一個API正合我意:SetThreadLocale。但是VOS沒用到SetThreadLocale,於是我修改 import表,插入了SetThreadLocale,再在代碼段中插入代碼去調用SetThreadLocale,都改好後,雙擊VOS運行……熟悉的韓文出現在我面前,當場暈倒。

說出我走過的艱辛的彎路,是爲了告訴大家,一開始找對方向有多麼重要。下面的正路要比彎路簡單多了。

進入正題,我用的工具:W32Dasm用來靜態反彙編,SoftIce用來動態跟蹤,UltraEdit 用來編輯。

首先,當然是用W32Dasm反彙編VOS.exe,還好HanseulSoft沒進行什麼噁心的壓縮加殼 ,輕鬆得到Vos的反彙編代碼。我們是要做的是VOS字體補丁,字體的英文叫Font,搜索Font ,果然VOS用到CreateFontA這個函數,而且跟Font有關的就是隻有這個函數。繼續搜索 CreateFontA,發現VOS共用了兩次CreateFontA,一次在0043DD0B,還有一次在0043DE17。

先看後面的那次調用:

:0043DDEF 50
push eax
//lpszFace
:0043DDF0 0FBF942490000000 movsx edx, word ptr [esp+00000090]  
:0043DDF8 6A02 push 00000002 //fdwPitchAndFamily
:0043DDFA 6A00 push 00000000 //fdwQuality
:0043DDFC 0FBF84249C000000 movsx eax, word ptr [esp+0000009C]  
:0043DE04 6A00 push 00000000 //fdwClipPrecision
:0043DE06 6A00 push 00000000 //fdwOutputPrecision
:0043DE08 6A01 push 00000001 //fdwCharSet DEFAULT_CHARSET
:0043DE0A 6A00 push 00000000 //fdwStrikeOut
:0043DE0C 6A00 push 00000000 //fdwUnderline
:0043DE0E 6A00 push 00000000 //fdwItalic
:0043DE10 51 push ecx //fnWeight
:0043DE11 6A00 push 00000000 //nOrientation
:0043DE13 6A00 push 00000000 //nEscapement
:0043DE15 52 push edx //nWidth
:0043DE16 50 push eax //nHeight
* Reference To: GDI32.CreateFontA, Ord:0036h    
|   
:0043DE17 FF1578104400 Call dword ptr [00441078]  

 

 

 

 

 













VC中函數的參數是倒着壓入堆棧中的,所以看的時候要倒過來看,熟悉一下CreateFont這個 函數:

HFONT CreateFont(
int nHeight, // logical height of font
int nWidth, // logical average character width
int nEscapement, // angle of escapement
int nOrientation, // base-line orientation angle
int fnWeight, // font weight
DWORD fdwItalic, // italic attribute flag
DWORD fdwUnderline, // underline attribute flag
DWORD fdwStrikeOut, // strikeout attribute flag
DWORD fdwCharSet, // character set identifier
DWORD fdwOutputPrecision, // output precision
DWORD fdwClipPrecision, // clipping precision
DWORD fdwQuality, // output quality
DWORD fdwPitchAndFamily, // pitch and family
LPCTSTR lpszFace // pointer to typeface name string
);


跟國家有關係的是fdwCharSet這個參數,顯然VOS把這個參數設成了HANGUL_CHARSET,所以在裝了 韓文字體的Windows下,VOS會顯示出韓文字。在VC的include目錄中,搜索HANGUL_CHARSET ,在wingdi.h中有:
#define HANGUL_CHARSET 129

129的十六進制是81,而0043DE17的那次CreateFont的CharSet是1,1是DEFAULT_CHARSET,所以不是我們的目標。
再看第一調用:

 

:0043DCD2 50 push eax //lpszFace
:0043DCD3 6A02 push 00000002 //fdwPitchAndFamily
:0043DCD5 83E180 and ecx, FFFFFF80  
:0043DCD8 6A00 push 00000000 //fdwQuality
:0043DCDA 6A00 push 00000000 //fdwClipPrecision
:0043DCDC 81C181000000 add ecx, 00000081 // <---源頭在這裏
:0043DCE2 6A00 push 00000000 //fdwOutputPrecision
:0043DCE4 51 push ecx //fdwCharSet <--- 犯人就是它!!!
:0043DCE5 6A00 push 00000000 //fdwStrikeOut
:0043DCE7 6A00 push 00000000 //fdwUnderline
:0043DCE9 6A00 push 00000000 //fdwItalic
:0043DCEB 52 push edx //fnWeight
:0043DCEC 6A00 push 00000000 //nOrientation
:0043DCEE 6A00 push 00000000 //nEscapement
:0043DCF0 6A00 push 00000000 //nWidth
:0043DCF2 6A48 push 00000048 //nHeight
:0043DCF4 6A5A push 0000005A  
:0043DCF6 57 push edi  
* Reference To: GDI32.GetDeviceCaps, Ord:0125h    
|   
:0043DCF7 FF1534104400 Call dword ptr [00441034]  
:……   
:* Reference To: GDI32.CreateFontA, Ord:0036h    
:0043DD0B FF1578104400 Call dword ptr [00441078]  
     


 

 

 

 

 

 

 

 

 

 









這次調用被VC優化過,參數都在前面設好了,GetDeviceCaps用到兩個參數,倒推上去,可以看到CharSet是通過寄存器CX設置的,所以只要在前面

:0043DCDC 81C181000000 add ecx, 00000081

改成

mov ecx, 1

nop

就可以了。

當我第一次在SoftIce裏改好後進入VOS,看到熟悉的中文,興奮之情難於言表。

2003-08-30  

by noword (歡迎轉載傳閱)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章