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

来源:互联网 发布:淘宝上水果能买吗 编辑:程序博客网 时间:2024/05/17 08:03

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

分类: Visual C++2010编程技术 VC++编程技术 Visual Studio2012 Windows8 1738人阅读 评论(1) 收藏 举报

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