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 (欢迎转载传阅)

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