Windows 95/98 使用 x86 保護模式 Ring 0 (核心) 與 Ring 3 (應用程式)。一般應用程式無法執行特權指令或呼叫 BIOS/DPMI 服務。本文示範利用 SIDT 取得 IDT 基址,修改中斷描述符安裝自訂中斷服務程式 (ISR),觸發中斷後由 VMM 在 Ring 0 呼叫 ISR,從而獲得核心權限。
SIDT 非特權指令,Ring 3 可執行,可讀取 IDTR 取得 IDT 基址。#include <stdio.h>
#include <conio.h>
// 若無 DDK 可略去底線開頭的 VMM 服務呼叫示範
DWORDLONG IDTR, SavedGate;
WORD OurGate[4] = {0, 0x0028, 0xee00, 0x0000}; // 中斷門描述符
DWORD _eax, _ecx, _cr0;
WORD vmmver;
HVM sysvm;
void nothing() { sysvm = Get_Sys_VM_Handle(); } // 測試 Ring 0 呼叫子程式
void __declspec(naked) Ring0Proc(void) // 中斷服務程式,運行於 Ring 0
{
_asm {
mov _eax, eax
mov _ecx, ecx
mov eax, CR0 // 測試 Ring 3 無法執行的特權指令
mov _cr0, eax
}
VMMCall(Get_VMM_Version); // 呼叫 VMM 服務
_asm { mov vmmver, ax }
nothing(); // 測試在 Ring 0 呼叫子程式
_asm iretd // 中斷返回
}
void main()
{
_asm {
mov eax, offset Ring0Proc
mov [OurGate], ax
shr eax, 16
mov [OurGate+6], ax // 填入中斷門描述符
sidt fword ptr IDTR // 取得 IDTR
mov ebx, dword ptr [IDTR+2] // 取得 IDT 基址
add ebx, 8*9 // 定位 Int 9 描述符 (Win32 下未使用)
mov edi, offset SavedGate
mov esi, ebx
movsd // 備份原 Int 9 描述符
movsd
mov edi, ebx
mov esi, offset OurGate
movsd // 替換為自訂中斷門
movsd
mov eax, 0x6200 // 測試資料傳遞
mov ecx, 0
int 9h // 人為觸發中斷 -> 進入 Ring0Proc
mov edi, ebx
mov esi, offset SavedGate
movsd // 還原原 Int 9 描述符
movsd
}
printf("CR0=%x\n", _cr0);
_getch();
}
Int 9 (鍵盤中斷) 因 Win32 保護模式下未佔用。__declspec(naked) 函數中手寫組語,編譯器不產生序言/結語。