首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 組合語言

Windows 驅動開發:KMDKIT 環境下驅動程式的編譯與連結實戰指南

     編輯:組合語言

前言

Windows 驅動程式開發(KMDF/WDM)需要特殊的編譯鏈接選項:輸出 .sys 格式、指定基址、對齊、子系統為 NATIVE、連結 ntoskrnl.lib 等。KMDKIT (Kernel Mode Driver Kit) 提供了一種巧妙的「批處理 + 組合語言」混合腳本技巧,將編譯命令嵌入 `.bat` 檔案註釋中,雙擊即可完成編譯連結,極大簡化了開發流程。本文以經典的 ring0.sys 範例為例詳細說明。

混合腳本原理

Windows 批處理執行時會忽略以 `;` 開頭的行(視為註釋),而 MASM/TASM 組譯器則將 `;` 視為註釋標記。利用這一點,可在同一個檔案中同時包含:

  • 批處理命令(`:make` 標籤後的 `ml`、`link` 指令)
  • 組合語言源代碼(`;` 開頭的行)

組譯器會跳過批處理命令行(因為它們以 `;` 開頭),批處理會跳過組合語言指令行(因為它們不以 `:` 開頭且非有效命令)。雙擊 `.bat` 即觸發編譯。

ring0.bat 完整內容(含驅動源代碼)

;@echo off
;goto make
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 .586P                                              ; 保護模式指令集
 .model flat,stdcall
 option casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 include \masm32\include\w2k\ntddk.inc
; 中斷相關資料結構
 IDT_REG        STRUCT
     limit        WORD        ?
     base         DWORD       ?
 IDT_REG        ENDS

; 中斷描述符
 INT_DESCRIPTOR STRUCT
     offs0_15     WORD        ?
     sel          WORD        ?
     paramcnt     BYTE        ?
     attrs        BYTE        ?
     offs16_31    WORD        ?
 INT_DESCRIPTOR ENDS

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代碼段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 .code
 szBuffer       db       16 dup(0)
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 MyIntFunc      proc
     push       edx
     call       eax
     iretd
 MyIntFunc      endp

;====================================================================
 AddMyInt       proc       uses edi
     local      @IDT

 sidt           szBuffer
     mov        edi,(IDT_REG ptr [szBuffer]).base
     add        edi,21h*8        ; IDT 向量 0x21

 ; 使用 Int 0x21 中斷,該中斷在 Win2k 下未被使用
 ; cli
     mov        eax,offset MyIntFunc
     mov        [edi],ax
     shr        eax,16
     mov        [edi+6],ax       ; 設定入口位址高 16 位
     mov        [edi+2],cs       ; 設定段選擇子
     mov        WORD ptr [edi+4],0EE00h ; 設定 DPL=3 (Ring 3 可呼叫), Present=1, Type=0Eh (32-bit Interrupt Gate)
 ; sti

 ret
 AddMyInt       endp
;====================================================================
 WdmUnload      proc       DriverObject:DWORD
     local      @IDT

 sidt           szBuffer
     mov        edi,(IDT_REG ptr [szBuffer]).base
     add        edi,21h*8
     xor        eax,eax
     mov        [edi],ax
     mov        [edi+6],ax
     mov        [edi+2],ax
     mov        WORD ptr [edi+4],ax ; 清除 IDT 條目

 ret
 WdmUnload      endp
;====================================================================
 DriverEntry    proc       DriverObj:DWORD, RegistryPath:DWORD

     mov        eax,DriverObj
     assume     eax:ptr DRIVER_OBJECT
     mov        [eax].DriverUnload,offset WdmUnload
     assume     eax:nothing
     invoke     AddMyInt

     xor        eax,eax
     ret
 DriverEntry    endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 end DriverEntry

:make

 set drv=ring0

 \masm32\bin\ml /nologo /c /coff %drv%.bat
 \masm32\bin\link /nologo /driver /base:0x10000 /align:32 /out:%drv%.sys /subsystem:native %drv%.obj

 del %drv%.obj

 echo.
 pause
 rem =====以上為 ring0.bat 的內容=============

關鍵編譯連結參數解析

工具參數說明
ML.EXE/nologo隱藏版權資訊
/c僅編譯不連結
/coff輸出 COFF 格式 .obj (Win32/Win64 驅動必需)
LINK.EXE/nologo隱藏版權資訊
/driver建立驅動程式 (.sys),設定 subsystem=NATIVE, 入口點=DriverEntry
/base:0x10000指定映像基址 (驅動常用 0x10000 避開用戶模式衝突)
/align:32檔案區段對齊 32 位元組 (節省空間,驅動常用)
/out:xxx.sys輸出檔名
/subsystem:native原生子系統 (無 Win32 依賴)

驅動核心功能說明

  • AddMyInt:讀取 IDT 基址(SIDT),修改向量 0x21 的描述符,將處理器指向 MyIntFunc,設置 DPL=3 允許 Ring 3 通過 INT 21h 調用(Win2k 下此向量未使用)。
  • MyIntFunc:簡易存儲器,調用 EAX 指向的函數並 IRETD 返回。
  • WdmUnload:卸載時清除 IDT 條目,防止系統崩潰。
  • DriverEntry:註冊卸載例程,安裝中斷 Hook,返回成功。

使用步驟

  1. 安裝 MASM32 SDK(確保 `ml.exe`、`link.exe`、`ntddk.inc` 存在於 `\masm32\` 目錄)。
  2. 將上述內容存為 `ring0.bat`(需與 MASM32 位於同一磁碟分區,如皆在 C:)。
  3. 雙擊 `ring0.bat`,控制台顯示編譯連結過程,生成 `ring0.sys`。
  4. 修改代碼:右鍵 `ring0.bat` → 編輯,修改 `;` 開頭的組合語言部分,保存後再次雙擊編譯。

注意事項

  • 此範例為教學用途,實際驅動開發建議使用 WDK (Windows Driver Kit) + Visual Studio,支援簽名、靜態分析、部署測試完整流程。
  • 測試驅動需啟用測試簽名模式(bcdedit /set testsigning on)或使用正式簽章。
  • IDT Hook 在現代 Windows (PatchGuard, HVCI) 中會導致系統崩潰或被阻止,僅適用於舊版本或研究環境。

總結

KMDKIT 的批處理混合腳本技巧是早期驅動開發者智慧的結晶,將「編輯-編譯-測試」循環壓縮到雙擊一個檔案。雖然工具鏈已過時,但其核心思想——**將構建腳本與源代碼共存、零配置啟動**——在現代 `CMakeLists.txt`、`Makefile`、`package.json`、`build.ps1` 等構建腳本中依然閃耀著實用主義的光芒。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved