用Visual studio11在Windows8上开发驱动实现注册表监控和过滤

来源:互联网 发布:鉴声师鉴声用什么软件 编辑:程序博客网 时间:2024/04/30 05:46

在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的注册表监控和过滤技术,请见代码分析


[cpp] view plaincopyprint?
  1. #include "ntifs.h" 
  2. #include "RegistryCallBack.h" 
  3. #include <ntstrsafe.h> 
  4.  
  5. NTSTATUS st; 
  6. LARGE_INTEGER g_CallbackCookie; 
  7. ANSI_STRING  astr; 
  8.   
  9. VOID UnloadDriver(PDRIVER_OBJECT DriverObject); 
  10.  
  11. NTSTATUS RegistryCallback(IN PVOID CallbackContext, INPVOID Argument1, IN PVOID Argument2); 
  12.  
  13. BOOLEAN GetRegistryObjectCompleteName(PUNICODE_STRING pRegistryPath, PUNICODE_STRING pPartialRegistryPath,PVOID pRegistryObject); 
  14.  
  15. NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) 
  16. {     
  17.      
  18.     DbgPrint("[RegRoutine]Loading!\n"); 
  19.      
  20.     DriverObject->DriverUnload = UnloadDriver; 
  21.          
  22.     st = CmRegisterCallback(RegistryCallback,NULL,&g_CallbackCookie); 
  23.     if ( !NT_SUCCESS(st) )   
  24.     { 
  25.         DbgPrint("[RegRoutine]CmRegisterCallback Failed!\n"); 
  26.         return st; 
  27.     } 
  28.     DbgPrint("[RegRoutine]RegistryCallback Addr:0x%08X\n",RegistryCallback);     
  29.     DbgPrint("[RegRoutine]Cookie.LowPart:0x%08X Cookie.HighPart:0x%08X\n",g_CallbackCookie.LowPart,g_CallbackCookie.HighPart); 
  30.     return st; 
  31. VOID UnloadDriver(PDRIVER_OBJECT DriverObject) 
  32.     CmUnRegisterCallback(g_CallbackCookie); 
  33.     DbgPrint("[RegRoutine]UnLoading!\n"); 
  34.  
  35. NTSTATUS  
  36.   RegistryCallback( 
  37.     IN PVOID  CallbackContext, 
  38.     IN PVOID  Argument1, 
  39.     IN PVOID  Argument2  
  40.     ) 
  41.     int type; 
  42.     BOOLEAN exception = FALSE; 
  43.     BOOLEAN registryEventIsValid = FALSE; 
  44.     UNICODE_STRING registryPath; 
  45.     UCHAR* registryData = NULL; 
  46.     ULONG registryDataLength = 0; 
  47.     ULONG registryDataType = 0; 
  48.      
  49.     registryPath.Length = 0; 
  50.     registryPath.MaximumLength = NTSTRSAFE_UNICODE_STRING_MAX_CCH * sizeof(WCHAR); 
  51.     registryPath.Buffer = ExAllocatePoolWithTag(NonPagedPool, registryPath.MaximumLength,'ConT'); 
  52.      
  53.     if(registryPath.Buffer == NULL) 
  54.     { 
  55.         DbgPrint("[RegRoutine]Allocate registryPath failed!\n"); 
  56.         return STATUS_SUCCESS; 
  57.     } 
  58.      
  59.     type = (REG_NOTIFY_CLASS)Argument1; 
  60.      
  61.     try 
  62.     { 
  63.         switch(type) 
  64.         { 
  65.             case RegNtPostCreateKey: 
  66.             {    
  67.                 PREG_POST_CREATE_KEY_INFORMATION createKey = (PREG_POST_CREATE_KEY_INFORMATION)Argument2; 
  68.                 if( NT_SUCCESS(createKey->Status) || createKey->Status == STATUS_PENDING )//创建注册表项状态为成功和未决的都记录一下 
  69.                 { 
  70.                     PVOID* registryObject = createKey->Object; 
  71.                     registryEventIsValid = GetRegistryObjectCompleteName(®istryPath, createKey->CompleteName,*registryObject); 
  72.                     if ( registryEventIsValid ) 
  73.                     { 
  74.                         RtlUnicodeStringToAnsiString(&astr,®istryPath,TRUE); 
  75.                         DbgPrint("[RegCreated]KeyName:%s!\n",astr.Buffer); 
  76.                          
  77.                         //如果创建的是自启动项,则警告一下 
  78.                         if ( strstr(astr.Buffer,"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run") ) 
  79.                         { 
  80.                             DbgPrint("[RegCreated]Forbin!\n"); 
  81.                             DbgPrint("[RegCreated]ForbinKeyName:%s!\n",astr.Buffer); 
  82.                             RtlFreeAnsiString(&astr); 
  83.                         } 
  84.                         RtlFreeAnsiString(&astr); 
  85.                     } 
  86.                     else 
  87.                         DbgPrint("[RegCreated]Get Key Name Failed!\n"); 
  88.                 } 
  89.                  
  90.             } 
  91.                 break
  92.             //使用PreCreateKey可以阻止key的创建,但是能够作为判断依据的只有一个key的CompleteName,无法得到完整路径来判断 
  93.             case RegNtPreCreateKey: 
  94.             { 
  95.                 PREG_PRE_CREATE_KEY_INFORMATION createKey = (PREG_PRE_CREATE_KEY_INFORMATION)Argument2; 
  96.                 RtlCopyUnicodeString(®istryPath,createKey->CompleteName); 
  97.                 RtlUnicodeStringToAnsiString(&astr,®istryPath,TRUE); 
  98.                 DbgPrint("[RegRoutine]PreCreate:%s!\n",astr.Buffer); 
  99.                 if ( !strcmp(astr.Buffer,"新项 #1") ) 
  100.                         { 
  101.                             DbgPrint("[RegRoutine]Forbin!\n"); 
  102.                             DbgPrint("[RegRoutine]ForbinKeyName:%s!\n",astr.Buffer); 
  103.                             RtlFreeAnsiString(&astr); 
  104.                             return STATUS_INVALID_PARAMETER; 
  105.                         } 
  106.                 RtlFreeAnsiString(&astr); 
  107.             } 
  108.                 break
  109.             case RegNtDeleteKey: 
  110.             { 
  111.                 PREG_DELETE_KEY_INFORMATION deleteKey = (PREG_DELETE_KEY_INFORMATION)Argument2; 
  112.                 registryEventIsValid = GetRegistryObjectCompleteName(®istryPath, NULL, deleteKey->Object); 
  113.                  
  114.                 if ( registryEventIsValid ) 
  115.                     { 
  116.                         RtlUnicodeStringToAnsiString(&astr,®istryPath,TRUE); 
  117.                         DbgPrint("[RegDeletedKey]KeyName:%s!\n",astr.Buffer); 
  118.                         if ( !strcmp(astr.Buffer,"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\\ljh00001") ) 
  119.                         { 
  120.                             DbgPrint("[RegDeletedKey]Forbin!\n"); 
  121.                             DbgPrint("[RegDeletedKey]ForbinKeyName:%s!\n"); 
  122.                             RtlFreeAnsiString(&astr); 
  123.                             return STATUS_INVALID_PARAMETER; 
  124.                         } 
  125.                         RtlFreeAnsiString(&astr); 
  126.                     } 
  127.                      
  128.             } 
  129.                 break
  130.             case RegNtSetValueKey: 
  131.             { 
  132.                 PREG_SET_VALUE_KEY_INFORMATION setvalue = (PREG_SET_VALUE_KEY_INFORMATION)Argument2; 
  133.                  
  134.                 if( MmIsAddressValid(setvalue->ValueName) ) 
  135.                 { 
  136.                     registryEventIsValid = GetRegistryObjectCompleteName(®istryPath, NULL, setvalue->Object); 
  137.                  
  138.                     if ( registryEventIsValid ) 
  139.                     { 
  140.                         RtlUnicodeStringToAnsiString(&astr,®istryPath,TRUE); 
  141.                         DbgPrint("[RegSetValue]ValueParentPath:%s!\n",astr.Buffer); 
  142.                         RtlFreeAnsiString(&astr); 
  143.                     } 
  144.                     RtlUnicodeStringToAnsiString(&astr,setvalue->ValueName,TRUE); 
  145.                     DbgPrint("[RegSetValue]ValueName:%s!\n",astr.Buffer); 
  146.                     RtlFreeAnsiString(&astr); 
  147.                     //输出设置的键值的数据类型和大小,如果类型是REG_SZ则data是一个unicode_string,而数据大小为buffer长度 
  148.                     //加上4字节长度的length和MaxLength再加上2个字节的结尾00的长度 
  149.                     DbgPrint("[RegSetValue]ValueDataType:%X,DataSize:%X\n",setvalue->Type,setvalue->DataSize); 
  150.                     if ( setvalue->Type == 1 )//Type为REG_SZ,其它类型的数据暂时忽略  
  151.                     { 
  152.                         DbgPrint("[RegSetValue]Data:%ws\n",setvalue->Data); 
  153.                     } 
  154.                 } 
  155.                  
  156.             } 
  157.                 break
  158.             case RegNtDeleteValueKey: 
  159.             { 
  160.                 PREG_DELETE_VALUE_KEY_INFORMATION deletevalue = (PREG_DELETE_VALUE_KEY_INFORMATION)Argument2; 
  161.                  
  162.                 if( MmIsAddressValid(deletevalue->ValueName) ) 
  163.                 { 
  164.                     registryEventIsValid = GetRegistryObjectCompleteName(®istryPath, NULL, deletevalue->Object); 
  165.                  
  166.                     if ( registryEventIsValid ) 
  167.                     { 
  168.                         RtlUnicodeStringToAnsiString(&astr,®istryPath,TRUE); 
  169.                         DbgPrint("[RegDelValue]ValueParentPath:%s!\n",astr.Buffer); 
  170.                         RtlFreeAnsiString(&astr); 
  171.                     } 
  172.                     RtlUnicodeStringToAnsiString(&astr,deletevalue->ValueName,TRUE); 
  173.                     DbgPrint("[RegDelValue]ValueName:%s!\n",astr.Buffer); 
  174.                     if ( !strcmp(astr.Buffer,"ljh00001") ) 
  175.                         { 
  176.                             DbgPrint("[RegDelValue]Forbin!\n"); 
  177.                             DbgPrint("[RegDelValue]ForbinKeyName:%s!\n"); 
  178.                             RtlFreeAnsiString(&astr); 
  179.                             return STATUS_INVALID_PARAMETER; 
  180.                         } 
  181.                     RtlFreeAnsiString(&astr); 
  182.                 } 
  183.                  
  184.             } 
  185.                 break
  186.             case RegNtRenameKey: 
  187.             { 
  188.                 PREG_RENAME_KEY_INFORMATION renamevalue = (PREG_RENAME_KEY_INFORMATION)Argument2; 
  189.                  
  190.                 if( MmIsAddressValid(renamevalue->NewName) ) 
  191.                 { 
  192.                     registryEventIsValid = GetRegistryObjectCompleteName(®istryPath, NULL, renamevalue->Object); 
  193.                  
  194.                     if ( registryEventIsValid ) 
  195.                     { 
  196.                         RtlUnicodeStringToAnsiString(&astr,®istryPath,TRUE); 
  197.                         DbgPrint("[RegRenameKey]KeyPath:%s!\n",astr.Buffer); 
  198.                         RtlFreeAnsiString(&astr); 
  199.                     } 
  200.                     RtlUnicodeStringToAnsiString(&astr,renamevalue->NewName,TRUE); 
  201.                     DbgPrint("[RegRenameKey]KeyName:%s!\n",astr.Buffer); 
  202.                     RtlFreeAnsiString(&astr); 
  203.                 } 
  204.                  
  205.             } 
  206.                 break
  207.             default
  208.                 break
  209.         } 
  210.     }  
  211.     except( EXCEPTION_EXECUTE_HANDLER )  
  212.     { 
  213.         DbgPrint("[RegRoutine]Catch a Expection!\n"); 
  214.         exception = TRUE; 
  215.         registryEventIsValid = FALSE; 
  216.     } 
  217.      
  218.     if(registryPath.Buffer != NULL) 
  219.     { 
  220.         ExFreePoolWithTag(registryPath.Buffer, 'ConT'); 
  221.     } 
  222.     return STATUS_SUCCESS; 
  223.  
  224.  
  225. BOOLEAN GetRegistryObjectCompleteName(PUNICODE_STRING pRegistryPath, PUNICODE_STRING pPartialRegistryPath,PVOID pRegistryObject) 
  226.     BOOLEAN foundCompleteName = FALSE; 
  227.     BOOLEAN partial = FALSE; 
  228.     NTSTATUS status; 
  229.     ULONG returnedLength; 
  230.     PUNICODE_STRING pObjectName = NULL; 
  231.     //判断object的有效性 
  232.     if( (!MmIsAddressValid(pRegistryObject)) || (pRegistryObject == NULL) ) 
  233.     { 
  234.         DbgPrint("[RegRoutine]pRegistryObject Invalid!\n"); 
  235.         return FALSE; 
  236.     } 
  237.     //使用ObQueryNameString来得到object对应的名称 
  238.     status = ObQueryNameString(pRegistryObject, (POBJECT_NAME_INFORMATION)pObjectName, 0, &returnedLength ); 
  239.     if(status == STATUS_INFO_LENGTH_MISMATCH)  //第一次传的buffer长度为0,ObQueryNameString返回的结果必定是缓冲区大小不足 
  240.     { 
  241.         pObjectName = ExAllocatePoolWithTag(NonPagedPool, returnedLength,'ConT'); //申请内存 
  242.         if ( pObjectName == NULL ) //申请内存失败则返回FALSE 
  243.         { 
  244.             DbgPrint("[RegRoutine]AllocatePool Failed!\n"); 
  245.             return FALSE; 
  246.         } 
  247.         //查询名称 
  248.         status = ObQueryNameString(pRegistryObject, (POBJECT_NAME_INFORMATION)pObjectName, returnedLength, &returnedLength ); 
  249.         if(NT_SUCCESS(status)) 
  250.         { 
  251.             RtlUnicodeStringCopy(pRegistryPath, pObjectName);  //拷贝名称 
  252.             foundCompleteName = TRUE; 
  253.         } 
  254.         ExFreePoolWithTag(pObjectName, 'ConT');//无论查询是否成功都应该释放内存    
  255.     } 
  256.  
  257.     return foundCompleteName; 
  258.  
  259.  

原文地址:http://blog.csdn.net/yincheng01/article/details/8107320

原创粉丝点击