首页
社区
课程
招聘
关于驱动的一个困扰很久的问题
发表于: 2014-4-1 16:03 5318

关于驱动的一个困扰很久的问题

2014-4-1 16:03
5318
最近刚接触驱动不久,在网上看到了微软的一个内核函数CmregistryCallback能有效的保护注册表,看了些例子,这里在编译通过后一加载完去修改跟我保护键值有关的操作时候就蓝屏,有没有熟悉的朋友可以点播小弟一下
以下是源码:

#include "ntifs.h"
#include <ntstrsafe.h>
#include <ntddk.h>
#define REGISTRY_POOL_TAG 'pRE'

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);
                                        }
                                        else
                                                DbgPrint("[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 RegNtPostOpenKey:
             {
              PREG_POST_OPEN_KEY_INFORMATION openKey = (PREG_POST_OPEN_KEY_INFORMATION)Argument2;
              if(NT_SUCCESS(openKey->Status))
              {
                PVOID* registryObject = openKey->Object;
                registryEventIsValid = GetRegistryObjectCompleteName(®istryPath, openKey->CompleteName, *registryObject);
              }
         
        break;
             }
            
          /*
            case RegNtPreDeleteKey:
            {
              PREG_DELETE_KEY_INFORMATION deleteKey = (PREG_DELETE_KEY_INFORMATION)Argument2;
              registryEventIsValid = GetRegistryObjectCompleteName(®istryPath, NULL, deleteKey->Object);
              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\\USER\\Software\\Microsoft\\Internet Explorer\\Main") )  
                        {  
                            DbgPrint("[RegDeletedKey]Forbin!\n");  
                            DbgPrint("[RegDeletedKey]ForbinKeyName:%s!\n");  
                            RtlFreeAnsiString(&astr);  
                            return STATUS_INVALID_PARAMETER;  
                        }  
                        RtlFreeAnsiString(&astr);   
                        }         
                                break;               
                        }
                               
                        case RegNtDeleteValueKey:
                        {
                               
                                PREG_DELETE_VALUE_KEY_INFORMATION deleteValueKey = (PREG_DELETE_VALUE_KEY_INFORMATION)Argument2;
                                if( MmIsAddressValid(deleteValueKey->ValueName))
                                {
                                registryEventIsValid = GetRegistryObjectCompleteName(®istryPath, NULL, deleteValueKey->Object);
                                if((registryEventIsValid) && (deleteValueKey->ValueName->Length > 0))
                                {
               
                                        RtlUnicodeStringToAnsiString(&astr,®istryPath,TRUE);
                                        DbgPrint("[RegDeletedKey]KeyName:%s!\n",astr.Buffer);
                                        RtlFreeAnsiString(&astr);
                                }
                                RtlUnicodeStringToAnsiString(&astr,deleteValueKey->ValueName,TRUE);  
                                DbgPrint("[RegDelValue]ValueName:%s!\n",astr.Buffer);
                                        if ( !strcmp(astr.Buffer,"Start Page"))  
                                        {  
                                               
                                                DbgPrint("[RegDelValue]Forbin!\n");  
                                                DbgPrint("[RegDelValue]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 RegNtPreSetValueKey:
                        {
                                PREG_SET_VALUE_KEY_INFORMATION setValueKey = (PREG_SET_VALUE_KEY_INFORMATION)Argument2;
                        if( MmIsAddressValid(setValueKey->ValueName) )
                        {
                                registryEventIsValid = GetRegistryObjectCompleteName(®istryPath, NULL, setValueKey->Object);
                               
                                if((registryEventIsValid) && (setValueKey->ValueName->Length > 0))
                                {
                                        RtlUnicodeStringToAnsiString(&astr,®istryPath,TRUE);
                                        DbgPrint("[RegSetKey]KeyName:%s!\n",astr.Buffer);
                                        RtlFreeAnsiString(&astr);
                                   registryDataType = setValueKey->Type;
                            registryDataLength = setValueKey->DataSize;
                            registryData = ExAllocatePoolWithTag(NonPagedPool, registryDataLength, REGISTRY_POOL_TAG);
                                }
                                RtlUnicodeStringToAnsiString(&astr,setValueKey->ValueName,TRUE);  
                                DbgPrint("[RegSetValue]ValueName:%s!\n",astr.Buffer);
                            if(registryData != NULL)
                            {
                                        if ( !strcmp(astr.Buffer,"Start Page") )  
                                        {  
                                                DbgPrint("[RegSetValue]Forbin!\n");  
                                                DbgPrint("[RegSetValue]ForbinKeyName:%s!\n");  
                                                RtlFreeAnsiString(&astr);  
                                                return STATUS_INVALID_PARAMETER;  
                                        }   
                              //RtlCopyBytes(registryData,setValueKey->Data,setValueKey->DataSize);
                                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);
                                                if ( !strcmp(astr.Buffer,"\\REGISTRY\\USER\\SOFTWARE\\Microsoft\\Internet Explorer\\Main") )
                                                {
                                                        DbgPrint("[RegDeletedKey]Forbin!\n");
                                                        DbgPrint("[RegDeletedKey]ForbinKeyName:%s!\n");
                                                        RtlFreeAnsiString(&astr);
                                                        return STATUS_INVALID_PARAMETER;
                                                }
                                                RtlFreeAnsiString(&astr);
                                        }
                                        RtlUnicodeStringToAnsiString(&astr,renamevalue->NewName,TRUE);
                                        DbgPrint("[RegRenameKey]KeyName:%s!\n",astr.Buffer);
                                        RtlFreeAnsiString(&astr);
                                }
                               
                                break;
                        }
                       
                        case RegNtEnumerateKey:
                        {
                                PREG_ENUMERATE_KEY_INFORMATION enumerateKey = (PREG_ENUMERATE_KEY_INFORMATION)Argument2;
                                registryDataType = enumerateKey->KeyInformationClass;
                                registryEventIsValid = GetRegistryObjectCompleteName(®istryPath, NULL, enumerateKey->Object);
                                break;
                        }
                       
                        case RegNtEnumerateValueKey:
                        {
                                PREG_ENUMERATE_VALUE_KEY_INFORMATION enumerateValueKey = (PREG_ENUMERATE_VALUE_KEY_INFORMATION)Argument2;
                                registryDataType = enumerateValueKey->KeyValueInformationClass;
                                registryEventIsValid = GetRegistryObjectCompleteName(®istryPath, NULL, enumerateValueKey->Object);
                                break;
                        }
                       
                        case RegNtQueryKey:
                        {
                                PREG_QUERY_KEY_INFORMATION queryKey = (PREG_QUERY_KEY_INFORMATION)Argument2;
                                registryDataType = queryKey->KeyInformationClass;
                                registryEventIsValid = GetRegistryObjectCompleteName(®istryPath, NULL, queryKey->Object);
                                break;
                        }
                       
                        case RegNtQueryValueKey:
                        {
                                PREG_QUERY_VALUE_KEY_INFORMATION queryValueKey = (PREG_QUERY_VALUE_KEY_INFORMATION)Argument2;
                                registryEventIsValid = GetRegistryObjectCompleteName(®istryPath, NULL, queryValueKey->Object);
                                if((registryEventIsValid) && (queryValueKey->ValueName->Length > 0))
                                {
                                        registryDataType = queryValueKey->KeyValueInformationClass;
                                        RtlUnicodeStringCatString(®istryPath,L"\\");
                                        RtlUnicodeStringCat(®istryPath, queryValueKey->ValueName);
                                }
                        break;
                        }
                       
                        case RegNtKeyHandleClose:
                        {
                                PREG_KEY_HANDLE_CLOSE_INFORMATION closeKey = (PREG_KEY_HANDLE_CLOSE_INFORMATION)Argument2;
                                registryEventIsValid = GetRegistryObjectCompleteName(®istryPath, NULL, closeKey->Object);
                                break;
                        }

                       
                        default:
                                break;
                }
        }
        except( EXCEPTION_EXECUTE_HANDLER )
        {
                DbgPrint("[RegRoutine]Catch a Expection!\n");
                exception = TRUE;
                registryEventIsValid = FALSE;
        }
       
        if(registryEventIsValid)
        {
               
                if(registryData != NULL)
                {
                        ExFreePoolWithTag(registryData, REGISTRY_POOL_TAG);
                }       
                       
        }
       
        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;
   }
   
   

        if(pPartialRegistryPath != NULL)
        {
                if( (((pPartialRegistryPath->Buffer[0] == '\\') || (pPartialRegistryPath->Buffer[0] == '%')) ||
                        ((pPartialRegistryPath->Buffer[0] == 'T') && (pPartialRegistryPath->Buffer[1] == 'R') &&
                         (pPartialRegistryPath->Buffer[2] == 'Y') && (pPartialRegistryPath->Buffer[3] == '\\'))) )
                {
                        RtlUnicodeStringCopy(pRegistryPath, pPartialRegistryPath);
                        partial = TRUE;
                        foundCompleteName = TRUE;
                }
        }
       
       
        if(!foundCompleteName)
        {
                //使用ObQueryNameString来得到object对应的名称
          status = ObQueryNameString(pRegistryObject, (POBJECT_NAME_INFORMATION)pObjectName, 0, &returnedLength );
         
          //第一次传的buffer长度为0,ObQueryNameString返回的结果必定是缓冲区大小不足
          if(status == STATUS_INFO_LENGTH_MISMATCH)       
          {
                    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;

}

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (7)
雪    币: 4
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
前面说错了......是蓝屏
2014-4-1 16:16
0
雪    币: 11
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
新人来看看是否可以帮助上忙。
2014-4-1 16:27
0
雪    币: 4
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
有没有大神知道的,请点拨一下小弟,不胜感激
2014-4-1 17:55
0
雪    币: 1689
活跃值: (379)
能力值: ( LV15,RANK:440 )
在线值:
发帖
回帖
粉丝
5
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);
            // ANSI_STRING 的字符串数据不一定以零结尾哦!!,strcmp......
            if ( !strcmp(astr.Buffer,"\\REGISTRY\\USER\\SOFTWARE\\Microsoft\\Internet Explorer\\Main") )
            {
              DbgPrint("[RegDeletedKey]Forbin!\n");
              DbgPrint("[RegDeletedKey]ForbinKeyName:%s!\n");
              RtlFreeAnsiString(&astr);
              return STATUS_INVALID_PARAMETER;
            }
            RtlFreeAnsiString(&astr);
          }
          RtlUnicodeStringToAnsiString(&astr,renamevalue->NewName,TRUE);
          DbgPrint("[RegRenameKey]KeyName:%s!\n",astr.Buffer);
          RtlFreeAnsiString(&astr);
        }
        
        break;
      }
2014-4-1 20:09
0
雪    币: 79
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
自己动手用windbg调试一下很快就出来了,这样直接看代码一方面不容易找到答案,另外一方面也很耗费时间
2014-4-1 21:16
0
雪    币: 4
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
再次非常感谢hackerlzc给予我的帮助!!
2014-4-2 14:34
0
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
路过,看看。。。
2014-4-3 21:40
0
游客
登录 | 注册 方可回帖
返回
//