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

Windows 核心驅動程式動態加載實戰:從 Service Control Program 到 Ring 0 突破

     編輯:組合語言

前言:驅動程式開發後的關鍵一步

編寫完核心模式驅動程式(Kernel Mode Driver, KMD)後,如何將其載入系統並執行?根據 Four-F 的經驗分享,主要有三種途徑:服務控制管理器(SCM)、服務控制程式(SCP)以及服務程式本身。本文將深入實作「服務控制程式(SCP)」這一方式,實現驅動程式的動態加載與卸載,並透過一個經典的蜂鳴器驅動範例,讓您親耳聽到 Ring 0 代碼直接操作硬體發出的聲音。

核心架構:SCP 與驅動的互動流程

SCP 是一個運行在用戶模式(Ring 3)的應用程式,它的任務是透過 Windows Service Control Manager (SCM) API,將驅動程式(.sys 檔案)註冊為系統服務,隨後啟動它。驅動程式載入後執行 DriverEntry,完成任務(如播放音樂)後主動返回錯誤狀態以觸發卸載,SCP 隨後清理服務註冊資訊。

關鍵 API 序列

  1. OpenSCManager:取得 SCM 資料庫控制代碼,要求 SC_MANAGER_CREATE_SERVICE 權限。
  2. GetFullPathName:解析驅動檔案(如 beeper.sys)的完整路徑,因 CreateService 需絕對路徑。
  3. CreateService:在 SCM 中建立服務記錄,類型為 SERVICE_KERNEL_DRIVER,啟動類型為 SERVICE_DEMAND_START(手動啟動)。
  4. StartService:觸發驅動載入,系統呼叫 DriverEntry。
  5. DeleteService / CloseServiceHandle:驅動執行完畢後移除服務定義並關閉代碼。

完整程式碼實作(MASM32 語法)

1. 用戶端加載器:scp.asm

;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; scp.asm - Service Control Program for beeper.sys driver
; Written by Four-F (four-f@mail.ru)
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
.386
.model flat, stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include \masm32\include\advapi32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\advapi32.lib
include \masm32\Macros\Strings.mac

.code
start proc
    local hSCManager:HANDLE
    local hService:HANDLE
    local acDriverPath[MAX_PATH]:CHAR

    ; 1. 連接 SCM
    invoke OpenSCManager, NULL, NULL, SC_MANAGER_CREATE_SERVICE
    .if eax != NULL
        mov hSCManager, eax

        ; 2. 取得驅動完整路徑
        push eax
        invoke GetFullPathName, $CTA0("beeper.sys"), sizeof acDriverPath, addr acDriverPath, esp
        pop eax

        ; 3. 註冊驅動服務
        invoke CreateService, hSCManager, $CTA0("beeper"), $CTA0("Nice Melody Beeper"), \
            SERVICE_START + DELETE, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, \
            SERVICE_ERROR_IGNORE, addr acDriverPath, NULL, NULL, NULL, NULL, NULL
        .if eax != NULL
            mov hService, eax

            ; 4. 啟動驅動 -> 此時 DriverEntry 執行,喇叭響起
            invoke StartService, hService, 0, NULL

            ; 5. 清理:移除服務註冊
            invoke DeleteService, hService
            invoke CloseServiceHandle, hService
        .else
            invoke MessageBox, NULL, $CTA0("Can't register driver."), NULL, MB_ICONSTOP
        .endif
        invoke CloseServiceHandle, hSCManager
    .else
        invoke MessageBox, NULL, $CTA0("Can't connect to Service Control Manager."), NULL, MB_ICONSTOP
    .endif

    invoke ExitProcess, 0
start endp
end start

2. 核心驅動程式:beeper.sys (來源於 beeper.bat 內嵌原始碼)

此驅動展示三種硬體存取方式:直接 I/O 埠操作、HAL 封裝函式、以及 HalMakeBeep 高層 API。DriverEntry 執行完畢後返回 STATUS_DEVICE_CONFIGURATION_ERROR,讓系統自動卸載驅動,實現「閃現式」執行。

;::: 核心片段 ::: 
TIMER_FREQUENCY equ 1193167
OCTAVE equ 2
PITCH_C equ 523
PITCH_E equ 659
PITCH_G equ 784
TONE_1 equ TIMER_FREQUENCY/(PITCH_C*OCTAVE)
TONE_2 equ TIMER_FREQUENCY/(PITCH_E*OCTAVE)
TONE_3 equ (PITCH_G*OCTAVE)
DELAY equ 1800000h

MakeBeep1 proc dwPitch:DWORD          ; 直接操作 8254 定時器與 61H 埠
    cli
    mov al, 10110110b
    out 43h, al
    mov eax, dwPitch
    out 42h, al
    mov al, ah
    out 42h, al
    in al, 61h
    or al, 3
    out 61h, al
    sti
    DO_DELAY
    cli
    in al, 61h
    and al, 0FCh
    out 61h, al
    sti
    ret
MakeBeep1 endp

DriverEntry proc pDriverObject:PDRIVER_OBJECT, pusRegistryPath:PUNICODE_STRING
    invoke MakeBeep1, TONE_1          ; Do
    invoke MakeBeep2, TONE_2          ; Mi (via HAL READ/WRITE_PORT_UCHAR)
    invoke HalMakeBeep, TONE_3        ; Sol (via HAL.DLL)
    DO_DELAY
    invoke HalMakeBeep, 0             ; 關閉
    mov eax, STATUS_DEVICE_CONFIGURATION_ERROR ; 強制卸載
    ret
DriverEntry endp

3. 編譯腳本:beeper.bat

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

實操步驟與驗證

  1. 進入 KmdKit\examples\simple\Beeper\ 目錄。
  2. 雙擊 beeper.bat 編譯產生 beeper.sys。
  3. 以一般 Win32 ASM 專案方式編譯 scp.asm 產生 scp.exe。
  4. 以系統管理員身份執行 scp.exe。

結果: 您將聽到主板蜂鳴器播放一段簡單的旋律(Do-Mi-Sol)。這證明了您的代碼已成功在 Ring 0 執行,直接控制了硬體 I/O 埠(0x42, 0x43, 0x61),突破了用戶模式的限制。

核心觀念總結

  • SCM 是守門人: 所有核心驅動必須透過 SCM 註冊才能合法載入。
  • 動態加載優勢: 無需重開機、無需修改註冊表 HKLM\System\CurrentControlSet\Services 即可即時測試驅動。
  • DriverEntry 返回錯誤碼: 是讓測試性驅動「用完即走」的經典技巧,避免殘留佔用資源。
  • HAL 層的意義: READ/WRITE_PORT_UCHAR 與 HalMakeBeep 提供了跨平台(如多處理器、不同晶片組)的硬體存取抽象層。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved