> 文章列表 > nvlddmkm.sys导致蓝屏(tsfltmgr.sys)

nvlddmkm.sys导致蓝屏(tsfltmgr.sys)

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、}

本文到此结束,希望对大家有所帮助。