程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 令Win32應用程序跳入系統零層

令Win32應用程序跳入系統零層

編輯:關於C++

眾 所 周 知, 在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.?<

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved