四通利方(RichWin)中文之星(CStar)是大家广为熟知的汉化Windows产品陷阱技术即动态修改Windows代码一直是其对外宣称的过人技术本文从Windows的模块调用机制与重定位概念着手介绍了陷阱技术的实现并给出了采用陷阱技术动态修改Windows代码的示例源程序 一发现了什么? 笔者多年来一直从事Windows下的软件开发工作经历了Windows 直至Windows NT的成长过程也遍历了长青窗口长城窗口DBWinCStarRichWin等多个Windows汉化产品从现在看来影响最大也最为成功的当推四通利方的RichWin;此外中文之星CStar与RichWin师出一门其核心技术自然也差不多其对外宣传采用独特的陷阱 技术即动态修改Windows代码一直是笔者感兴趣的地方 EXEHDR是Microsoft Visual C++开发工具中很有用的一个程序它可以检查NE(NewExe cutable)格式文件用它来分析RichWin的WSENGINEDLL或CStar的CHINESEDLL就会发现与众不同的两点(以CStar 为例): C:\CSTAR>exehdr chinesedll /v typeoffset targetBASEaseg offset PTReimp GDIGETCHARABCWIDTHSPTRbimp GDIENUMFONTFAMILIESPTRimp DISPLAY( EXTTEXTOUT )PTRimp KEYBOARD( TOASCII )PTRbaimp KEYBOARD( ANSITOOEM )PTRcimp KEYBOARD( OEMTOANSI )PTRdimp KEYBOARD( ANSITOOEMBUFF )PTRfimp USER( LSTRCMP )PTReimp KEYBOARD( OEMTOANSIBUFF )PTRimp USER( ANSIUPPER )PTRimp USER( ANSILOWER )PTRaaimp GDI( CREATEFONT )PTReimp USER( ISCHARALPHA )PTRbimp GDI( CREATEFONTINDIRECT )PTRdimp USER( ISCHARALPHANUMERIC )PTRcimp USER( GETSYSTEMMETRICS )PTRimp USER( ISCHARUPPER )PTRfimp USER( ISCHARLOWER )PTRimp USER( ANSIUPPERBUFF )PTRimp USER( ANSILOWERBUFF )PTRcimp GDI( DELETEOBJECT )PTRcimp GDI( ENUMFONTS )PTRabimp KERNELISDBCSLEADBYTEPTRdimp GDI( GETOBJECT )PTRdimp KERNEL( OPENFILE )PTRimp GDI( GETTEXTEXTENT )PTReimp GDI( GETTEXTFACE )PTRfimp GDI( GETCHARWIDTH )PTRimp GDI( EXTTEXTOUT )PTRimp USER( LSTRCMPI )PTRfimp USER( ANSINEXT )PTRimp USER( ANSIPREV )PTRimp USER( GETMESSAGE )PTRimp USER( PEEKMESSAGE ) relocations (括号内为笔者加上的对应Windows API函数) 第一在数据段中发现了重定位信息 第二这些重定位信息提示的函数全都与文字显示输出和键盘字符串有关也就是说汉化Windows必须修改这些函数 在这非常特殊的地方隐藏着什么呢?毋庸置疑这与众不同的两点对打开陷阱技术之门而言不是金钥匙也是敲门砖 二Windows的模块调用机制与重定位概念 为了深入探究陷阱技术我们先来介绍Windows的模块调用机制 Windows的运行分实模式标准模式和增强模式三种虽然这几种模式各不相同但其核心模块的调用关系却是完全一致的见图一 主要的三个模块有如下的关系: ·KERNEL是Windows系统内核它不依赖其它模块 ·GDI是Windows图形设备接口模块它依赖于KERNEL模块 ·USER是Windows用户接口服务模块它依赖于KERNELGDI模块及设备驱动程序等所有模块 这三个模块实际上就是Windows的三个动态链接库KERNEL有三种系统存在形式:Kern elexe(实模式)Krnlexe(标准模式)Krnlexe(增强模式);GDI模块是Gdiex e;USER模块是Userexe虽然文件名都以EXE为扩展名但它们实际都是动态链接库 同时几乎所有的API函数都隐藏在这三个模块中用EXEHDR对这三个模块分析就可列出一大堆大家所熟悉的Windows API函数 以GDI模块为例运行结果如下: C:\WINDOWS\SYSTEM>exehdr gdiexe Exports: rd seg offset name e EXTTEXTOUT exported shared data e CREATEFONT exported shared data 至此读者已能从Windows纷繁复杂的系统中理出一些头续来下面再引入一个重要概念——重定位 一个Windows执行程序对调用API函数或对其它动态库的调用在程序装入内存前都是一些不能定位的动态链接;当程序调入内存时这些远调用都需要重新定位重新定位的依据就是重定位表在Windows执行程序(包括动态库)的每个段后面通常都跟有这样一个重定位表重定位包含调用函数所在模块函数序列号以及定位在模块中的位置 例如用EXEHDR /v 分析CHINESEDLL得到: type offset target PTR imp GDI 就表明在本段的H偏移处调用了GDI的第号函数如果在H处是:FFFF 表示本段内仅此一处调用了GDI函数;否则表明了本段内还有一处调用此函数调用的位置就是H处所指向的内容实际上重定位表只含有引用位置的链表的链头那么GDI 是一个什么函数呢?用EXEHDR对GDIEXE作一分析就可得出在GDI的出口(Export)函数中第号是ExtTextOut 这样我们在EXEHDR这一简单而非常有用的工具帮助下已经在Windows的浩瀚海洋中畅游了一会下面让我们继续深入下去 三动态汉化Windows原理 我们知道传统的汉化Windows的方法是要直接修改Windows的显示输入打印等模块代码或用DDK直接开发中文设备驱动模块这样不仅工作量大而且系统的完备性很难保证性能上也有很多限制(早期的长青窗口就是如此)所以只有从内核上修改Windows核心代码才是最彻底的办法 从Windows的模块调用机制我们可以看到Windows实际上是由包括在KERNELGDIUS ER等几个模块中的众多函数支撑的那么修改其中涉及语言文字处理的函数使之能适应中文需要不就能达到汉化目的了吗? 因而我们可以得出这样的结论:在自己的模块中重新编写涉及文字显示输入的多个函数然后将Windows中对这些函数的引用改向到自己的这些模块中来修改哪些函数才能完成汉化这需要深入分析Windows的内部结构但CHINESEDLL已明确无误地告诉了我们在其数据段的重定位表中列出的引用函数正是CStar修改了的Windows函数!为了验证这一思路 我们利用RichWin作一核实 用EXEHDR分析GDIEXE得出ExtTextOut函数在GDI的第一代码段H偏移处(不同版本的Windows其所在代码段和偏移可能不一样)然后用HelpWalk(也是Microsoft Visual C+ +开发工具中的一个)检查GDI的Code段H处前个字节是 B FF 经过运行Ri chWin for Internet后再查看同样的地方已改为 EA F D其实反汇编就知道这个字节就是 Jmp DF:而句柄为xDF的模块用HelpWalk能观察正是RichWin 的WSENGINEDLL的第一代码段( 模块名为TEXTMAN)而偏移H处 B B D B E C E正是一个函数起始的地方这实际上就是RichWin所重改写的ExtTextOut函数退出Ri chWin后再用HelpWalk观察GDI的Code代码段一切又恢复正常!这与前面的分析结论完全吻合!那么下一个关键点就是如何动态修改Windows的函数代码也就是汉化Windows的核心——陷阱技术 四陷阱技术 讨论陷阱技术还要回到前面的两个发现发现之二已能解释为修改的Windows函数而发现之一却仍是一个迷 数据段存放的是变量及常量等内容如果这里面包含有重定位信息那么必定要在变量说明中将函数指针赋给一个FARPROC类型的变量于是在变量说明中写下: FARPROC FarProcFunc=ExtTextOut; 果然在自己程序的数据段中也有了重定位信息这样当程序调入内存时变量FarPro cFunc已是函数ExtTextOut的地址了 要直接修改代码段的内容还遇到一个难题就是代码段是不可改写的这时需要用到一个未公开的Windows函数AllocCStoDSAlias取得与代码段有相同基址的可写数据段别名 其函数声明为: WORD FAR PASCAL AllocCStoDSAlias(WORD code_sel); 参数是代码段的句柄返回值是可写数据段别名句柄 Windows中函数地址是位高字节是其模块的内存句柄低字节是函数在模块内的偏移将得到的可写数据段别名句柄锁定再将函数偏移处的个字节保留下来然后将其改为转向替代函数(用 EA Jmp): *(lpStr+wOffset) =xEA; 四通利方(RichWin)中文之星(CStar)是大家广为熟知的汉化Windows产品陷阱技术即动态修改Windows代码一直是其对外宣称的过人技术本文从Windows的模块调用机制与重定位概念着手介绍了陷阱技术的实现并给出了采用陷阱技术动态修改Windows代码的示例源程序 //源程序 relocatec#include <WINDOW |