动态修改Windows内核

动态修改Windows内核

如前所述, Windows95 不是一个“纯” 32 位操作系统,其内核模块中的 USER GDI 均是用 16 位代码实现的。 USER32.DLL GDI32.DLL 只是 16 位的 USER.EXE GDI.EXE 32 位调用接口。因此,如果屏幕截获程序用 32 位代码实现,则只能截获 32 位应用程序对 USER32.DLL GDI32.DLL 的调用,无法截获 16 位应用程序对 USER.EXE GDI.EXE 的调用,所以如果想截获所有应用程序(包括 Windows95 的桌面程序 Explorer )中有关屏幕输出的系统调用,则应该用 16 位代码实现屏幕截获功能。这就是 LTW32 为什么不是“纯” 32 位应用程序的原因。 LTW32 主要截获两个系统调用 TextOut() ExtTextOut() ,方法很简单,把这两个函数的头五个字节修改为一个 JMP FAR 指令,使得对这两个函数的调用均转向屏幕截获程序。这就涉及到一个关键问题:动态修改 Windows 的代码。

在传统的 DOS 程序中,动态修改程序代码无任何困难,但在 Windows 中则不然,因为在 Windows 中,代码可被同一程序的多个实例(进程)共享,所以系统不允许应用程序动态的修改代码。在 16 位侧,内存的可读、写属性是与段选择符联系在一起的。段选择符基本上可分为两类:数据段选择符和代码段选择符。前者可读、可写、不可执行;后者可读、可执行、不可写。 Windows 提供了这两类段选择符相转换的系统调用。未公开的 16 位系统调用 AllocCStoDSAlias() 为给定的代码段选择符分配一个具有相同线性基址和尺寸的数据段别名( DS Alias )。通过 DS 别名可以对给定的代码段进行修改。 AllocCStoDSAlias() 的使用方法如下:

WORD (FAR PASCAL *AllocCStoDSAlias)(WORD);

AllocCStoDSAlias = GetProcAddress(

GetModuleHandle(“KERNEL”), ”ALLOCCSTODSALIAS”);

调用参数为给定的代码选择符,调用成功时返回一个线性基址和尺寸均与原代码选择符相同的 DS 别名。当不再使用此 DS 别名时,要用系统调用 FreeSelector() DS 别名释放掉。

使用上述技术,就可实现动态修改 Windows 代码,从而改变 GDI 的系统调用 TextOut() ExtTextOut() 的执行动作,实时地截获屏幕输出,为实现鼠标随动翻译提供可能。

把上述的 32 位到 16 位的形式替换、 32 位代码与 16 位代码的数据交换、动态修改 Windows 内核等技术综合应用在一起,配合单词查找算法和词组分析算法就可以实现鼠标随动翻译功能。

你可能感兴趣的:(动态修改Windows内核)