前置知識需求
本文假設讀者熟悉 x86 保護模式核心概念:
- 特權等級 (Ring 0 / Ring 3)
- 虛擬 8086 模式 (V86 Mode)
- 分頁機制、GDT/LDT/IDT 描述符表
- 中斷門/陷阱門/任務門
若不熟悉,請先研讀 Intel 開發者手冊 (developer.intel.com)。
Windows 9x 架構核心:VMM 才是真正的老大
許多人誤以為 kernel32.dll, user32.dll, gdi32.dll 運行在 Ring 0。**錯誤!** 它們和應用程式一樣運行在 Ring 3。**系統實際控制權掌握在:**
- VMM (Virtual Machine Manager):32-bit 保護模式核心,運行在 Ring 0,負責建立/管理虛擬機 (VM)、排程 CPU 時間、提供核心服務。
- VxD (Virtual Device Drivers):運行在 Ring 0 的模組,虛擬化硬體 (如 VKD 虛擬鍵盤, VMD 虛擬滑鼠)、提供 Ring 0 服務給其他 VxD 或透過
DeviceIoControl 給 Ring 3 應用。
為什麼需要虛擬機 (VM)?
歷史包袱:Windows 3.x 必須同時運行 Windows 程式 (合作式多工) 和 DOS 程式 (獨佔硬體、無多工概念)。
解法:
- System VM:單一特殊 VM,運行 Windows 核心 (krnl386.exe) 與所有 Win16/Win32 應用。這些應用之間用合作式多工 (GetMessage/PeekMessage)。
- DOS VMs:每個 DOS 應用獨佔一個 V86 模式 VM,自以為擁有完整硬體 (鍵盤、螢幕、硬碟、中斷向量表)。
- VMM 在 VM 之間進行**優先權搶佔式多工**分派 CPU 時間。
虛擬機本質:軟體模擬的「假硬體」。DOS 程式透過中斷 (INT 21h)、BIOS 呼叫、I/O 埠存取硬體,VxD 截獲並模擬這些行為,讓 DOS 程式以為自己在真機上運行。
Windows 95 啟動流程 (關鍵節點)
- 載入
IO.SYS。
- 執行
CONFIG.SYS / AUTOEXEC.BAT。
- 呼叫
WIN.COM。
WIN.COM 執行 VMM32.VXD (實為 DOS EXE 格式)。
VMM32.VXD 透過 XMS 驅動將 VMM 核心載入擴展記憶體。
- VMM 初始化自身與預設 VxD,**進入保護模式,建立 System VM**。
- 最後載入的 Virtual Shell Device 在 System VM 執行
KERNL386.EXE 啟動 Windows 圖形介面。
KERNL386.EXE 載入所有系統 DLL,最後載入 Shell (Explorer)。
關鍵點:VMM 是**第一個**載入記憶體的 VxD,它是所有 VxD 的監控者與服務提供者。
VxD 運作模式:潛伏喚醒
- 大部分時間**潛伏** (不佔用 CPU)。
- 特定**中斷/異常/事件**發生時被喚醒處理。
- VMM **不可重入** (Non-reentrant):VxD 呼叫 VMM 服務時必須同步,不可在 VMM 處理硬體中斷時再次進入 VMM (會導致系統死機)。
- 代碼運行在 Ring 0,**無任何保護**,一行錯誤代碼即藍畫面 (BSOD)。
VxD 分類:靜態 vs 動態
| 類型 | 載入時機 | 卸載 | 適用場景 |
| 靜態 VxD | 開機啟動階段 (VMM 初始化時) | 關機前常駐記憶體 | 核心虛擬裝置 (VPICD, VTD, VCD 等)、Win3.x 相容 |
| 動態 VxD | 執行期按需載入 (Win32 應用呼叫 CreateFile) | 可隨時卸載 (CloseHandle + FILE_FLAG_DELETE_ON_CLOSE) | Plug-and-Play 設備、特定功能擴充、除錯工具 |
VxD 間三大通訊機制
1. 控制訊息 (Control Messages)
- VMM 廣播系統事件給所有已載入 VxD (如
Sys_VM_Init, Device_Init, Sys_Critical_Init... 共 50+ 種)。
- 每個 VxD 必須實作 **Device Control Procedure** 處理。
- 訊息少是為了效能:太多訊息會拖慢系統 (每個 VxD 都要處理)。
- VxD 可定義私有控制訊息供特定 VxD 間通訊。
2. 服務 API (VxD Services) — 核心機制
- VxD (含 VMM) 導出公開函式供其他 VxD 呼叫。
- **呼叫機制**:
INT 20h + 雙字參數 (高字 = Device ID, 低字 = Service Index)。
- Device ID 範例:
VMM_DEVICE_ID equ 1, VPICD_DEVICE_ID equ 3, VDMAD_DEVICE_ID equ 4... 向 Microsoft 申請唯一 ID。
- VMM 抓取優化:首次
INT 20h 成功後,VMM 將呼叫點修補為 CALL [Service_Address] (同樣 6 bytes),後續直接跳轉,極快。
- 致命限制:一旦靜態 VxD 服務被抓取,**該 VxD 永不可卸載** (否則 Call 會跳到無效位址崩潰)。**動態 VxD 不適合做服務提供者**。
3. 回呼函式 (Callbacks)
- 私有函式,VxD 在特定情況將函式指標傳給其他 VxD (如 VMM)。
- 用途:VxD 處理硬體中斷時不可呼叫 VMM 服務 (會重入),改將回呼函式登記給 VMM,待 VMM 可重入時由 VMM 主動呼叫。
- 類比:Windows 視窗程序 (
WndProc)、SetWindowsHookEx 鉤子程序。
VxD 對應用程式的四種介面
- VxD Services:給其他 VxD (Ring 0) 用。
- V86 Interface:給 V86 模式程式 (DOS 應用) 用,透過中斷向量表攔截。
- Protected Mode (PM) Interface:給 16-bit 保護模式程式 (Win16 應用) 用,透過 Call Gates。
- Win32 DeviceIoControl Interface:**給 Win32 應用 (Ring 3) 用**,下一篇重點講解。
總結:VxD 開發鐵律
- 三思而後行:能在 Ring 3 做的事 (用戶模式 DLL、驅動模型如 WDM/KMDF) 絕不寫 VxD。
- 不可移植:VxD 僅存在 Windows 9x/Me,**Windows NT 系列 (2000/XP/Vista/7/10/11) 完全不支援**。
- 極度危險:無保護機制,惡意/錯誤 VxD 可摧毀整個系統。
- 同步至上:VMM 不可重入,所有共享資料存取必須用 VMM 提供的同步原語 (Mutex, Semaphore, Spinlock)。
- 上一篇文章: ListView 控件完全掌握:報表模式、欄位排序、圖示切換與雙擊回應實戰
- 下一篇文章: 動態 VxD 實戰:Win32 DeviceIoControl 介面讓 Ring 3 應用呼叫 Ring 0 代碼
Copyright ©
程式碼之家 All Rights Reserved