首页
社区
课程
招聘
[原创]瑞星2011 Hookhelp.sys在LoadImageNotifyRoutine中的全局性Fast Mutex设置可能导致死锁(deadlock)
发表于: 2011-4-1 10:43 32040

[原创]瑞星2011 Hookhelp.sys在LoadImageNotifyRoutine中的全局性Fast Mutex设置可能导致死锁(deadlock)

2011-4-1 10:43
32040
收藏
免费 8
支持
分享
最新回复 (35)
雪    币: 1233
活跃值: (907)
能力值: ( LV12,RANK:750 )
在线值:
发帖
回帖
粉丝
26
不错,学习了
2011-4-6 08:35
0
雪    币: 605
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cfz
27
正在用瑞星的杀毒,进来看下。。谢谢分享
2011-4-6 12:38
0
雪    币: 51
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
28
强帖,留名,分析很透彻
2011-4-6 13:45
0
雪    币: 379
活跃值: (152)
能力值: ( LV12,RANK:330 )
在线值:
发帖
回帖
粉丝
29
分析的十分透彻,学习了
2011-4-6 17:28
0
雪    币: 95
活跃值: (56)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
30
很久没有看到轩辕小聪发贴~一来就是好贴啊~
2011-4-13 16:52
0
雪    币: 12
活跃值: (773)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
31
今天更新了下驱动,估计解决了
2011-4-14 21:11
0
雪    币: 722
活跃值: (123)
能力值: ( LV12,RANK:300 )
在线值:
发帖
回帖
粉丝
32
4月1日当天晚上,我在瑞星论坛版主区以及相应Q群上联系瑞星人员告知该问题。
4月7日瑞星人员通过论坛短消息联系我,并通过邮箱发送正在测试中的新版HookHelp.sys驱动给我测试。该驱动版本号25.0.0.11,数字签名时间戳‎2011‎年‎4‎月‎2‎日 15:14:14,从这个时间上看瑞星算是挺重视的了,我4月1日告知的内容第二天就进行了修补。
换上这个驱动之后终于可以正常使用了,于是我又分析了一下,不过因为当时此驱动处于测试阶段,详情就没有往这里发。
直到4月14日瑞星终于通过更新推送了这个驱动(同时还更新了HookTdi.sys)。

新版HookHelp.sys驱动的具体做法是在hookhelp.sys注册的CreateProcessNotifyRoutine中,修改了获取子进程映像文件名的方法。

原函数调用位置(hookhelp.sys版本号25.0.0.9):
.text:00011FF6                 push    208h            ; Size
.text:00011FFB                 lea     ecx, [ebp+ProcessFileNameBuffer]
.text:00012001                 push    ecx             ; Buffer
.text:00012002                 mov     edx, [ebp+ProcessId]
.text:00012005                 push    edx             ; ProcessId
.text:00012006                 mov     ecx, ds:FastMutex
.text:0001200C                 call    GetProcessFileName

现函数调用位置:
.text:00011CF6                 push    208h            ; Size
.text:00011CFB                 lea     ecx, [ebp+ProcessFileNameBuffer]
.text:00011D01                 push    ecx             ; Buffer
.text:00011D02                 push    0               ; ImagePathOffsetModify
.text:00011D04                 mov     edx, [ebp+ProcessId]
.text:00011D07                 push    edx             ; ProcessId
.text:00011D08                 mov     ecx, ds:FastMutex
.text:00011D0E                 call    GetProcessFileName

可以看到多了一个参数,这个参数在函数中用来修正_RTL_USER_PROCESS_PARAMETERS结构中ImagePathName的偏移,应该是针对另一个版本的系统预留的。

原函数出问题的地方,根源在于它调用NtReadVirtualMemory来读取子进程用户态空间内容,而这个函数在nt内核中其实是未导出给内核态使用的,而只是在SSDT上给用户态使用的,它要求读取内容后写入的目标缓冲区也是用户态缓冲区,因此原函数必须调用ZwAllocateVirtualMemory先为自身进程获取一块位于用户态空间的缓冲区,才能调用NtReadVirtualMemory。而正是对ZwAllocateVirtualMemory的调用内容将获取自身进程的AddressCreationLock,这个动作加上hookhelp.sys的全局性Fast Mutex,就可能导致与另一线程的LoadImageNotifyRoutine之间造成死锁。

为了避免这个死锁,应该放弃使用ZwAllocateVirtualMemory,从而也放弃使用NtReadVirtualMemory这个本来就不是为内核态调用准备的函数,直接使用KeStackAttachProcess切换到目标进程的上下文直接读取。

修改之后的hookhelp.sys,采用了如下方法:
1. 仍然使用ZwOpenProcess获取进程句柄,再使用ZwQueryInformationProcess(ProcessBasicInformation)获取进程信息,从而得到进程PEB地址。这一步与原来是一样的。
2. 第1步的句柄关闭后,再次使用ZwOpenProcess获取进程句柄,这一次的目的是使用ObReferenceObjectByHandle通过这个句柄得到EPROCESS结构指针。
3. 当目标进程不是自身进程时,采用KeStackAttachProcess切换到目标进程的上下文,然后直接读取其中的内容得到ImagePathName
4. 最后KeUnstackDetachProcess切换回来后ObfDereferenceObjece和ZwClose进行扫尾。

总的来说,确实实现了避免原先的ZwAllocateVirtualMemory造成的死锁,初步看起来应该是解决了我提到的问题,至少不会完全卡死了。
不过第1、2步仍稍显累赘,特别是有了ProcessId的情况下,还要先获取Handle再用ObReferenceObjectByHandle来得到EPROCESS,是没有必要的,完全可以用PsLookupProcessByProcessId一步到位(实际上ZwOpenProcess内部也是PsLookupProcessByProcessId再ObOpenObjectByPointer得到Handle)
另外,原函数得到ImagePathName之后还有个格式转换并转大写的操作,现函数没有。
2011-4-15 00:46
0
雪    币: 585
活跃值: (568)
能力值: ( LV13,RANK:290 )
在线值:
发帖
回帖
粉丝
33
留起,,33333333333333
2011-4-15 11:18
0
雪    币: 585
活跃值: (568)
能力值: ( LV13,RANK:290 )
在线值:
发帖
回帖
粉丝
34
好想找个专门研究内核工作,现在做的RING3工作太没意思了。,,,
2011-4-18 19:54
0
雪    币: 235
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
35
真是分析强帖啊,留下脚印
2011-7-8 09:40
0
雪    币: 3738
活跃值: (3872)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
36
感谢分享!
2023-2-4 15:30
0
游客
登录 | 注册 方可回帖
返回
//