浅谈基于 callback 的注册表监控和过滤技 术

上传人:wt****50 文档编号:37828411 上传时间:2018-04-23 格式:PDF 页数:7 大小:747.26KB
返回 下载 相关 举报
浅谈基于 callback 的注册表监控和过滤技 术_第1页
第1页 / 共7页
浅谈基于 callback 的注册表监控和过滤技 术_第2页
第2页 / 共7页
浅谈基于 callback 的注册表监控和过滤技 术_第3页
第3页 / 共7页
浅谈基于 callback 的注册表监控和过滤技 术_第4页
第4页 / 共7页
浅谈基于 callback 的注册表监控和过滤技 术_第5页
第5页 / 共7页
点击查看更多>>
资源描述

《浅谈基于 callback 的注册表监控和过滤技 术》由会员分享,可在线阅读,更多相关《浅谈基于 callback 的注册表监控和过滤技 术(7页珍藏版)》请在金锄头文库上搜索。

1、2009 年第年第 7 期期 前置知识:VC 关键词:编程、CallBack、注册表 浅谈基于浅谈基于 CallBack 的注册表监控和过滤技的注册表监控和过滤技术术 文文/图图 ly(cqupt) ljh(cqupt) 说起注册表监控技术, 大家的第一反应应该就是 SSDT 或者 inline hook Zw/Nt 系列的注 册表操作函数(大多数杀毒软件和 HIPS 都是采用这种方式,最经典的莫过于 sysinternal 出 品的 RegMon 了) ,再深入一点可能会想到 Hook Object 系列的函数,比如 coldzenleft 曾经 在黑防上发表过 hook ObOpenObj

2、ectByPointer、ObRefrenceObjectByPointer 保护注册表的文 章。再往下就到了 object hook 的层次,比如 hook CmpKeyObject 的 ParseProcedure 等。 这些方法无一例外都需要先 Hook,而如今对于 Hook 的检测也已经是越来越普及了 (CmpKeyObject hook 的目前公开的 ark 只有 XueTr 可以检测出) 。抛开检测不说,Hook 本 身的兼容性、稳定性也是个难题,Hook 做起来容易,可是要做到稳定兼容的 Hook 就很需 要功力了。 除了自己实现的五花八门的 Hook 之外,对于注册表的监控和过

3、滤还是有别的办法。黑 防以前的文章都没有写到过微软提供的注册表 callback,这里就给大家稍微介绍一下吧。 按照 WDK 文档的描述,在 Windows XP 系统下,内核模式驱动程序可以调用 CmRegisterCallback 函数来注册一个回调例程,调用 CmUnRegisterCallback 函数来卸载这个 例程。 在配置管理器进行注册表操作之前会给这个例程发送通知, 每一次注册表操作的信息 都会被填充进一个 REG_Xxx_KEY_INFORMATION 结构体里面。回调例程能够阻止注册 表操作(不包括创建注册表项和打开注册表项) ,当配置管理器完成创建注册表项或者打开 注册表

4、项的操作时,回调例程也能接收到通知。 使用微软提供的注册表 callback 来监控和过滤注册表操作,最大的好处就是稳定和方 便。不需要繁琐的编码,不需要担惊受怕 Hook 失败系统蓝屏,而且目前公开的 ARK 我测 试过 IceSword、Rku、XueTr、Gmer、CodeWalker、PsNull、狙剑都没有检测注册表 callback 的功能,隐蔽性还算不错吧。 言归正传,我们先来看看函数原型。 NTSTATUS CmRegisterCallback( IN PEX_CALLBACK_FUNCTION Function, IN PVOID Context, OUT PLARGE_IN

5、TEGER Cookie ); 再来看看 callback 例程函数的原型: NTSTATUS RegistryCallback( 黑客防线 w w w .h a c k e r .c o m .c n 转载请注明出处2009 年第年第 7 期期 IN PVOID CallbackContext, IN PVOID Argument1, IN PVOID Argument2 ); 使用 callback 例程的关键就在于正确的区分和处理第一个参数的情况,也就是处理好 Notification 的 Type。Windows XP 支持的 Notification Type 有以下几种: RegN

6、tDeleteKey、RegNtPreDeleteKey、RegNtSetValueKey、 RegNtPreSetValueKey、RegNtDeleteValueKey、RegNtPreDeleteValueKey、 RegNtSetInformationKey、RegNtPreSetInformationKey、RegNtRenameKey、 RegNtPreRenameKey、RegNtEnumerateKey、RegNtPreEnumerateKey、 RegNtEnumerateValueKey、RegNtPreEnumerateValueKey、RegNtQueryKey、 Re

7、gNtPreQueryKey、RegNtQueryValueKey、RegNtPreQueryValueKey、 RegNtQueryMultipleValueKey、RegNtPreQueryMultipleValueKey、 RegNtPreCreateKey、RegNtPostCreateKey、RegNtPreOpenKey、 RegNtPostOpenKey、RegNtKeyHandleClose 和 RegNtPreKeyHandleClose。其中 含有 Post 的都是在注册表操作成功完成之后才会收到通知,所以只能用来做记录,不能用 来过滤,而另外两种都是既可以记录也可以过滤的

8、。RegNtPreCreateKey 和 RegNtPreOpenKey 比较特殊,只在 Windowss XP 平台有效,可以阻止注册表项的创建 和打开,但使用这两种类型只能得到一个不完整的项名,因为其结构体定义是这样的: typedef struct _REG_PRE_CREATE_KEY_INFORMATION PUNICODE_STRING CompleteName; REG_PRE_CREATE_KEY_INFORMATION, REG_PRE_OPEN_KEY_INFORMATION, *PREG_PRE_OPEN_KEY_INFORMATION; 在 RegistryCallba

9、ck 函数中,传进来的两个参数,第一个指明了 Notification 的类型,第二个则是相应的结构体信息。由于传进来的结构体通常包含的 Unicode 形式的 KeyName 都是不完整的,而通常这个结构体中都会有注册表项的 object 指针,所以我们 可以使用 ObQueryNameString 来查询,再加上其中已经包含 KeyName,就可以得到完 整的注册表路径。实现代码如下: BOOLEAN GetRegistryObjectCompleteName(PUNICODE_STRING pRegistryPath,PUNICODE_STRING pPartialRegistryPat

10、h, PVOID pRegistryObject) BOOLEAN foundCompleteName = FALSE; BOOLEAN partial = FALSE; NTSTATUS status; ULONG returnedLength; PUNICODE_STRING pObjectName = NULL; /判断 object 的有效性 if( (!MmIsAddressValid(pRegistryObject) | (pRegistryObject = NULL) ) DbgPrint(“RegRoutinepRegistryObject Invalid!n“); 黑客防线

11、w w w .h a c k e r .c o m .c n 转载请注明出处2009 年第年第 7 期期 return FALSE; /使用 ObQueryNameString 得到 object 对应的名称 status = ObQueryNameString(pRegistryObject, (POBJECT_NAME_INFORMATION)pObjectName, 0, if(status = STATUS_INFO_LENGTH_MISMATCH)/第一次传的 buffer 长度为 0, ObQueryNameString 返回的结果必定是缓冲区大小不足 pObjectName =

12、ExAllocatePoolWithTag(NonPagedPool, returnedLength, ConT); /申请内存 if ( pObjectName = NULL ) /申请内存失败则返回 FALSE DbgPrint(“RegRoutineAllocatePool Failed!n“); return FALSE; /查询名称 status = ObQueryNameString(pRegistryObject, (POBJECT_NAME_INFORMATION)pObjectName, returnedLength, if(NT_SUCCESS(status) RtlUni

13、codeStringCopy(pRegistryPath, pObjectName);/拷贝名称 foundCompleteName = TRUE; ExFreePoolWithTag(pObjectName, ConT);/无论查询是否成功都应该释放内存 return foundCompleteName; 接下来我们看看 RegistryCallback 的实现代码,完整代码请参见附件中的 RegistryCallback.c。首先是 PostCreateKey,这个类型只在 Windows XP 下才有, 只支持记录,不能用作过滤。 case RegNtPostCreateKey: PRE

14、G_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( if ( registryEventIsVal

15、id ) RtlUnicodeStringToAnsiString( 黑客防线 w w w .h a c k e r .c o m .c n 转载请注明出处2009 年第年第 7 期期 DbgPrint(“RegCreatedKeyName:%s!n“,astr.Buffer); /如果创建的是自启动项,则警告 if ( strstr(astr.Buffer,“REGISTRYMACHINESOFTWAREMicrosoftWindowsCurrentVersio nRun“) ) DbgPrint(“RegCreatedForbin!n“); DbgPrint(“RegCreatedForb

16、inKeyName:%s!n“,astr.Buffer); RtlFreeAnsiString( RtlFreeAnsiString( else DbgPrint(“RegCreatedGet Key Name Failed!n“); 最终得到的效果如图 1 所示。之后是 DeleteKey 的实现,代码如下: 图 1 case RegNtDeleteKey: PREG_DELETE_KEY_INFORMATION deleteKey = (PREG_DELETE_KEY_INFORMATION)Argument2; registryEventIsValid = GetRegistryObjectCompleteN

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 建筑/环境 > 建筑资料

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号