令Win32应用程序跳入系统零层

众所周知,在Windows95/98的Win32onIntelx86体系中利用了处理器的三环保护模型中的零环(Ring0,最高权限级别)和三环(Ring3,最低权限级别)。

一般应用程序都运行在Ring3下,受到严格的”保护”,只能规矩地使用Win32API。如果我们想进行一些系统级的操作,例如在嵌入汇编中使用诸如”MovEAX,CR0″,或像在DOS下那样调用一些必不可少的系统服务(如BIOS,DPMI服务)而用”Intxx”,都会导致”非法操作”。但这种能力有时是必不可少的,一到这种时候Microsoft就”建议编写一个VxD”。

VxD大家早有所闻了,在VxD里,不但可以执行CPU的所有指令,而且可以调用VMM(虚拟机管理器)和其他VxD提供的上千个系统级服务。

获得这一能力的最本质原因在于它运行在Ring0,与系统内核同一级别。但是它体系的复杂性、开发工具的不易获得、帮助文档的不完备,使Microsoft排除了一大批程序员和竞争对手。

而将在Windows2000(Windows98也开始支持)中取代VxD的WDM对Win95程序员也是个噩梦,它需要了解WindowsNT核心驱动模型。

有没有简单一些的办法呢?我们可以令一个普通Win32应用程序运行在Ring0下,从而获得VxD的能力吗?答案是肯定的。下面我们就简述一下这一技巧,有关Intelx86保护模式的基础知识请大家看有关书籍。

首先此技巧基于以下理论根据:

一、SIDT指令(将中断描述符表寄存器IDTR--64位宽,16~47Bit存有中断描述符表IDT基地址--的内容存入指定地址单元)不是特权指令,就是说我们可以在Ring3下执行该指令,获得IDT的基地址,从而修改IDT,增加一个中断门安置我们的中断服务,一旦Ring3程序中产生此中断,VMM就会调用此中断服务程序,而此中断服务程序就运行在Ring0下了。这一点与在DOS下非常相似。

二、Windows95Win32应用程序运行一个映射到全部4G内存的段中,选择子为0137h,Ring0中的VxD运行在另一个映射到全部4G内存的段中,选择子028h,这两个段除了选择子决定的访问权限不同外,没什么不同,各自段中相同的偏移量对应了相同的线性地址。所以我们放在Win32应用程序中的中断服务程序可以以Ring3的段偏移量被Ring0中的VMM寻址。

下面我们以具体例子进一步说明,程序中有详细注释。

这是一个Win32ConsoleProgram(控制台应用程序),虽然运行中看起来很像DOS筐中运行的实模式DOS程序,但它是货真价实的运行在Ring3下的Win32程序。用VisualC++5.0AppWizard创建一个Win32ConsoleProgram项目,添加以下.CPP文件,编译即可。