用Visual studio11在Windows8上開發驅動實現註冊表監控和過濾

來源:互聯網
上載者:User

在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 studio11與Windows8帶來格外不同的新體驗

 

1.啟動Vs11

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

3.選擇一個驅動模式,有核心模式與使用者模式兩種的驅動

 

4.建立一個驅動程式,KMDF DriverMVP

 

5.我們選擇的是核心模式的驅動程式,下面是建立成功後的介面,分別是驅動程式本身,與驅動安裝包

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

 


插入下列代碼實現基於callback的註冊表監控和過濾技術,請見程式碼分析

#include "ntifs.h"#include "RegistryCallBack.h"#include <ntstrsafe.h>NTSTATUS st;LARGE_INTEGER g_CallbackCookie;ANSI_STRING  astr; VOID UnloadDriver(PDRIVER_OBJECT DriverObject);NTSTATUS RegistryCallback(IN PVOID CallbackContext, IN PVOID Argument1, IN PVOID Argument2);BOOLEAN GetRegistryObjectCompleteName(PUNICODE_STRING pRegistryPath, PUNICODE_STRING pPartialRegistryPath,PVOID pRegistryObject);NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath){    DbgPrint("[RegRoutine]Loading!\n");DriverObject->DriverUnload = UnloadDriver;st = CmRegisterCallback(RegistryCallback,NULL,&g_CallbackCookie);if ( !NT_SUCCESS(st) ){DbgPrint("[RegRoutine]CmRegisterCallback Failed!\n");return st;}DbgPrint("[RegRoutine]RegistryCallback Addr:0x%08X\n",RegistryCallback);DbgPrint("[RegRoutine]Cookie.LowPart:0x%08X Cookie.HighPart:0x%08X\n",g_CallbackCookie.LowPart,g_CallbackCookie.HighPart);    return st;}VOID UnloadDriver(PDRIVER_OBJECT DriverObject){CmUnRegisterCallback(g_CallbackCookie);DbgPrint("[RegRoutine]UnLoading!\n");}NTSTATUS   RegistryCallback(    IN PVOID  CallbackContext,    IN PVOID  Argument1,    IN PVOID  Argument2     ){int type;BOOLEAN exception = FALSE;BOOLEAN registryEventIsValid = FALSE;UNICODE_STRING registryPath;UCHAR* registryData = NULL;ULONG registryDataLength = 0;ULONG registryDataType = 0;registryPath.Length = 0;registryPath.MaximumLength = NTSTRSAFE_UNICODE_STRING_MAX_CCH * sizeof(WCHAR);registryPath.Buffer = ExAllocatePoolWithTag(NonPagedPool, registryPath.MaximumLength, 'ConT');if(registryPath.Buffer == NULL){DbgPrint("[RegRoutine]Allocate registryPath failed!\n");return STATUS_SUCCESS;}type = (REG_NOTIFY_CLASS)Argument1;try{switch(type){case RegNtPostCreateKey:{PREG_POST_CREATE_KEY_INFORMATION createKey = (PREG_POST_CREATE_KEY_INFORMATION)Argument2;if( NT_SUCCESS(createKey->Status) || createKey->Status == STATUS_PENDING ) //建立登錄機碼狀態為成功和未決的都記錄一下{PVOID* registryObject = createKey->Object;registryEventIsValid = GetRegistryObjectCompleteName(istryPath, createKey->CompleteName,*registryObject);if ( registryEventIsValid ){RtlUnicodeStringToAnsiString(&astr,istryPath,TRUE);DbgPrint("[RegCreated]KeyName:%s!\n",astr.Buffer);//如果建立的是自啟動項,則警告一下if ( strstr(astr.Buffer,"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run") ){DbgPrint("[RegCreated]Forbin!\n");DbgPrint("[RegCreated]ForbinKeyName:%s!\n",astr.Buffer);RtlFreeAnsiString(&astr);}RtlFreeAnsiString(&astr);}elseDbgPrint("[RegCreated]Get Key Name Failed!\n");}}break;//使用PreCreateKey可以阻止key的建立,但是能夠作為判斷依據的只有一個key的CompleteName,無法得到完整路徑來判斷case RegNtPreCreateKey:{PREG_PRE_CREATE_KEY_INFORMATION createKey = (PREG_PRE_CREATE_KEY_INFORMATION)Argument2;RtlCopyUnicodeString(istryPath,createKey->CompleteName);RtlUnicodeStringToAnsiString(&astr,istryPath,TRUE);DbgPrint("[RegRoutine]PreCreate:%s!\n",astr.Buffer);if ( !strcmp(astr.Buffer,"新項 #1") ){DbgPrint("[RegRoutine]Forbin!\n");DbgPrint("[RegRoutine]ForbinKeyName:%s!\n",astr.Buffer);RtlFreeAnsiString(&astr);return STATUS_INVALID_PARAMETER;}RtlFreeAnsiString(&astr);}break;case RegNtDeleteKey:{PREG_DELETE_KEY_INFORMATION deleteKey = (PREG_DELETE_KEY_INFORMATION)Argument2;registryEventIsValid = GetRegistryObjectCompleteName(istryPath, NULL, deleteKey->Object);if ( registryEventIsValid ){RtlUnicodeStringToAnsiString(&astr,istryPath,TRUE);DbgPrint("[RegDeletedKey]KeyName:%s!\n",astr.Buffer);if ( !strcmp(astr.Buffer,"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\\ljh00001") ){DbgPrint("[RegDeletedKey]Forbin!\n");DbgPrint("[RegDeletedKey]ForbinKeyName:%s!\n");RtlFreeAnsiString(&astr);return STATUS_INVALID_PARAMETER;}RtlFreeAnsiString(&astr);}}break;case RegNtSetValueKey:{PREG_SET_VALUE_KEY_INFORMATION setvalue = (PREG_SET_VALUE_KEY_INFORMATION)Argument2;if( MmIsAddressValid(setvalue->ValueName) ){registryEventIsValid = GetRegistryObjectCompleteName(istryPath, NULL, setvalue->Object);if ( registryEventIsValid ){RtlUnicodeStringToAnsiString(&astr,istryPath,TRUE);DbgPrint("[RegSetValue]ValueParentPath:%s!\n",astr.Buffer);RtlFreeAnsiString(&astr);}RtlUnicodeStringToAnsiString(&astr,setvalue->ValueName,TRUE);DbgPrint("[RegSetValue]ValueName:%s!\n",astr.Buffer);RtlFreeAnsiString(&astr);//輸出設定的索引值的資料類型和大小,如果類型是REG_SZ則data是一個unicode_string,而資料大小為buffer長度//加上4位元組長度的length和MaxLength再加上2個位元組的結尾00的長度DbgPrint("[RegSetValue]ValueDataType:%X,DataSize:%X\n",setvalue->Type,setvalue->DataSize);if ( setvalue->Type == 1 ) //Type為REG_SZ,其它類型的資料暫時忽略 {DbgPrint("[RegSetValue]Data:%ws\n",setvalue->Data);}}}break;case RegNtDeleteValueKey:{PREG_DELETE_VALUE_KEY_INFORMATION deletevalue = (PREG_DELETE_VALUE_KEY_INFORMATION)Argument2;if( MmIsAddressValid(deletevalue->ValueName) ){registryEventIsValid = GetRegistryObjectCompleteName(istryPath, NULL, deletevalue->Object);if ( registryEventIsValid ){RtlUnicodeStringToAnsiString(&astr,istryPath,TRUE);DbgPrint("[RegDelValue]ValueParentPath:%s!\n",astr.Buffer);RtlFreeAnsiString(&astr);}RtlUnicodeStringToAnsiString(&astr,deletevalue->ValueName,TRUE);DbgPrint("[RegDelValue]ValueName:%s!\n",astr.Buffer);if ( !strcmp(astr.Buffer,"ljh00001") ){DbgPrint("[RegDelValue]Forbin!\n");DbgPrint("[RegDelValue]ForbinKeyName:%s!\n");RtlFreeAnsiString(&astr);return STATUS_INVALID_PARAMETER;}RtlFreeAnsiString(&astr);}}break;case RegNtRenameKey:{PREG_RENAME_KEY_INFORMATION renamevalue = (PREG_RENAME_KEY_INFORMATION)Argument2;if( MmIsAddressValid(renamevalue->NewName) ){registryEventIsValid = GetRegistryObjectCompleteName(istryPath, NULL, renamevalue->Object);if ( registryEventIsValid ){RtlUnicodeStringToAnsiString(&astr,istryPath,TRUE);DbgPrint("[RegRenameKey]KeyPath:%s!\n",astr.Buffer);RtlFreeAnsiString(&astr);}RtlUnicodeStringToAnsiString(&astr,renamevalue->NewName,TRUE);DbgPrint("[RegRenameKey]KeyName:%s!\n",astr.Buffer);RtlFreeAnsiString(&astr);}}break;default:break;}} except( EXCEPTION_EXECUTE_HANDLER ) {DbgPrint("[RegRoutine]Catch a Expection!\n");exception = TRUE;registryEventIsValid = FALSE;}if(registryPath.Buffer != NULL){ExFreePoolWithTag(registryPath.Buffer, 'ConT');}return STATUS_SUCCESS;}BOOLEAN GetRegistryObjectCompleteName(PUNICODE_STRING pRegistryPath, PUNICODE_STRING pPartialRegistryPath, PVOID pRegistryObject){BOOLEAN foundCompleteName = FALSE;BOOLEAN partial = FALSE;NTSTATUS status;ULONG returnedLength;PUNICODE_STRING pObjectName = NULL;//判斷object的有效性if( (!MmIsAddressValid(pRegistryObject)) || (pRegistryObject == NULL) ){DbgPrint("[RegRoutine]pRegistryObject Invalid!\n");return FALSE;}//使用ObQueryNameString來得到object對應的名稱status = ObQueryNameString(pRegistryObject, (POBJECT_NAME_INFORMATION)pObjectName, 0, &returnedLength );if(status == STATUS_INFO_LENGTH_MISMATCH)//第一次傳的buffer長度為0,ObQueryNameString返回的結果必定是緩衝區大小不足{pObjectName = ExAllocatePoolWithTag(NonPagedPool, returnedLength, 'ConT'); //申請記憶體if ( pObjectName == NULL ) //申請記憶體失敗則返回FALSE{DbgPrint("[RegRoutine]AllocatePool Failed!\n");return FALSE;}//查詢名稱status = ObQueryNameString(pRegistryObject, (POBJECT_NAME_INFORMATION)pObjectName, returnedLength, &returnedLength );if(NT_SUCCESS(status)){RtlUnicodeStringCopy(pRegistryPath, pObjectName);//拷貝名稱foundCompleteName = TRUE;}ExFreePoolWithTag(pObjectName, 'ConT');//無論查詢是否成功都應該釋放記憶體 }return foundCompleteName;}
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.