nvlddmkm.sys导致蓝屏(tsfltmgr.sys)
大家好,小杨来为大家解答以上问题,nvlddmkm.sys导致蓝屏,tsfltmgr.sys很多人还不知道,现在让我们一起来看看吧!
1、(1)可以进入安全模式和带网络功能的安全模式;
2、(2)正常模式,在WindowXP滚动条出现之前?重新开始;
3、(3)进入安全模式,禁用你的主动重启,然后正常启动。出现蓝屏并向TsFltMgr.sys报告内存错误!
4、上网查询,不断摸索,终于发现是可恶的QQ软件管家的错。在安全模式下坚决卸载QQ软件管家后,我重新启动,系统完全正常。
5、以下转载一篇分析QQ电脑管家的文章,请参考:
6、QQ电脑管家中TsFltMgr钩子框架分析
7、在新版QQ电脑管家中,有一个驱动名为TsFltMgr.sys这个驱动简单分析一下,看到一个漂亮的钩子框架,发出来和大家分享一下。如果分析有误,请见谅。
8、首先,TsFltMgr挂钩KiFastCallEntry函数,挂钩点在这里:
9、代码:
10、复制代码
11、代码如下:
12、kd u KiFastCallEntry+e3
13、nt!KiFastCallEntry+0xe3:
14、8053dbb3 c1e902 shr ecx,2
15、-------------------------------------------------------------------------
16、8053dbb6 90 nop
17、8053dbb7 90 nop
18、8053dbb8 90 nop
19、8053dbb9 e962170c77 jmp TsFltMgr+0x2320 (f75ff320)
20、-------------------------------------------------------------------------
21、8053dbbe 0f83a8010000 jae nt!KiSystemCallExit2+0x9f (8053dd6c)
22、8053dbc4 f3a5 rep movs double-word pointer es:[edi], double-word pointer [esi]
23、8053dbc6 ffd3 call ebx
24、原始的KiFastCallEntry在shr ecx,2指令后面应该是mov edi,espcmp esi,MmUserProbeAddress,共8个字节,
25、在这里,它被TsFltMgr替换为三个nop和一个jmp。
26、jmp会跳转到kifastcullenty _ detail函数,kifastcullenty _ detail函数的代码如下:
27、代码:
28、复制代码
29、代码如下:
30、//保存网站
31、pushfd
32、pushad
33、//调用KiFastCallEntry_Filter函数实现过滤。
34、Push edi //这个系统调用中对应SysCall表的地址(SSDT或SSDTShadow的地址)。
35、Push ebx //系统调用SysCall表中对应的内核函数地址。
36、推送eax //本次系统调用中SysCall表中对应内核函数的函数号。
37、call KiFastCallEntry_Filter //调用KiFastCallEntry_Filter,实现过滤
38、mov [esp+10h], eax //更改本次调用相应的内核函数地址!
39、//恢复现场
40、popad
41、popfd
42、//运行KiFastCallEntry 函数中被替换掉的指令,并跳回原函数
43、mov edi,esp
44、cmp esi, g_7fff0000
45、push g_JmpBack
46、ret
47、这里须要注意的是call KiFastCallEntry_Filter 之后的mov [esp+10h], eax。之前保存现场时的指令pushad会导致寄存器EAX, ECX, EDX,
48、 EBX, ESP, EBP, ESI, EDI依次入栈,并通过后面的popad指令恢复这些寄存器的值。因此此处的mov [esp+10h],
49、 eax实际上是用KiFastCallEntry_Filter 函数的返回值来改写堆栈中保存的ebx的值,即改写本次系统调用相应的内核函数地址。
50、KiFastCallEntry_Filter 是真正实现过滤的函数,该函数的?数和返回值上文已经说明了,其详细实现分析整理后,C语言描写叙述例如以下:
51、代码:
52、复制代码
53、代码如下:
54、ULONG __stdcall KiFastCallEntry_Filter(ULONG ulSyscallId, ULONG ulSyscallAddr,
55、 PULONG pulSyscallTable)
56、{
57、PFAKE_SYSCALL pFakeSysCall=NULL;
58、if ( ulSyscallId=0x400 )
59、return ulSyscallAddr;
60、if ( pulSyscallTable==g_KiServiceTable ulSyscallId=g_ServiceNum/*0x11c */)
61、{
62、pFakeSysCall=g_FakeSysCallTable[ulSyscallId]; //SSDT
63、}
64、else if (pulSyscallTable==g_KeServiceDescriptorTable
65、g_KeServiceDescriptorTable ulSyscallId=g_ServiceNum/*0x11c */)
66、{
67、pFakeSysCall=g_FakeSysCallTable[ulSyscallId]; //SSDT
68、}
69、else if (pulSyscallTable==g_W32pServiceTableAddr ulSyscallId=g_ShadowServiceNum/*0x29b */)
70、{
71、pFakeSysCall=g_FakeSysCallTable[ulSyscallId + 1024]; //ShadowSSDT
72、}
73、if ( pFakeSysCall pFakeSysCall-ulFakeSysCallAddr )
74、{
75、pFakeSysCall-ulOrigSysCallAddr=ulSyscallAddr;
76、return pFakeSysCall-ulFakeSysCallAddr;
77、}
78、return ulSyscallAddr;
79、}
80、这里须要说明的是,TsFltMgr内部有一张表,暂且命名为g_FakeSysCallTable,该表中存放的是指向FAKE_SYSCALL 结构的指针。
81、表中的每个FAKE_SYSCALL 结构相应一个系统调用,表的前半部分相应SSDT中的系统调用,1024项以后相应ShadowSSDT里的系统调用。
82、当中FAKE_SYSCALL 结构大致例如以下(当中非常多域的作用没弄明确):
83、代码:
84、复制代码
85、代码如下:
86、typedef struct __FAKE_SYSCALL__ {
87、ULONG xxx1;
88、ULONG ulSyscallId; //该系统调用的功能号
89、ULONG xxx3;
90、ULONG ulTableIndex;
91、ULONG xxx5;
92、ULONG ulCountForPreWork;
93、ULONG ulCountForPostWork;
94、ULONG xxx8;
95、ULONG ulOrigSysCallAddr; //真实的系统调用地址
96、ULONG ulFakeSysCallAddr; //假的系统调用地址
97、ULONG xxx11;
98、ULONG xxx12;
99、ULONG xxx13;
100、……
101、} FAKE_SYSCALL, *PFAKE_SYSCALL, **PPFAKE_SYSCALL;
102、因此KiFastCallEntry_Filter 函数的所做的就是依据系统调用的功能号在g_FakeSysCallTable 中索引出相应的pFakeSysCall 对象,
103、然后推断该系统调用是否须要hook,假设须要则将真实的系统调用地址保存到pFakeSysCall-ulOrigSysCallAddr 中,
104、并将pFakeSysCall-ulFakeSysCallAddr 作为假系统调用的地址返回。
105、这样的调用过程中动态获取真实系统调用地址的方法使TsFltMgr 的Hook框架有较高的兼容性,比如不会使载入顺序晚于TsFltMgr的驱动中的SSDT Hook失效,
106、比如QQ电脑管家本身带的TSKsp.sys驱动。
107、对于我的?试系统(XP_SP2),TsFltMgr hook的函数有:
108、代码:
109、复制代码
110、代码如下:
111、//SSDT中:
112、NtCreateFile、NtCreateKey、NtCreateSection、NtCreateSymbolicLinkObject、NtCreateThread、NtDeleteFile、NtDeleteKey、NtDeleteValueKey、NtDeviceIoControlFile、NtDuplicateObject、NtEnumerateValueKey、NtLoadDriver、NtOpenProcess、NtOpenSection、NtProtectVirtualMemory、NtQueryValueKey、NtRequestWaitReplyPort、NtSetContextThread、NtSetInformationFile、NtSetSystemInformation、NtSetValueKey、NtSuspendThread、NtSystemDebugControl、NtTerminateProcess、NtTerminateThread、NtWriteFile、NtWriteVirtualMemory
113、//ShadowSSDT中:
114、NtUserBuildHwndList、NtUserFindWindowEx、NtUserGetForegroundWindow、NtUserMoveWindow、NtUserQueryWindow、NtUserSendInput、NtUserSetParent、NtUserSetWindowLong、NtUserSetWindowPlacement、NtUserSetWindowPos、NtUserShowWindow、NtUserShowWindowAsync、NtUserWindowFromPoint
115、全部假系统函数都有统一的代码框架,假系统函数的代码框架大致例如以下:
116、代码:
117、复制代码
118、代码如下:
119、NTSTATUS __stdcall FakeNt_XXX(xxx)
120、{
121、PFAKE_SYSCALL pFakeSysCall;
122、ULONG ulXXX=0;
123、ULONG ulStatus;
124、NTSTATUS status;
125、ULONGLONG ullTickCount;
126、pFakeSysCall=g_pFakeSysCall_Nt_XXX; //该系统调用相应的pFakeSysCall 对象
127、status=STATUS_ACCESS_DENIED;
128、//貌似是做性能?试时候须要的,实际版本号中g_bPerformanceTest 为FALSE
129、if ( g_bPerformanceTest ) {
130、ullTickCount=KeQueryInterruptTime();
131、}
132、//系统调用的调用前处理!
133、//+++
134、InterlockedIncrement(pFakeSysCall-ulCountForPreWork);
135、ulStatus=PreWork(ulXXX, pFakeSysCall);
136、InterlockedDecrement(pFakeSysCall-ulCountForPreWork);
137、//---
138、if ( ulStatus !=0xEEEE0004 ulStatus !=0xEEEE0005)
139、{
140、OrigSysCall * pOrigSysCall=pFakeSysCall-ulOrigSysCallAddr;
141、//调用原始系统调用!
142、if ( pOrigSysCall NT_SUCCESS(pOrigSysCall(xxx)) )
143、{
144、//系统调用的调用后处理!
145、//+++
146、InterlockedIncrement(pFakeSysCall-ulCountForPostWork),
147、ulStatus=PostWork(ulXXX),
148、InterlockedDecrement(pFakeSysCall-ulCountForPostWork),
149、//---
150、}
151、}
152、//0xEEEE0004 应该是拒绝调用的意思,0xEEEE0005 应该是同意调用的意思
153、if (ulStatus==0xEEEE0005)
154、status=STATUS_SUCCESS;
155、//PsGetCurrentProcessId 这个调用的返回值后面并没实用到,可能是多余的
156、PsGetCurrentProcessId();
157、//貌似是做性能?试时候须要的
158、if ( g_pFakeSysCall_NtTerminateProcess-xxx5 ullTickCount g_bPerformanceTest) {
159、PerformanceTest(g_pFakeSysCall_NtTerminateProcess-xxx13, ullTickCount);
160、}
161、return status;
162、}
本文到此结束,希望对大家有所帮助。