标签:
同事一WindowsXP系统,正常执行,关闭后,第二天无法启动。详细症状为:
(1)安全模式以及带网络功能的安全模式都能够进入。
(2)正常模式。还没出现WindowXP滚动栏就開始重新启动;
(3)进安全模式,禁用自己主动重新启动后,再正常启动,出现蓝屏。报TsFltMgr.sys内存错误!
经过互联网查询,和不断摸索。最后发现居然是可恶的QQ软件管家惹的祸,进安全模式果断卸载QQ软件管家后,再重新启动,系统全然正常了。
以下转载了一篇分析QQ电脑管家的文章,请參考:
QQ电脑管家中的TsFltMgr Hook框架分析
分析不正确的地方请多多包涵。
kd> u KiFastCallEntry+e3 nt!KiFastCallEntry+0xe3: 8053dbb3 c1e902 shr ecx,2 ------------------------------------------------------------------------- 8053dbb6 90 nop 8053dbb7 90 nop 8053dbb8 90 nop 8053dbb9 e962170c77 jmp TsFltMgr+0x2320 (f75ff320) ------------------------------------------------------------------------- 8053dbbe 0f83a8010000 jae nt!KiSystemCallExit2+0x9f (8053dd6c) 8053dbc4 f3a5 rep movs dword ptr es:[edi],dword ptr [esi] 8053dbc6 ffd3 call ebx
// 保存现场 pushfd pushad // 调用 KiFastCallEntry_Filter 函数,实现过滤 push edi // 本次系统调用相应的SysCall Table的地址(SSDT或SSDTShadow的地址) push ebx // 本次系统调用在SysCall Table中相应的内核函数地址 push eax // 本次系统调用相应的内核函数在SysCall Table中的功能号 call KiFastCallEntry_Filter // 调用KiFastCallEntry_Filter,实现过滤 mov [esp+10h], eax // 更改本次调用相应的内核函数地址! // 恢复现场 popad popfd // 运行 KiFastCallEntry 函数中被替换掉的指令。并跳回原函数 mov edi,esp cmp esi, g_7fff0000 push g_JmpBack ret
因此此处的mov [esp+10h], eax实际上是用 KiFastCallEntry_Filter 函数的返回值来改写堆栈中保存的ebx的值,即改写本次系统调用相应的内核函数地址。
ULONG __stdcall KiFastCallEntry_Filter(ULONG ulSyscallId, ULONG ulSyscallAddr, PULONG pulSyscallTable) { PFAKE_SYSCALL pFakeSysCall = NULL; if ( ulSyscallId >= 0x400 ) return ulSyscallAddr; if ( pulSyscallTable == g_KiServiceTable && ulSyscallId <= g_ServiceNum/* 0x11c */ ) { pFakeSysCall = g_FakeSysCallTable[ulSyscallId]; // SSDT } else if (pulSyscallTable == g_KeServiceDescriptorTable && g_KeServiceDescriptorTable && ulSyscallId <= g_ServiceNum/* 0x11c */) { pFakeSysCall = g_FakeSysCallTable[ulSyscallId]; // SSDT } else if (pulSyscallTable == g_W32pServiceTableAddr && ulSyscallId <= g_ShadowServiceNum/* 0x29b */) { pFakeSysCall = g_FakeSysCallTable[ulSyscallId + 1024]; // ShadowSSDT } if ( pFakeSysCall && pFakeSysCall->ulFakeSysCallAddr ) { pFakeSysCall->ulOrigSysCallAddr = ulSyscallAddr; return pFakeSysCall->ulFakeSysCallAddr; } return ulSyscallAddr; }
typedef struct __FAKE_SYSCALL__ { ULONG xxx1; ULONG ulSyscallId; // 该系统调用的功能号 ULONG xxx3; ULONG ulTableIndex; ULONG xxx5; ULONG ulCountForPreWork; ULONG ulCountForPostWork; ULONG xxx8; ULONG ulOrigSysCallAddr; // 真实的系统调用地址 ULONG ulFakeSysCallAddr; // 假的系统调用地址 ULONG xxx11; ULONG xxx12; ULONG xxx13; …… } FAKE_SYSCALL, *PFAKE_SYSCALL, **PPFAKE_SYSCALL;
// SSDT中: 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 // ShadowSSDT中: NtUserBuildHwndList、NtUserFindWindowEx、NtUserGetForegroundWindow、NtUserMoveWindow、NtUserQueryWindow、NtUserSendInput、NtUserSetParent、NtUserSetWindowLong、NtUserSetWindowPlacement、NtUserSetWindowPos、NtUserShowWindow、NtUserShowWindowAsync、NtUserWindowFromPoint
NTSTATUS __stdcall FakeNt_XXX(xxx) { PFAKE_SYSCALL pFakeSysCall; ULONG ulXXX = 0; ULONG ulStatus; NTSTATUS status; ULONGLONG ullTickCount; pFakeSysCall = g_pFakeSysCall_Nt_XXX; // 该系统调用相应的 pFakeSysCall 对象 status = STATUS_ACCESS_DENIED; // 貌似是做性能測试时候须要的,实际版本号中 g_bPerformanceTest 为 FALSE if ( g_bPerformanceTest ) { ullTickCount = KeQueryInterruptTime(); } // 系统调用的调用前处理! // +++ InterlockedIncrement(&pFakeSysCall->ulCountForPreWork); ulStatus = PreWork(&ulXXX, pFakeSysCall); InterlockedDecrement(&pFakeSysCall->ulCountForPreWork); // --- if ( ulStatus != 0xEEEE0004 && ulStatus != 0xEEEE0005) { OrigSysCall * pOrigSysCall = pFakeSysCall->ulOrigSysCallAddr; // 调用原始系统调用! if ( pOrigSysCall && NT_SUCCESS(pOrigSysCall(xxx)) ) { // 系统调用的调用后处理。 // +++ InterlockedIncrement(&pFakeSysCall->ulCountForPostWork), ulStatus = PostWork(&ulXXX), InterlockedDecrement(&pFakeSysCall->ulCountForPostWork), // --- } } // 0xEEEE0004 应该是拒绝调用的意思,0xEEEE0005 应该是同意调用的意思 if (ulStatus == 0xEEEE0005) status = STATUS_SUCCESS; // PsGetCurrentProcessId 这个调用的返回值后面并没实用到,可能是多余的 PsGetCurrentProcessId(); // 貌似是做性能測试时候须要的 if ( g_pFakeSysCall_NtTerminateProcess->xxx5 && ullTickCount && g_bPerformanceTest) { PerformanceTest(&g_pFakeSysCall_NtTerminateProcess->xxx13, ullTickCount); } return status; }
TsFltMgr.sys其原因是,该系统蓝屏QQ计算机管理器!
标签:
原文地址:http://www.cnblogs.com/lcchuguo/p/4560665.html