首页
社区
课程
招聘
[原创]通过CmRegisterCallback学习注册表监控与反注册表监控
发表于: 2021-10-26 19:03 29900

[原创]通过CmRegisterCallback学习注册表监控与反注册表监控

2021-10-26 19:03
29900

实验环境是Win7 X86系统。

曾经在这篇文章中常见的几种DLL注入技术说过,通过修改注册表的内容可以实现AppInit_DLLs注入。那么本文的实验是通过CmRegisterCallback来实现对注册表修改的监控以此来阻止修改。并通过对CmRegisterCallback的逆向分析来实现对监控函数的删除。

在Windows系统中,可以通过使用CmRegisterCallback来设置注册表监控的回调函数,该函数在文档中的定义如下

PEX_CALLBACK_FUNCTION回调函数在文档中的定义如下,该函数的返回值为STATUS_SUCCESS之外的错误码的时候,则表示系统会拒绝操作相应的注册表。

其中的REG_NOTIFY_CLASS定义如下

其中的几个比较常用的类型,它们的意义,以及对应的Argument2的结构体的内容如下

PREG_CREATE_KEY_INFORMATION结构体定义如下

关键的两个成员

CompleteName

PREG_DELETE_KEY_INFORMATION的结构体定义如下

成员Object指向要删除的注册表项的注册表项对象的指针。

PREG_DELETE_VALUE_KEY_INFORMATION结构体定义如下

PREG_SET_VALUE_KEY_INFORMATION结构体定义如下

根据上面的内容可以知道,回调函数中是可以获取要操作的注册表键的对象的,所以可以使用ObQueryNameString函数来获得键操作的键的名称,该函数在文档中的定义如下

OBJECT_NAME_INFORMATION的定义如下

只有一个UNICODE_STRING的Name参数,保存了返回的名称。

想要实现对监控函数的删除,可以使用CmUnRegisterCallback函数来实现,该函数在文档中的定义如下。它只有一个参数,就是前面设置监控函数时候指定的Cookie的地址

根据上面的内容就可以实现对注册表的监控来拒绝AppInit_DLLs的注入,具体实现代码如下

接下来通过IDA分析CmRegisterCallback来看看是如何保存注册表的回调函数。IDA中对CmRegisterCallback的反汇编如下

这个函数做了两件事情,将Init_Data的赋值赋给eax,将需要的参数入栈以后调用CmCRegisterCallback函数。经过分析以后发现,这个Init_Data是用来赋值一些数据,不过在这里用处不大,入栈的1也是。

继续看CmCRegisterCallback的反汇编代码

可以看到,系统分配0x30大小的内存来保存相应的内容,根据以上的分析可以得出下面的结论

最开始的8个字节保存的是一个LIST_ENTRY类型的双向链表

偏移0x10保存的是COOKIE

偏移0x1C保存的Context

偏移0x18保存的是回调函数的地址

所以可以想到注册表监控的回调函数是用LIST_ENTRY双向链表来一个个连起来的。而真正将分配的这块内存加入链表的函数则是SetRegisterCallback函数,以下是这个函数的反汇编分析

在这个ListBegin就是链表头的地址,里面保存的就是第一个链表的地址。首先会将它保存的内容取出判断保存的是否就是ListBegin的首地址,如果是的话就说明到了链表的尾部,接下来就会跳转到loc_69F3DE来把结构加进链表。如果不是的话,它会执行以下的循环,其中的一部分是

这个循环就是不断的取链表中的下一个数据直到链表尾。

找到以后,程序就会在loc_69F3DE处把数据加到链表里面

根据上面分析可以知道,注册表的监控回调函数被以链表的形式保存到了内存中,其中这个链表头是ListBegin。接下来只要找到这个链表头并且遍历这个链表,取出COOKIE就可以实现回调函数的删除。

而想要找到这个链表头,首先需要在CmRegisterCallback中使用0xE8找到CmcRegisterCallback

随后需要在CmCRegisterCallback中使用0x8BC6E8找到SetRegisterCallback

最终才在SetRegisterCallback中使用0xBB找到这个链表头


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2021-11-30 09:59 被1900编辑 ,原因:
收藏
免费 9
支持
分享
最新回复 (5)
雪    币: 515
活跃值: (3267)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wem
2
谢谢
2021-12-5 10:25
0
雪    币: 16402
活跃值: (1640)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
@1900  希望加入对目标程序写注册表的call地址拦截功能,并得到虚拟地址
2021-12-6 00:05
0
雪    币: 22411
活跃值: (25361)
能力值: ( LV15,RANK:910 )
在线值:
发帖
回帖
粉丝
4
killbr @1900 希望加入对目标程序写注册表的call地址拦截功能,并得到虚拟地址
那需要去HOOK函数了  不能用这种方法
2021-12-6 09:28
0
雪    币: 8111
活跃值: (6384)
能力值: ( LV12,RANK:207 )
在线值:
发帖
回帖
粉丝
5
PREG_DELETE_VALUE_KEY_INFORMATION 结构体贴错了
2022-10-19 11:51
0
雪    币: 243
活跃值: (3311)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
E1696        无法打开 源 文件 "ntifs.h",这个报错怎么解决
2023-3-21 20:49
0
游客
登录 | 注册 方可回帖
返回
//