在 Win9x 中,可执行代码被划分权限等级,普通的应用程序代码处于 Ring3 级,不能直
接调用硬件中断,硬件中断被系统保护,只有处于 Ring0 级的代码才能够调用(就像过去
的 DOS 程序中的做法一样)。在 NT/2000 中没有 Ring0/Ring3 的概念,所以以下方法
不能在 NT/2000 中使用!在 NT/2000 中要使用 NT DDK 或者 WDM 驱动模型。
第一种方法:写一个 VxD 虚拟设备驱动程序,只在 Win9x 下有效,在 NT/2000 下无效。
主要是因为 VxD 代码处于系统 Ring0 级,与系统内核同级别,可以直接调用被系统保护
的硬件中断。
第二种方法:不使用 VxD 而直接使自己的代码进入系统 Ring0 级,目的是一样的。主要
是修改系统 IDT(中断描述表),可用于普通应用程序中。一旦自己的代码跳入 Ring0 级
别,就可以像设备驱动程序那样调用真正的硬件中断了。下面是在 C++ Builder 中的直接
跳入系统 Ring0 层的代码,供参考:
// =====================================================
#define IntNo 9
DWORDLONG IDTR, SavedGate;
WORD OurGate[4] = {0, 0x0028, 0xee00, 0x0000};
// =====================================================
// 系统Ring0层中执行的代码
void Ring0_Proc()
{
// 直接执行受系统保护的代码,如硬件中断
// ...
asm int 13h;
// ...
}
// =====================================================
// 新的中断函数
void __declspec(naked) NewInterrupt()
{
Ring0_Proc()
// 执行自己的Ring0函数
asm iretd
// 返回
}
// =====================================================
// 跳入系统Ring0的代码
void GotoRing0()
{
asm
{
mov eax,offset NewInt
mov [OurGate],ax
shr eax,16
mov [OurGate+6],ax
sidt fword ptr IDTR
mov ebx,dword ptr [IDTR+2]
add ebx,IntNo*8
mov edi,offset SavedGate
mov esi,ebx
movsd
movsd
mov edi,ebx
mov esi,offset OurGate
movsd
movsd
int IntNo
mov edi,ebx
mov esi,offset SavedGate
movsd
movsd
}
}
// ===================================================
void __fastcall TForm1::Button1Click(TObject *Sender)
{
// 按下窗体上某个按钮就执行Ring0级保护代码
GotoRing0();
}
// ===================================================
用 Delphi 改写一上代码要注意,Delphi 的编译器中内嵌的汇编器不是对所有的汇编指令
都有效的,对于某些汇编代码需要变通修改,不方便。C++ Builder 内嵌汇编使用的仍然是
TASM32 汇编器,兼容所有的 x86 汇编指令(MMX 和 3D Now! 除外)。以上方法在 NT/2000
中无效!