客戶暫存器結構(轉)
我們將學習本教程中另外一個重要的結構,叫客戶暫存器結構。在本文中,V86指虛擬8086模式。在這裡下載例子程式
理論
VxDs與正常的win32/win16/DOS應用程式有很大不同。大多數情況下,當其他應用程式正常工作時,它們是休眠的。它們象一個監管者一樣工作,其作用是監視ring-3應用程式並在其出錯時改正它們。下面是其工作時的典型的情況:
1、中斷髮生時
2、VMM得到控制權時
3、VMM存貯暫存器組的值時
4、VMM服務於中斷或呼叫其他VxDs完成此工作時
5、VMM交還控制權給被中斷的程式時
在以上過程中令人感興趣的是,VMM只有這一種方式能影響被中斷的應用程式,即修改儲存的暫存器映象。例如,VMM認為被中斷的程式應該返回到另外一個地址,它就修改儲存的暫存器映象中CS:IP的值,當這個程式被重新分派時,它將在新的CS:IP處開始執行。
VMM在客戶暫存器結構中儲存中斷點處的暫存器值。
Client_Reg_Struc STRUC
Client_EDI DD ?
Client_ESI DD ?
Client_EBP DD ?
Client_res0 DD ?
Client_EBX DD ?
Client_EDX DD ?
Client_ECX DD ?
Client_EAX DD ?
Client_Error DD ?
Client_EIP DD ?
Client_CS DW ?
Client_res1 DW ?
Client_EFlags DD ?
Client_ESP DD ?
Client_SS DW ?
Client_res2 DW ?
Client_ES DW ?
Client_res3 DW ?
Client_DS DW ?
Client_res4 DW ?
Client_FS DW ?
Client_res5 DW ?
Client_GS DW ?
Client_res6 DW ?
Client_Alt_EIP DD ?
Client_Alt_CS DW ?
Client_res7 DW ?
Client_Alt_EFlags DD ?
Client_Alt_ESP DD ?
Client_Alt_SS DW ?
Client_res8 DW ?
Client_Alt_ES DW ?
Client_res9 DW ?
Client_Alt_DS DW ?
Client_res10 DW ?
Client_Alt_FS DW ?
Client_res11 DW ?
Client_Alt_GS DW ?
Client_res12 DW ?
Client_Reg_Struc ENDS
你可以看到這個結構分為兩個部分:Client_xxx和Client_Alt_xxx。在這稍作說明,在一個給定的VM中,可能有兩個執行的執行緒:V86和保護模式。當V86程式執行時,假如一箇中斷產生,Client_xxx將包含V86程式的暫存器映象,Client_Alt_xxx將包含保護模式程式的暫存器映象。相應的,當保護模式程式執行時,假如一箇中斷產生,Client_xxx將包含保護模式程式的暫存器映象,Client_Alt_xxx將包含V86程式的暫存器映象。Client_resX被保留而沒有使用。
在檢視過這個結構後,你可能有一問題:怎樣改變暫存器中的一個位元組,比如al?上面的結構僅僅描述了字和雙字大小的暫存器組。不用擔心,在vmm.inc找一找。那有兩個為此附加的結構:Client_Word_Reg_Struc和Client_Byte_Reg_Struc。假如你想以字或位元組大小來訪問暫存器,根據你的需要轉換Client_Reg_Struc到Client_Word_Reg_Struc或Client_Byte_Reg_Struc。
下一個問題:我們如何得到一個指向客戶暫存器結構的指標?
這相當簡單:一般地,當VMM呼叫我們的VxD時,把客戶暫存器結構的地址放在ebp中。在這裡的客戶暫存器結構是當前VM的。你可以從VM的控制程式碼中得到這個指標。記住,VM的控制程式碼是VM控制塊的線性地址。
cb_s STRUC
CB_VM_Status DD ?
CB_High_Linear DD ?
CB_Client_Pointer DD ?
CB_VMID DD ?
CB_Signature DD ?
cb_s ENDS
CB
CB_Client_Pointer包含指向VM的客戶暫存器結構的指標。例如:你可用下邊的程式碼得到指向當前VM中的客戶暫存器結構的指標:
VMMCall Get_Cur_VM_Handle ; return the current VM handle in ebx
assume ebx:ptr cb_s
mov ebp,[ebx+CB_Client_Pointer] ; pointer to client reg struct
現在我們瞭解了客戶暫存器結構,我們可以用它來開始工作了。我們將使用客戶暫存器結構去傳送暫存器組的值到一個DOS中斷中,也就是,int 21h,功能2h,顯示一個字元。這個DOS服務把要顯示的字元放在dl中。假如我們傳送響鈴字元(07h)到這個服務,將透過PC喇叭發出一聲響。
記住,int 21h是一個DOS服務,因而其在V86模式下是可用的,我們如何在VxD中呼叫一個V86中斷?一個方法是使用Exec_Int服務。這個VMM服務把要呼叫的中斷號放在eax中。它模擬指定的中斷然後返回到呼叫的VM。然而,它必須在一個巢狀執行塊中被呼叫。巢狀執行塊被Begin_Nest_V86_Exec (或 Begin_Nest_Exec)和End_Nest_Exec包括起來。如果我們要呼叫int 21h功能2h,我們需要在巢狀執行塊內轉換Client_Byte_Reg_Struc結構的Client_ah和Client_Dl,然後把值21h放在eax中。當一切準備好了,就呼叫Exec_Int。
例子:
例子是一個動態VxD,它呼叫int 21h的功能2使PC喇叭發聲。
.386p
include masmincludevmm.inc
include masmincludevwin32.inc
include masmincludev86mmgr.inc
VxDName TEXTEQU
ControlName TEXTEQU
VxDMajorVersion TEXTEQU <1>
VxDMinorVersion TEXTEQU <0>
VxD_STATIC_DATA_SEG
VxD_STATIC_DATA_ENDS
VXD_LOCKED_CODE_SEG
;----------------------------------------------------------------------------
; Remember: The name of the vxd MUST be uppercase else it won't work/unload
;----------------------------------------------------------------------------
DECLARE_VIRTUAL_DEVICE %VxDName,%VxDMajorVersion,%VxDMinorVersion, %ControlName,UNDEFINED_DEVICE_ID,UNDEFINED_INIT_ORDER
Begin_control_dispatch %VxDName
Control_Dispatch W32_DEVICEIOCONTROL, OnDeviceIoControl
End_control_dispatch %VxDName
VXD_LOCKED_CODE_ENDS
VXD_PAGEABLE_CODE_SEG
BeginProc OnDeviceIoControl
assume esi:ptr DIOCParams
.if [esi].dwIoControlCode==1
Push_Client_State
VMMCall Begin_Nest_V86_Exec
assume ebp:ptr Client_Byte_Reg_Struc
mov [ebp].Client_dl,7
mov [ebp].Client_ah,2
mov eax,21h
VMMCall Exec_Int
VMMCall End_Nest_Exec
Pop_Client_State
EndI:
.endif
xor eax,eax
ret
EndProc OnDeviceIoControl
VXD_PAGEABLE_CODE_ENDS
end
講解
Push_Client_State
這沒什麼好講解的。當一個VxD接收到一個DeviceIoControl訊息,ebp已經指向了當前VM的客戶暫存器結構。我們呼叫Push_Client_State宏在堆疊中儲存客戶暫存器結構的狀態。然後用Pop_Client_State宏恢復客戶暫存器。
VMMCall Begin_Nest_V86_Exec
透過呼叫Begin_Nest_V86_Exec開始巢狀執行塊。
assume ebp:ptr Client_Byte_Reg_Struc
mov [ebp].Client_dl,7
mov [ebp].Client_ah,2
改變在客戶暫存器中的dl和ah暫存器的映象。這個改變的值將由中斷使用。
mov eax,21h
VMMCall Exec_Int
Exec_Int要求在eax存有一箇中斷號。我們想使用int 21h。等會我們呼叫Exec_Int去模擬中斷。
VMMCall End_Nest_Exec
Pop_Client_State
當Exec_Int返回,我們完成了巢狀執行塊,並且由堆疊中恢復了客戶暫存器結構的值。 你將聽到你的PC喇叭發出一聲響。
[@more@]來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10172717/viewspace-928819/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Intel 8086微處理器暫存器結構Intel
- 函式呼叫暫存器及棧幀結構函式
- CS 暫存器 和 IP 暫存器
- 暫存器
- 暫存器,觸發器,三極體小結觸發器
- 自學C day03-CPU內部結構和暫存器
- PC暫存器
- STM32暫存器操作、模板構建
- 暫存器定址和暫存器間接定址的區別
- 為什麼Modbus的只讀暫存器被稱為“輸入暫存器(Input Registers)”而不是“輸出暫存器”
- 【STM32】【暫存器】暫存器位讀寫方式配置系統時鐘
- CS、IP和PC暫存器
- 暫存
- 新手分享_再談FS暫存器
- CPU 中通用暫存器的作用
- 儲存器的層次結構
- 客戶端資料儲存概述客戶端
- iOS彙編基礎(二)暫存器iOS
- 6.常見暫存器和指令
- 10.1 除錯事件讀取暫存器除錯事件
- 程式設計中暫存器的使用程式設計
- STM32 GPIO 暫存器的配置
- 第五章:通用暫存器是()。
- 暫存器指定為寫0或者1
- Nacos - 客戶端心跳續約及客戶端總結客戶端
- Java讀取暫存器資料的方法Java
- 一文搞懂 ARM 64 系列: 暫存器
- 基於暫存器呼叫的軟體加速
- 程式分析與優化 - 8 暫存器分配優化
- 【C/C++】 C++暫存器優化C++優化
- php連結nsq客戶端PHP客戶端
- 儲存結構
- 【STC8H】STC8系列專有的特殊的暫存器位——PW_2暫存器的最高位 EAXFR
- CPU中跟蹤後繼指令地址的暫存器
- Git清空暫存區Git
- Merkle:客戶體驗轉型報告
- 關於STM32的BSRR(埠位設定/清除暫存器) 和 BRR(埠位清除暫存器) 的理解(初學32)
- T-Mobile證實資料洩露但客戶暫無風險
- JanusGraph -- 儲存結構