大家知道整天都在讨論的CIH病毒利用了VxD技術,掌握了VxD 程式設計,就等于破除了CIH 病毒神話,徹底清除CIH 病毒。仔細學習這篇文章。
VxD介紹
本文介紹VxD的作用。如果Windows 95提供的标準VxD對你的硬體或者軟體不能提供100%的相容支援,你需要為你的硬體或者軟體(包括16位和32位軟體) 建立VxD。如果你想讓Windows使用者使用你的硬體或者軟體的某些新特征,你也可以建立VxD。本文介紹如何寫VxD,講述了建立VxD所需的結構、過程和調用,還給出了建立和測試VxD 的步驟。VxD 可以是靜态的或者動态裝載的,下面的内容主要講述靜态VxD,不過關于格式和功能的内容兩者都适用。
什麼是VxD
VxD是一個管理例如硬體裝置或者已安裝軟體等系統資源的32位可執行程式,使得幾個應用程式可以同時使用這些資源。Windows通過使用VxD允許基于Windows的應用程式實作多任務。VxD在與Windows的連接配接工作中進行中斷,并為需要進行I/O操作的應用程式執行I/O操作,而且不影響其他應用程式的執行。大多數VxD管理硬體裝置,也有一些VxD管理或代替與之相關的軟體, 例如普通ROM BIOS。VxD可以包含必須在相應裝置上執行的裝置相關代碼,也可以依靠其它軟體去執行這些對裝置的操作。任何情況下,VxD都會為每一個應用程式保留該裝置狀态的記錄,保證無論何時一個應用程式繼續執行該裝置均處于正确狀态。一些VxD僅僅管理已安裝軟體,例如MS-DOS裝置驅動程式或者TSR 程式,這樣的VxD通常包含仿真這些軟體或者保護這些軟體用于正在運作的應用程式的資料的代碼。VxD有時還用于提高已安裝軟體的性能,Intel相容CPU執行32位的VxD比執行16位的MS-DOS裝置驅動程式或者TSR程式有更高的效率。
标準VxD
Windows包括多種VxD,用于支援公共硬體裝置和可安裝軟體。在某些情況下,可能需要修改VxD以提供新的特征或者支援非标準硬體。Windows提供許多不準備修改,但能夠輔助支援其他VxD的VxD。例如:許多 VxD使用V86記憶體管理器(V86MMGR)和虛拟可程式設計中斷控制器裝置(VPICD)提供的功能儲存V86模式記憶體和允許硬體中斷請求。要取得開發VxD的幫助,Windows 95裝置驅動程式開發工具包(DDK)包括了大量可用裝置驅動程式的源代碼。
建立VxD
你可以通過修改VxD例子程式或者自己學着寫來建立VxD 。你可以用彙編語言來寫VxD,也可以用進階語言(例如C語言)來寫一部分VxD。要建立一個VxD,需要以下步驟:
1、閱讀硬體手冊中關于描述這種型号硬體VxD的章節。
2、寫出所需的控制過程,VxD服務和API函數。
3、建立為VxD标示适當子產品名的子產品定義檔案,并引出需要的裝置描述塊。
4、彙編連接配接VxD。
5、用調試版Windows 95測試VxD,要獲得更多關于調試VxD的資訊,請參閱相關資料(可以用Soft-ICE調試——譯者注)。
6、為VxD和相關檔案建立安裝檔案(INF檔案),通過修改注冊資訊和向Windows的SYSTEM目錄和相關目錄拷貝檔案來安裝VxD。
7、建立最終發行軟體包。募窗滄癡xD。
你需要怎樣開始
本文假定你是一位有經驗的彙編語言程式員,而且熟悉Intel相容處理器的說明和系統結構。在某些特殊情況下,你還應該懂得下列内容:
保護模式和虛拟8086(即V86——譯者注)模式。
平坦記憶體模式
中斷和異常處理
保護和特權級
段和頁式記憶體管理以及錯誤處理
輸入和輸出保護以及錯誤處理
本文也假定你已經熟練了解專門硬體的特征和相應的普通ROM BIOS 以及其他可安裝軟體。
寫一個VxD
許多情況下,寫一個VxD用來代替一個由Windows 95提供的标準VxD。然而,大多數情況下,寫一個VxD 是用來支援新硬體裝置或者軟體的,在這種情況下,通常手工建立一個VxD比修改已經存在的VxD要容易,原因是大多數VxD 都是裝置相關的。然而,已存在VxD 的源代碼需要盡可能地仔細分析,原因是它們可能包含通用的格式和結構,以及說明怎樣使用VMM和VxD服務去實作有用的功能。
寫一個VxD需要下列步驟:
1、建立包含VxD各個段,VxD 說明,裝置控制過程,處理系統控制消息過程的基本部分和API過程的基本部分的VxD架構。
2、加入實模式初始化過程(可選)。
3、完成處理初始化消息的過程。這些過程應該能夠初始化控制塊, 配置設定全局記憶體以及安裝中斷、I/O捕獲和頁錯誤回調過程。
4、完成處理不同中斷和錯誤的回調過程。
5、為服務加入服務表定義和說明(可選)。
6、完成API過程(可選)
7、完成處理系統控制消息的過程以建立和删除虛拟機。
在寫一個VxD的過程中,你可以安裝該VxD并在調試器控制下運作Windows,在該VxD中設定斷點監視該VxD管理的中斷,這樣可以幫助你查明該VxD是否正确工作。
VxD段
VxD可以包含下面5個段的一些組合:
1、VxD_CODE段:保護模式代碼段(必須)。該段包含VxD系統控制過程、回調過程、服務和API過程。該段用宏VxD_CODE_SEG和VxD_CODE_ENDS定義開始和結束,也可命名為_LTEXT。
2、VxD_DATA段:保護模式資料段(必須)。該段包括裝置描述表、 服務表和部分VxD全局資料。該段用宏VxD_DATA_SEG和VxD_DATA_ENDS定義開始和結束,也可命名為_LDATA。
3、VxD_ICODE段:保護模式初始化代碼段(可選)。該段一般包括隻在VxD初始化過程中使用的過程和服務,VMM在Init_Complete 消息發生後丢棄此段。該段用宏VxD_ICODE_SEG和VxD_ICODE_ENDS定義開始和結束,也可命名為_ITEXT。
4、VxD_IDATA段:保護模式初始化資料段(可選)。該段一般包括初始化過程和服務使用的資料,VMM在Init_Complete消息發生後丢棄此段。 該段用宏VxD_IDATA_SEG和VxD_IDATA_ENDS定義開始和結束,也可命名為_IDATA。
5、VxD_REAL_INIT段:實模式初始化段(可選)。該段包含實模式初始化過程和資料,VMM在加載VxD其它部分之前調用此過程,過程傳回後丢棄此段,該段用宏VxD_REAL_INIT_SEG和VxD_REAL_INIT_ENDS定義開始和結束,也可命名為_RTEXT。除實模式初始化段以外,所有代碼和資料段均為32位平坦記憶體模式的保護模式段,這就是說定義在保護模式段中的過程和資料均為32位的偏移量。當VMM裝載VxD時,按照VxD在記憶體中的實際位置修正所有的偏移量。是以,在保護模式段中使用普通OFFSET指令處應該使用OFFSET32宏,OFFSET32宏定義的偏移量為連接配接器确定了正确的偏移量修正資訊。
VxD不能改變CS、DS、ES和SS段寄存器,VxD能夠使用FS和GS段寄存器。
保護模式指令
VxD的源程式檔案必須以.386p指令開始,以通知彙編器允許保護模式指令。雖然VxD工作在0特權級,但也不應該用保護模式指令去修改CPU 的運作,例如修改全局描述符(選擇子——譯者注)或中斷描述符以及修改任務狀态段或寄存器,這樣做可能會對Windows運作有不利影響。唯一的例外情況是當該VxD為虛拟數學協處理器裝置驅程式(VMCPD),允許修改CR0寄存器中的80387位。
包含(Include)檔案
包含檔案定義了VxD 需要的宏、結構、符号和服務表,用于聲明段和過程以及使用VMM和其它VxD服務。下面列出每個包含檔案包含的公共服務定義、宏和符号定義:
1、VMM.INC:包含所有的VMM服務以及所需的宏和符号,例如Declare_Virtual_Device和VMMCall。
2、DEBUG.INC:包含在調試終端上輸出資訊和執行各種資料檢查的宏。這些宏的功能由定義了調試符号的VxD在彙編時該檔案生成的代碼實作。
3、VPICD.INC:包含為虛拟可程式設計中斷控制器裝置(VPICD )定義的所有服務、宏和符号。VPICD處理所有的中斷,是以許多VxD需要VPICD服務。
4、SHELL.INC:包含虛拟外殼裝置提供的公共服務的定義。虛拟外殼裝置提供對例如MessageBox這樣的Windows函數的調用,可以讓VxD顯示對話框。
VxD聲明
每一個VxD 都要聲明一個名稱、一個版本号、一個初始化順序和一個裝置控制過程,許多虛拟裝置驅動程式還聲明一個裝置辨別和一些API過程。 VxD一般使用Declare_Virtual_Device宏來實作這些聲明,例如:
Declare_Virtual_Device VSAMPLED, 4, 0, VSAMPLED_Control, VSAMPLED_Device_ID, VSAMPLED_Init_Order, VSAMPLED_V86_API_Handler, VSAMPLED_PM_API_Handler
本例聲明了一個VxD執行個體——VSAMPLED V4.0 ,在對應的源檔案必須定義名字為VSAMPLED_Control的裝置控制過程。符号VSAMPLED_Device_ID和VSAMPLED_Init_Order說明非标準VxD的辨別和初始化順序,該VxD支援V86模式和保護模式API過程。VMM用宏定義的資訊來初始化VxD并發送系統控制消息給VxD,并且允許MS-DOS 應用程式、裝置驅動程式和TSR調用VxD。為了使VMM 存取這些資訊,相應的宏建立一個裝置描述塊(DDB)并将其儲存在保護模式資料段中(DDB的格式與VxD_Desc_Block結構相同),宏為DDB建立了一個必須在VxD連接配接時被顯式引出的标号。在上例中,DDB 的名稱是VSAMPLED_DDB。
VxD辨別(ID)
一個VxD提供一個VxD辨別,以差別于其它VxD。VMM 動态連接配接例程使用VxD辨別為合适的VxD連接配接服務調用,如果VxD提供服務或者提供V86模式和保護模式API過程以及其它需要唯一辨別的情況,VxD就必須有唯一辨別。雖然标準VxD使用預定義VxD 辨別(符号定義在VMM.INC檔案中),支援新裝置和新軟體接口的VxD還是必須全部有新辨別。為了防止與其他新VxD沖突,Microsoft通過請求和注冊辨別來保證沒有其它廠商使用自己的VxD的辨別,Microsoft保留0—01FFH之間的所有VxD 辨別自己使用。不提供服務或者API過程,或者不需要唯一辨別的VxD應該使用Undefined_Device_ID 符号來定義VxD辨別。
初始化順序
每一個VxD都有一個用于指定VMM應該何時初始化該VxD的初始化順序值,VMM按照該值從小到大的順序初始化虛拟機(VM ——譯者注)。如果兩個或者兩個以上的VxD有相同的值,VMM會按照SYSTEM.INI 檔案中出現的順序來初始化,但指定順序是沒有保證的。對于需要調用其它VxD服務或者需要在其它VxD 之前攔截中斷的VxD,初始化順序是很重要的。如果一個VxD需要在标準VxD之前或者之後初始化,它的初始化順序值應該通過在标準VxD預定義的初始化順序符号(在VMM.INC檔案中定義)上加上或者減去一個小數值來建立。如果一個VxD不需要初始化順序值,應該使用Undefined_Init_Order 符号代替初始化順序值。
裝置控制過程
每一個VxD都有一個裝置控制過程,VMM通過調用此過程給VxD發送VxD系統控制消息。系統控制消息指導VxD完成動作,例如自身初始化或者通知VxD虛拟機的變化(例如建立虛拟機)等。許多VxD通過使用Begin_Control_Dispatch、 Control_Dispatch和End_Control_Dispatch宏來定義裝置控制過程,例如:
Begin_Control_Dispatch VSAMPLED
Control_Dispatch Sys_Critical_Init, VSAMPLED_Crit_Init
Control_Dispatch Device_Init, VSAMPLED_Device_Init
Control_Dispatch Sys_Critical_Exit, VSAMPLED_Crit_Exit
End_Control_Dispatch VSAMPLED
上例中,宏建立了一個名字為VSAMPLED_Control的裝置控制過程,并生成了檢查Sys_Critical_Init、Device_Init和Sys_Critical_Exit 消息的指令。當這些消息發送到該過程時,該過程通過控制相應的過程(例如VSAMPLED_Crit_Init)來處理消息,這些消息處理過程必須在VxD中定義。
系統控制消息
VMM發送系統控制消息給VxD,以通知VxD影響系統和虛拟機的變化。大多數VxD需要跟蹤虛拟機的建立和狀态,是以無論何時建立、初始化或者終止虛拟機,VMM都會發送消息給VxD。VMM也會在執行焦點移動到一個虛拟機或者從一個虛拟機移走時,以及虛拟外殼裝置需要給使用者顯示一個消息框時發送消息給VxD。
下面是公共消息和VxD應該怎樣處理這些消息的方法清單:
Begin_Message_Mode消息:當虛拟外殼裝置需要給使用者顯示一個消息框但不能使用系統虛拟機和Windows函數時VxD收到此消息。虛拟鍵盤、滑鼠和顯示裝置儲存目前狀态,允許任何消息模式服務并為消息模式處理初始化相應裝置。
Create_VM消息:這是當一個新的虛拟機被建立時VxD收到的第一條消息。VxD應該初始化與虛拟機有關的資料,特别是控制塊。
Debug_Query消息:VxD從WDEB386調試器收到此消息。VxD可以顯示調試清單和從調試終端讀取使用者指令。
Destroy_VM消息:這是VxD收到的第三條虛拟機終止消息。Simulate_Int和
Exec_Int服務對獲得此消息的虛拟機不再有效。
Device_Init消息:這是VxD收到的第二條消息。允許中斷,大多數VxD配置設定和拷貝初始狀态到系統虛拟機控制塊中的裝置指定部分,安裝中斷回調函數和I/O保護異常以及指定執行個體資料。這時,Simulate_Int和Exec_Int服務變得有效。
End_Message_Mode消息:當虛拟外殼裝置不再需要顯示消息框時VxD收到此消息。虛拟鍵盤、滑鼠和顯示器裝置恢複獲得此消息的虛拟機以前儲存的狀态,禁止任何消息模式服務。
Init_Complete消息:這是VxD收到的第三條消息,也是最後一條與系統初始化有關的消息。雖然大多數VxD都不處理此消息,但使用V86記憶體的VxD應該在此消息傳回前定位和申請記憶體。當VxD傳回此消息時,VMM丢棄VxD的初始化代碼和資料段。
Query_Destory消息:當虛拟外殼裝置需要決定是否可以删除虛拟機時VxD收到此消息。VxD可以通過設定進位标志(CF——譯者注)傳回以阻止虛拟機被删除,在這種情況下VxD應該使用SHELL_Message服務來通知使用者問題。
Reboot_Processor消息:當使用者試圖重新啟動計算機時VxD收到此消息。可以重新啟動計算機的VxD,例如鍵盤裝置應該完成該工作。
Set_Device_Focus消息:當執行焦點從一個虛拟機移動到另一個虛拟機時VxD收到此消息。VxD恢複硬體裝置到與虛拟機有關的狀态。如果VxD使用I/O捕獲管理沒有執行焦點時的虛拟機,VxD應該盡可能地移走太多的I/O捕獲,使虛拟機運作盡可能地快一些。
Sys_Critical_Exit消息:這是VxD收到的最後一條消息。禁止中斷,Simualte_Int和Exec_Int服務不再有效。VxD應該複位與之相關的硬體裝置,保證能夠無問題地傳回到實模式。
Sys_Critical_Init消息:這是VxD收到的第一條消息。中斷仍然不被允許,是以VxD應該盡可能快地完成任務。大多數VxD完成下列任務:
安裝和初始化需要支援來自裝置的硬體中斷和來自VMM或者其它VxD的軟體中斷的任何函數,為裝置提供除需要使用V86模式記憶體頁以外的申請,例如虛拟顯示裝置申請顯示記憶體。
初始化VxD服務需要的任何資料,這通常包括讀取SYSTEM.INI檔案中的設定。
當處理此消息時,Simualte_Int和Exec_Int服務必須不被使用。
Sys_VM_Init消息:在Init_Complete消息之後VxD收到此消息。VxD應該初始化系統虛拟機的硬體和軟體狀态。如果VxD設定進位标志傳回,VMM終止所有程序并退出Windows。
Sys_VM_Terminate消息:這是VxD收到的第一條系統虛拟機終止消息。VxD可以開始為虛拟機終止做準備。Simulate_Int和Exec_Int服務有效,系統虛拟機總是最後一個被終止的虛拟機。
System_Exit消息:這是當系統終止時VxD收到的第一條消息。VMM在發送Sys_VM_Terminate消息之後發送此消息,允許中斷,但Simualte_Int和Exec_Int服務不再有效。如果此消息來自一個緻命錯誤的結果,VxD可以通過修改系統虛拟機的記憶體以恢複系統狀态,使得Windows能夠終止而不當機。
VM_Critical_Init消息:這是當一個新的VxD(虛拟機——譯者注)被建立時VxD收到的第二條消息。VxD可以通過設定進位标志傳回以阻止虛拟機被建立。禁止中斷,Simualte_Int和Exec_Int服務不再有效。
VM_Init消息:這是當一個新的VxD被建立時VxD收到的第三條消息。VxD應該初始化虛拟機的硬體和軟體狀态,例如虛拟顯示裝置執行INT 10H功能設定初始顯示模式。
VM_Not_Execute消息:這是VxD收到的第二條虛拟機終止消息(如果虛拟機已經被虛拟外殼裝置删除,這是收到的第一條消息)。VxD可以通過檢查EDX寄存器中的标志來查明終止原因。Simulate_Int和Exec_Int服務對獲得此消息的虛拟機不再有效。
VM_Resume消息:當虛拟機的執行被恢複時VxD收到此消息,例如切換到前台時。VxD應該鎖定任何資源和為虛拟機重新開始準備内部結構。如果VxD設定進位标志傳回,VMM不恢複執行虛拟機。
VM_Suspend消息:當虛拟機已經被挂起時VxD收到此消息,例如切換到背景時。VxD應該解鎖任何與虛拟機有關的資源。
VM_Terminate