Iczelion 的 Win32Asm VxD 彙編教程 (四) (轉)
Iczelion 的 Win32Asm VxD 彙編教程 (四) (轉)[@more@]
We 我們在上一節學會了如何編寫一個什麼事也不做的VxD程式。在這一節裡,我們要給它增加處理控制訊息的功能。
當VMM載入你的靜態VxD程式時,你的VxD程式會按以下順序接收到三個控制訊息:
當要結束靜態VxD的時候,VMM傳送如下的控制訊息:
你也許會感到奇怪:為什麼這兩個訊息後面都跟著個“2" ”。這是因為:在VMM載入VxD程式的時候,它是按照初始化順序值小的VxD先載入的順序載入的,這樣VxD程式就可以使用那些在它們之前載入的VxD程式提供的服務。例如,VxD2要用到VxD1中的服務,它就必須把它的初始化順序值定義的比VxD小。載入的順序是:
還有兩種退出訊息:
上一節我們提到的例子是一個靜態的VxD,你可以把它轉換成一個動態的VxD,只要在.def檔案中VxD標記的後面加上關鍵字DYNAMIC。
一個動態的VxD可以按以下的方法被載入:
如果你用CreateFile來載入一個動態VxD,那麼這個動態VxD必須處理w32_DeviceIoControl 訊息。當你的動態VxD第一次被CreateFile載入的時候,VWIN32 向你的VxD發出這個訊息。你的VxD響應這個訊息,返回時eax中的值必須為零。當應用程式呼叫DeviceIoControl API來與一個動態VxD通訊時,w32_DeviceIoControl訊息也被髮送。我們會在下一章講到DeviceIoControl介面。
一個動態VxD在初始化時收到一個訊息:
你要用BeginProc和EndProc 宏來定義你的函式:
因為BeginProc-EndProc 宏比proc-endp 指令的功能要強,所以你應該用BeginProc-EndProc宏來代替proc-endp指令
VxD 設計
VxD的初始化和結束
VxD程式分為兩種:靜態的和動態的。每種的載入方法都不同,接受到的初始化和結束的控制訊息也不同。靜態VxD:
下列情況下,VMM載入一個靜態VxD:- 一個實常駐程式透過中斷2FH,1605H,來呼叫此VxD。
- 此VxD在登錄檔中的如下位置有定義:
- HKEY_LOCAL_MACHINESystemCurrentControlSetServicesVxDkeyStaticVxD=VxD帶路徑名
- 此VxD在system.ini中的[386enh]行下有定義:[386enh] section:
device=VxD帶路徑檔名
當VMM載入你的靜態VxD程式時,你的VxD程式會按以下順序接收到三個控制訊息:
- Sys_Critical_Init VMM在轉入到保護模式後,開放中斷前發出這個控制訊息。大多數VxD程式到不要用到這個訊息,除非:
- 你的VxD程式要接管一些其他VxD程式或者保護模式程式要用到的中斷。既然你處理這個訊息的時候這個中斷還沒有開啟,你就可以確定在你接管這個中斷的時候此中斷不會被呼叫。
- 你的VxD程式為其他的VxD程式提供了一些VxD服務。例如,一些在你的VxD程式後載入的VxD程式在處理Device_Init控制訊息時需要呼叫一些你的VxD服務,既然Sys_Critical_Init 控制訊息在Device_Init訊息之前被髮送,所以你應該在Sys_Critical_Init 訊息傳送時初始化你的程式。
- Device_Init VMM在開放中斷後傳送此資訊。大多數VxD程式都在得到這個訊息時初始化。因為中斷都開放了,所以耗時的操作也可以在這裡執行而不必怕會導致硬中斷的丟失。你可以在這時進行初始化(如果你需要的話)。
- Init_Complete 在所有的VxD程式處理完Device_Init 訊息之後,VMM釋放初始化段(ICODE和RCODE段類)之前,VMM發出這個控制訊息。只有少數幾個VxD要處理這個訊息。
當要結束靜態VxD的時候,VMM傳送如下的控制訊息:
- System_Exit2 當你的VxD程式收到這個訊息,Windows95正在關閉系統,除了系統虛擬機器所有其他虛擬機器都已經退出了。儘管如此,仍然處於保護模式下,在系統虛擬機器上執行真實模式編碼也是的。在這時Kernel32.dll也已經被解除安裝了。
- Sys_Critical_Exit2 當所有的VxD完成對System_Exit2的響應處理並且中斷都被關閉後,你的VxD收到到這個訊息。
你也許會感到奇怪:為什麼這兩個訊息後面都跟著個“2" ”。這是因為:在VMM載入VxD程式的時候,它是按照初始化順序值小的VxD先載入的順序載入的,這樣VxD程式就可以使用那些在它們之前載入的VxD程式提供的服務。例如,VxD2要用到VxD1中的服務,它就必須把它的初始化順序值定義的比VxD小。載入的順序是:
..... VxD1 ===> VxD2 ===> VxD3 .....那麼解除安裝的時候,理所當然的是初始化順序值大的VxD程式先被解除安裝,這樣他們仍然可以使用比它們後載入的那些VxD程式提供的服務。如上面的例子,次序是:
.... VxD3 ===> VxD2 ===> VxD1.....在上邊的例子中,如果VxD2在初始化時呼叫了VxD1中的某些服務,那麼解除安裝時它可能也要再次用到一些VxD1中的服務。System_Exit2和Sys_Critical_Exit2是反初始化順序傳送的。這表示,當VxD2接受到這些訊息時,VxD1還沒有被解除安裝,它仍可以呼叫VxD1的服務,而System_Exit和Sys_Critical_Exit訊息不是按照反初始化順序傳送的。這意味著,你不能肯定你是否仍能呼叫在你之前載入的VxD提供的VxD服務。新一代的VxD程式不應該使用這些訊息。
還有兩種退出訊息:
- Device_Reboot_Notify2 告訴VxD程式VMM正在準備重新啟動系統。這時候中斷還是開放的。
- Crit_Reboot_Notify2 告訴VxD程式VMM正在準備重新啟動系統。這時候中斷已經被關閉了。
動態VxD:
動態VxD在Windows9x裡可以動態的被載入和解除安裝。這個特點在Window3.x下是沒有的。動態VxD程式的主要作用是用來支援某些動態的裝置的重灌,比如:即插即用裝置。儘管如此,你可以從你的程式中載入/解除安裝它,也可以把它看作是你的程式的一個到ring-0的擴充套件。上一節我們提到的例子是一個靜態的VxD,你可以把它轉換成一個動態的VxD,只要在.def檔案中VxD標記的後面加上關鍵字DYNAMIC。
VxD FIRSTVxD DYNAMIC這就是你把一個靜態VxD轉換成一個動態的VxD所要做的一切。
一個動態的VxD可以按以下的方法被載入:
- 把它放到你的Windows目錄下的SYSTEMIOSUBSYS目錄中。在這個目錄裡的VxD會被輸入輸出監視器(ios)載入。這些VxD必須支援層裝置。所以用這種方法載入你的動態VxD並不是一個好辦法。
- 用VxD載入服務。 VxDLDR是一個可以載入動態VxD的靜態VxD。你可以在其他VxD裡面或者在16位程式碼裡面呼叫它的服務。
- 用Win32應用程式裡的 CreateFile 。你在呼叫CreateFile時,你的動態VxD要以下面的格式填寫:
.VxD完整路徑名
例如,如果你要載入一個在當前目錄下名為FirstVxD的動態VxD,你需要做如下的工作:.data
VxDName ".FirstVxD.VxD",0
......
.data?
hDevice dd ?
.....
.code
.....
invoke CreateFile, addr VxDName,0,0,0,0, FILE_FLAG_DELETE_ON_CLOSE,0
mov hDevice,eax
......
invoke CloseHandle,hDevice
......
如果你用CreateFile來載入一個動態VxD,那麼這個動態VxD必須處理w32_DeviceIoControl 訊息。當你的動態VxD第一次被CreateFile載入的時候,VWIN32 向你的VxD發出這個訊息。你的VxD響應這個訊息,返回時eax中的值必須為零。當應用程式呼叫DeviceIoControl API來與一個動態VxD通訊時,w32_DeviceIoControl訊息也被髮送。我們會在下一章講到DeviceIoControl介面。
一個動態VxD在初始化時收到一個訊息:
- Sys_Dynamic_Device_Init
- Sys_Dynamic_Device_Exit
其它系統控制訊息
當VxD在記憶體裡的時候,除了接收和初始化及結束相關的訊息外,它還要收到許多別的控制訊息。有些訊息是關於虛擬機器管理器的,有的是關於各種事件的。例如,關於虛擬機器的訊息如下:- Create_VM
- VM_Critical_Init
- VM_Suspend
- VM_Resume
- Close_VM_Notify
- Destroy_VM
在VxD內建立函式
你要在一個段裡面定義你的函式。你應該首先定義一個段,然後把你的函式放進去。例如,如果你要把你的函式放到一個可調頁段中。你應該先定義一個可調頁段,像這樣:VxD_PAGEABLE_CODE_SEG你可以在一個段裡面插入多個的函式。作為一個VxD編寫者,你必須決定每一個函式應該放到哪個段裡面去。如果你的函式必須時刻存在於記憶體中,如某些硬體中斷處理程式,就把它們放到鎖定頁面段裡面,否則,你應該把它們放到可調頁段。(你的函式寫在這裡)
VxD_PAGEABLE_CODE_ENDS
你要用BeginProc和EndProc 宏來定義你的函式:
BeginProc 函式名使用BeginProc 宏還可以加上一些引數,想了解這些細節,你可以看看Win95 DDK的文件。大多數時候,你只用填寫函式的名字就夠了。EndProc 函式名
因為BeginProc-EndProc 宏比proc-endp 指令的功能要強,所以你應該用BeginProc-EndProc宏來代替proc-endp指令
VxD約定
暫存器的使用
你的VxD程式可以使用所有的暫存器,FS和GS。但是在改動段暫存器的時候一定要小心。尤其是,一定不要改動CS和SS的內容,除非你對將發生的事情有絕對的把握。你可以使用DS和ES,但一定要記住在返回時恢復它們初值。有兩個特徵位尤其重要:方向和中斷特徵位。不要長時間的遮蔽中斷。還有如果你要改動方向特徵位,不要忘了在返回之前恢復它的初值。引數傳遞約定
VxD服務函式有兩種呼叫約定:暫存器法和堆疊法。呼叫暫存器法服務函式時,你透過各種暫存器來傳遞服務函式的引數。並且,在呼叫完成後檢查暫存器的值來看操作是否成功。不要總是以為在呼叫服務函式後主要暫存器的值還和以前一樣。當呼叫堆疊法服務函式時,你把要傳遞的引數壓棧,在eax得到返回值。堆疊呼叫法的服務函式儲存ebx,esi,edi和ebp的值。許多暫存器呼叫法服務函式都源於Windows3.x的時代。在大多數時候,你可以透過名字來區分這兩種服務函式,如果一個函式的名字一下劃線開頭,如_HeapAllocate,它就是一個堆疊法的服務函式(除了少數從VWIN32.VxD匯出的函式)。如果函式名不是一下劃線開頭,它就是一個暫存器法的服務函式。呼叫VxD服務函式
你可以透過VMMCall和VxDCall 宏來呼叫VMM和VxD服務。這兩個宏的語法是一樣的。當你要呼叫VMM匯出的VxD服務函式時,用VMMCall。當你要用其它VxD程式匯出的VxD服務函式時,用VxDCall。VMMCall service ; 呼叫暫存器法服務函式e正如我在前面所講的,VMMCall和VxDCall分解出一個跟著一個雙字的20h中斷,這樣用起來很方便。當你呼叫堆疊法服務時,你必須用角括號把你的引數列括起來。
VMMCall _service,; 呼叫堆疊法服務函式
VMMCall _HeapAllocate, <_HeapAllocate是一個堆疊法服務函式。它有兩個引數,我們必須用角括號把它們括起來。由於第一個引數是一個這個宏不能正確解釋的,所以我們又要用一個角括號把它括起來。, HeapLockedIfDP>
Flat地址
在老的編譯工具裡,當你使用offset 運算子時,和聯接器會生成錯誤地址,所以VxD編寫者用offset flat:來代替offset。imm.inc包括了一個使這更簡單的宏:OFFSET32 來代替offset flat:。所以如果你要用地址操作時,用OFFSET32 來代替offset運算子。注意: 當我寫這篇教程的時候,我試了一下用offset 運算子。它可以生成正確的地址。所以我想MASM6.14修正了這個。但是為了安全起見,你還是應該用OFFSET32宏來代替offset。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-991909/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 彙編 實驗四
- iOS逆向之旅(基礎篇) — 彙編(四) — 彙編下的函式iOS函式
- 彙編跳轉指令
- iOS彙編入門教程(三)彙編中的 Section 與資料存取iOS
- iOS彙編入門教程(一)ARM64彙編基礎iOS
- 51微控制器彙編教程
- C++內嵌彙編 教程1C++
- iOS彙編入門教程(二)在Xcode工程中嵌入彙編程式碼iOSXCode
- 站在彙編角度深入瞭解 Swift(四)Swift
- 彙編+qemu玩轉控制檯列印
- 彙編學習筆記之轉移指令筆記
- 彙編
- iOS彙編基礎(四)指標和macho檔案iOS指標Mac
- iOS逆向之旅(基礎篇) — 彙編(五) — 彙編下的BlockiOSBloC
- 重新整理彙編—————彙編的基礎理論前置篇
- nasm彙編ASM
- 彙編命令A
- ARM彙編解決階乘以及大小寫轉換
- iOS逆向之旅(基礎篇) — 彙編(二) — 彙編下的 IF語句iOS
- iOS彙編教程(六)CPU 指令重排與記憶體屏障iOS記憶體
- iOS逆向之旅(基礎篇) — 彙編(三) — 彙編下的 Switch語句iOS
- C語言轉寫成MIPS指令集彙編以及MIPS指令集彙編中函式呼叫時棧的變化C語言函式
- 彙編基礎
- 初識彙編
- linux彙編指令Linux
- 手撕彙編。。。
- ARM彙編指令集彙總
- iOS逆向之旅(基礎篇) — 彙編(一)— 彙編基礎iOS
- iOS逆向學習筆記 - 彙編(一) - 初識彙編iOS筆記
- Python教程:Pandas資料轉換編碼的10種方式Python
- 常用的x86彙編指令
- 彙編指令(待完善)
- 彙編快速入門
- 彙編 實驗3
- 彙編 實驗2
- 彙編 實驗五
- 彙編 實驗九
- 彙編 實驗一
- GCC 內聯彙編GC