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

Win32 組合語言 DeviceIoControl 介面完整實戰:動態 VxD 與 Ring-3 應用程式通訊

     編輯:組合語言

前言

DeviceIoControl 是 Win32 應用程式與動態 VxD 通訊的標準橋樑,實現 Ring-3 到 Ring-0 的受控呼叫。本文完整解析四大 VxD 介面架構、DeviceIoControl 參數結構、DIOCParams 解析、最小動態 VxD 框架與完整計算機啟動範例,掌握核心模組開發關鍵技術。

VxD 四大介面架構總覽

介面呼叫者位元寬度用途
VxD ServicesVxD 間、VMM32-bit核心服務呼叫(VMMCall/VxDCall)
V86 InterfaceV86 模式程式16-bitDOS/Win16 應用呼叫 VxD
Protected-Mode Interface保護模式 16-bit 程式16-bitWin16 DLL/驅動呼叫 VxD
Win32 DeviceIoControlWin32 應用程式32-bit標準 Ring-3 ↔ Ring-0 通道

Win32 應用程式端:CreateFile + DeviceIoControl

開啟 VxD

invoke CreateFile, addr VxDName, 0, 0, 0, 0, \
    FILE_FLAG_DELETE_ON_CLOSE, 0
; VxDName = "\\.\shellmsg.vxd"
; 成功 → EAX = 裝置控制代碼
; 失敗 → EAX = INVALID_HANDLE_VALUE
  • FILE_FLAG_DELETE_ON_CLOSE:關閉控制代碼時自動卸載 VxD。
  • 路徑格式:\\.\完整路徑 或 \\.\檔名(同目錄)。

發送控制碼

invoke DeviceIoControl, hVxD, 1, addr InBuffer, 8, \
    NULL, NULL, NULL, NULL
; hVxD           : CreateFile 回傳控制代碼
; 1              : dwIoControlCode (自訂操作碼)
; addr InBuffer  : 輸入緩衝區位址
; 8              : nInBufferSize (位元組)
; NULL...        : 無輸出緩衝區

VxD 端:處理 W32_DeviceIoControl

DIOCParams 結構解析

收到訊息時 ESI 指向此結構:

DIOCParams STRUC
    Internal1       DD ?  ; Win32 用戶暫存器結構指標
    VMHandle        DD ?  ; 虛擬機控制代碼
    Internal2       DD ?  ; DDB 指標
    dwIoControlCode DD ?  ; 控制碼 (對應 DeviceIoControl 第 2 參數)
    lpvInBuffer     DD ?  ; 輸入緩衝區線性位址
    cbInBuffer      DD ?  ; 輸入緩衝區大小
    lpvOutBuffer    DD ?  ; 輸出緩衝區線性位址
    cbOutBuffer     DD ?  ; 輸出緩衝區大小
    lpcbBytesReturned DD ? ; 實際寫入輸出位元組數指標
    lpoOverlapped   DD ?  ; OVERLAPPED 結構指標
    hDevice         DD ?  ; Ring-3 裝置控制代碼
    tagProcess      DD ?  ; 處理序標記
DIOCParams ENDS

最小動態 VxD 框架

.386p
include vmm.inc
include vwin32.inc

DECLARE_VIRTUAL_DEVICE DYNAVXD, 1, 0, DYNAVXD_Control, \
    UNDEFINED_DEVICE_ID, UNDEFINED_INIT_ORDER

Begin_Control_Dispatch DYNAVXD
    Control_Dispatch W32_DeviceIoControl, OnDeviceIoControl
End_Control_Dispatch DYNAVXD

VxD_PAGEABLE_CODE_SEG
BeginProc OnDeviceIoControl
    assume esi:ptr DIOCParams
    .if [esi].dwIoControlCode == DIOC_Open
        xor eax, eax          ; 允許開啟
    .endif
    ret
EndProc OnDeviceIoControl
VxD_PAGEABLE_CODE_ENDS
end
  • 必須處理 DIOC_Open(CreateFile 觸發),回傳 EAX=0 表示成功。
  • 關閉時會收到 DIOC_CloseHandle。

完整範例:ShellMsg.vxd — 從 VxD 彈出系統模態訊息框

Win32 呼叫端 (VxDLoader.asm)

.data
VxDName db "\\.\shellmsg.vxd",0
InBuffer dd offset MsgTitle
         dd offset MsgText
MsgTitle db "DeviceIoControl Example",0
MsgText  db "I'm called from a VxD!",0
.code
invoke CreateFile, addr VxDName, 0,0,0,0, FILE_FLAG_DELETE_ON_CLOSE, 0
.if eax != INVALID_HANDLE_VALUE
    mov hVxD, eax
    invoke DeviceIoControl, hVxD, 1, addr InBuffer, 8, NULL, NULL, NULL, NULL
    invoke CloseHandle, hVxD
.endif

VxD 端 (ShellMsg.asm) 核心邏輯

VxD_PAGEABLE_DATA_SEG
pTitle dd ?
pMessage dd ?
VxD_PAGEABLE_DATA_ENDS

VxD_PAGEABLE_CODE_SEG
BeginProc OnDeviceIoControl
    assume esi:ptr DIOCParams
    .if [esi].dwIoControlCode == DIOC_Open
        xor eax, eax
    .elseif [esi].dwIoControlCode == 1        ; 自訂控制碼 1
        mov edi, [esi].lpvInBuffer            ; EDI → InBuffer 陣列
        ; 複製標題字串
        VMMCall _lstrlen, <[edi]>
        inc eax
        push eax
        VMMCall _HeapAllocate, <eax, HEAPZEROINIT>
        mov pTitle, eax
        pop eax
        VMMCall _lstrcpyn, <pTitle, [edi], eax>
        ; 複製內文字串
        VMMCall _lstrlen, <[edi+4]>
        inc eax
        push eax
        VMMCall _HeapAllocate, <eax, HEAPZEROINIT>
        mov pMessage, eax
        pop eax
        VMMCall _lstrcpyn, <pMessage, [edi+4], eax>
        ; 彈出系統模態訊息框
        mov edi, pTitle
        mov ecx, pMessage
        mov eax, MB_OK
        VMMCall Get_Sys_VM_Handle
        VxDCall SHELL_sysmodal_Message
        ; 釋放記憶體
        VMMCall _HeapFree, pTitle, 0
        VMMCall _HeapFree, pMessage, 0
        xor eax, eax
    .endif
    ret
EndProc OnDeviceIoControl
VxD_PAGEABLE_CODE_ENDS

關鍵技術點

  1. 跨 Ring 字串複製:Ring-3 位址不可直接存取,需 _lstrlen 取長 → _HeapAllocate 配置 Ring-0 堆疊 → _lstrcpyn 複製內容。
  2. 系統模態訊息框:SHELL_sysmodal_Message 凍結整個系統直到使用者回應,需 Get_Sys_VM_Handle 取得系統 VM 控制代碼。
  3. 記憶體管理:用畢必呼叫 _HeapFree 釋放,避免核心記憶體洩漏。

模組定義檔 (ShellMsg.def)

VXD SHELLMSG DYNAMIC
SEGMENTS
... (標準段定義)
EXPORTS
SHELLMSG_DDB @1

建置與測試

; VxD
ml -coff -c -Cx -DMASM6 -DBLD_COFF -DIS_32 shellmsg.asm
link -vxd -def:shellmsg.def shellmsg.obj

; Loader
ml /coff /c /Cp vxdloader.asm
link /subsystem:windows vxdloader.obj

執行 vxdloader.exe,點擊按鈕 → 載入 VxD → 彈出「I'm called from a VxD!」系統模態對話框 → 關閉 → 卸載 VxD。

總結

DeviceIoControl 介面讓動態 VxD 成為 Win32 應用程式的 Ring-0 DLL 延伸,適用於硬體存取、即時處理、系統級監控等場景。核心要點:正確處理 DIOC_Open、解析 DIOCParams、跨 Ring 緩衝區複製、嚴格記憶體管理。本文範例提供最小框架與完整實戰範本,可直接作為專案起始點。

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