眾 所 周 知, 在Windows95/98 的Win32 on Intel x86 體 系 中 利 用 了 處 理 器 的 三 環 保 護 模 型 中 的 零 環(Ring0, 最 高 權 限 級 別) 和 三 環(Ring3, 最 低 權 限 級 別)。 一 般 應 用 程 序 都 運 行 在Ring3 下, 受 到 嚴 格 的" 保 護", 只 能 規 矩 地 使 用Win32API。 如 果 我 們 想 進 行 一 些 系 統 級 的 操 作, 例 如 在 嵌 入 匯 編 中 使 用 諸 如"Mov EAX,CR0", 或 像 在DOS 下 那 樣 調 用 一 些 必 不 可 少 的 系 統 服 務( 如BIOS,DPMI 服 務) 而 用"Int xx", 都 會 導 致" 非 法 操 作"。 但 這 種 能 力 有 時 是 必 不 可 少 的, 一 到 這 種 時 候Microsoft 就 " 建 議 編 寫 一 個VxD"。VxD 大 家 早 有 所 聞 了, 在VxD 裡, 不 但 可 以 執 行CPU 的 所 有 指 令, 而 且 可 以 調 用VMM( 虛 擬 機 管 理 器) 和 其 他VxD 提 供 的 上 千 個 系 統 級 服 務。 獲 得 這 一 能 力 的 最 本 質 原 因 在 於 它 運 行 在Ring0, 與 系 統 內 核 同 一 級 別。 但 是 它 體 系 的 復 雜 性、 開 發 工 具 的 不 易 獲 得、 幫 助 文 檔 的 不 完 備, 使Microsoft 排 除 了 一 大 批 程 序 員 和 競 爭 對 手。 而 將 在Windows2000(Windows98 也 開 始 支 持) 中 取 代VxD 的WDM 對Win95 程 序 員 也 是 個 噩 夢, 它 需 要 了 解Windows NT 核 心 驅 動 模 型。
----有 沒 有 簡 單 一 些 的 辦 法 呢 ? 我 們 可 以 令 一 個 普 通Win32 應 用 程 序 運 行 在Ring0 下, 從 而 獲 得VxD 的 能 力 嗎 ? 答 案 是 肯 定 的。 下 面 我 們 就 簡 述 一 下 這 一 技 巧, 有 關Intel x86 保 護 模 式 的 基 礎 知 識 請 大 家 看 有 關 書 籍。
----首 先 此 技 巧 基 於 以 下 理 論 根 據:
----一、SIDT 指 令( 將 中 斷 描 述 符 表 寄 存 器 IDTR - -64 位 寬,16 ~47Bit 存 有 中 斷 描 述 符 表IDT 基 地 址 - - 的 內 容 存 入 指 定 地 址 單 元) 不 是 特 權 指 令, 就 是 說 我 們 可 以 在Ring3 下 執 行 該 指 令, 獲 得IDT 的 基 地 址, 從 而 修 改IDT, 增 加 一 個 中 斷 門 安 置 我 們 的 中 斷 服 務, 一 旦Ring3 程 序 中 產 生 此 中 斷,VMM 就 會 調 用 此 中 斷 服 務 程 序, 而 此 中 斷 服 務 程 序 就 運 行 在Ring0 下 了。 這 一 點 與 在DOS 下 非 常 相 似。
----二、Windows95 Win32 應 用 程 序 運 行 一 個 映 射 到 全 部4G 內 存 的 段 中, 選 擇 子 為0137h,Ring0 中 的VxD 運 行 在 另 一 個 映 射 到 全 部4G 內 存 的 段 中, 選 擇 子028h, 這 兩 個 段 除 了 選 擇 子 決 定 的 訪 問 權 限 不 同 外, 沒 什 麼 不 同, 各 自 段 中 相 同 的 偏 移 量 對 應 了 相 同 的 線 性 地 址。 所 以 我 們 放 在Win32 應 用 程 序 中 的 中 斷 服 務 程 序 可 以 以Ring3 的 段 偏 移 量 被Ring0 中 的VMM 尋 址。
----下 面 我 們 以 具 體 例 子 進 一 步 說 明, 程 序 中 有 詳 細 注 釋。
----這 是 一 個Win32 Console Program( 控 制 台 應 用 程 序), 雖 然 運 行 中 看 起 來 很 像DOS 筐 中 運 行 的 實 模 式DOS 程 序, 但 它 是 貨 真 價 實 的 運 行 在Ring3 下 的Win32 程 序。 用Visual C + + 5.0 AppWizard 創 建 一 個Win32 Console Program 項 目, 添 加 以 下.CPP 文 件, 編 譯 即 可。
#include
#include
#include
#include
// 若 無DDK 帶 下 劃 線 的 可 略 去,
這 些 語 句 演 示 了 調 用VMM/VXD 服 務
DWORDLONG IDTR,SavedGate;
WORD OurGate[4]={0,0x0028,0xee00,0x0000};
// 中 斷 門 描 述 符 格 式 如 下:
DWORD _eax,_ecx,_cr0;
WORD vmmver;
HVM sysvm;
void nothing()
{
//Used to test call in Ring0
sysvm=Get_Sys_VM_Handle();
}
void __declspec( naked ) Ring0Proc(void)
// 中 斷 例 程, 運 行 在Ring0
{
_asm{
mov _eax,eax //
mov _ecx,ecx //
mov eax, CR0
// 測 試Ring3 中 不 能 執 行 的 特 權 指 令
mov _cr0,eax //
}
VMMCall(Get_VMM_Version);
// 調 用VMM 服 務
_asm{
mov vmmver,ax
}
nothing();
// 測 試 在 運 行 於Ring0 的
中 斷 例 程 中 調 用 子
_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 的 描 述 符 應 放 置 的 地 址 選 用
Int9 是 因 為 它 在Win32 保 護 模 式 下 未 占 用
mov edi, offset SavedGate
mov esi, ebx
movsd // 保 存 原 來 的Int 9 描 述 符 到
movsd //SavedGate 以 便 恢 復
mov edi, ebx
mov esi, offset OurGate
movsd // 替 換 原 來 的 中 斷 門 描 述 符
movsd // 以 安 裝 中 斷 服 務 例 程
mov eax,0x6200
// 用 以 測 試 放 在EAX 中 的 數 據
能 否 正 確 傳 到Ring0 中 斷
mov ecx,0
// 用 以 測 試 放 在ECX 中 的 數 據
能 否 正 確 傳 到Ring0 中 斷
mov ecx,0
// 用 以 測 試 放 在ECX 中 的 數 據
能 否 正 確 傳 到Ring0 中 斷
// 因 為 很 多VxD 服 務 都 用
此 二 寄 存 器 傳 遞 參 數
int 9h
// 人 為 觸 發 中 斷, 平 時 會 出 現
保 護 錯 誤 藍 屏 或 非 法 操
// 作 對 話 框, 現 在 安 裝 了
// 中 斷 服 務 例 程 後, 就 會 通 過
//VMM 在Ring0 調 用 中 斷 服 務 例 程
- -Ring0Proc
mov edi, ebx
mov esi, offset SavedGate
movsd // 恢 復 原 來 的 中 斷 門 描 述 符
movsd
}
cout<<"CR0="<<_cr0< } _getch(); if(0="=_getch())" while(_kbhit()="=0);" do{} continue.?<