TsFltMgr.sys系統(tǒng)藍(lán)屏的原因分析(小心QQ電腦管家)

同事一WindowsXP系統(tǒng),正常執(zhí)行,關(guān)閉后,第二天無法啟動(dòng),詳細(xì)癥狀為:
(1)安全模式以及帶網(wǎng)絡(luò)功能的安全模式都能夠進(jìn)入;
(2)正常模式,還沒出現(xiàn)WindowXP滾動(dòng)欄就開始重新啟動(dòng);
(3)進(jìn)安全模式,禁用自己主動(dòng)重新啟動(dòng)后,再正常啟動(dòng),出現(xiàn)藍(lán)屏,報(bào)TsFltMgr.sys內(nèi)存錯(cuò)誤!
經(jīng)過互聯(lián)網(wǎng)查詢,和不斷摸索,最后發(fā)現(xiàn)居然是可惡的QQ軟件管家惹的禍,進(jìn)安全模式果斷卸載QQ軟件管家后,再重新啟動(dòng),系統(tǒng)全然正常了。
以下轉(zhuǎn)載了一篇分析QQ電腦管家的文章,請(qǐng)參考:
QQ電腦管家中的TsFltMgr Hook框架分析
新版的QQ電腦管家中多了一個(gè)名字叫TsFltMgr.sys的驅(qū)動(dòng)(應(yīng)該是Sysnap大牛開發(fā)的,膜拜),對(duì)該驅(qū)動(dòng)進(jìn)行了一些簡單的分析,看見了一套美麗的Hook框架,發(fā)出來與大家分享。分析不正確的地方請(qǐng)多多包涵。
首先TsFltMgr掛鉤了KiFastCallEntry函數(shù),Hook點(diǎn)在這里:
代碼:
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
原始的KiFastCallEntry在 shr ecx, 2 指令后面應(yīng)該是 mov edi,esp;cmp esi, MmUserProbeAddress,共8個(gè)字節(jié),在這里被 TsFltMgr 替換成了3個(gè)nop和一個(gè)jmp。
該jmp會(huì)跳轉(zhuǎn)到 KiFastCallEntry_Detour 函數(shù)中,KiFastCallEntry_Detour 函數(shù)代碼例如以下:
代碼:
// 保存現(xiàn)場(chǎng)
pushfd
pushad </p> <p>// 調(diào)用 KiFastCallEntry_Filter 函數(shù),實(shí)現(xiàn)過濾
push edi // 本次系統(tǒng)調(diào)用相應(yīng)的SysCall Table的地址(SSDT或SSDTShadow的地址)
push ebx // 本次系統(tǒng)調(diào)用在SysCall Table中相應(yīng)的內(nèi)核函數(shù)地址
push eax // 本次系統(tǒng)調(diào)用相應(yīng)的內(nèi)核函數(shù)在SysCall Table中的功能號(hào)
call KiFastCallEntry_Filter // 調(diào)用KiFastCallEntry_Filter,實(shí)現(xiàn)過濾
mov [esp+10h], eax // 更改本次調(diào)用相應(yīng)的內(nèi)核函數(shù)地址!</p> <p>// 恢復(fù)現(xiàn)場(chǎng)
popad
popfd</p> <p>// 運(yùn)行 KiFastCallEntry 函數(shù)中被替換掉的指令,并跳回原函數(shù)
mov edi,esp
cmp esi, g_7fff0000
push g_JmpBack
ret
這里須要注意的是 call KiFastCallEntry_Filter 之后的 mov [esp+10h], eax。之前保存現(xiàn)場(chǎng)時(shí)的指令pushad會(huì)導(dǎo)致寄存器EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI依次入棧,并通過后面的popad指令恢復(fù)這些寄存器的值。因此此處的mov [esp+10h], eax實(shí)際上是用 KiFastCallEntry_Filter 函數(shù)的返回值來改寫堆棧中保存的ebx的值,即改寫本次系統(tǒng)調(diào)用相應(yīng)的內(nèi)核函數(shù)地址。
KiFastCallEntry_Filter 是真正實(shí)現(xiàn)過濾的函數(shù),該函數(shù)的參數(shù)和返回值上文已經(jīng)說明了,其詳細(xì)實(shí)現(xiàn)分析整理后,C語言描寫敘述例如以下:
代碼:
ULONG __stdcall KiFastCallEntry_Filter(ULONG ulSyscallId, ULONG ulSyscallAddr, PULONG pulSyscallTable)
{
PFAKE_SYSCALL pFakeSysCall = NULL;</p> <p> if ( ulSyscallId >= 0x400 )
return ulSyscallAddr;</p> <p> 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
}</p> <p> if ( pFakeSysCall && pFakeSysCall->ulFakeSysCallAddr )
{
pFakeSysCall->ulOrigSysCallAddr = ulSyscallAddr;
return pFakeSysCall->ulFakeSysCallAddr;
}
return ulSyscallAddr;
}
這里須要說明的是,TsFltMgr內(nèi)部有一張表,暫且命名為 g_FakeSysCallTable,該表中存放的是指向 FAKE_SYSCALL 結(jié)構(gòu)的指針。表中的每個(gè) FAKE_SYSCALL 結(jié)構(gòu)相應(yīng)一個(gè)系統(tǒng)調(diào)用,表的前半部分相應(yīng)SSDT中的系統(tǒng)調(diào)用,1024項(xiàng)以后相應(yīng)ShadowSSDT里的系統(tǒng)調(diào)用。
當(dāng)中 FAKE_SYSCALL 結(jié)構(gòu)大致例如以下(當(dāng)中非常多域的作用沒弄明確):
代碼:
typedef struct __FAKE_SYSCALL__ {
ULONG xxx1;
ULONG ulSyscallId; // 該系統(tǒng)調(diào)用的功能號(hào)
ULONG xxx3;
ULONG ulTableIndex;
ULONG xxx5;
ULONG ulCountForPreWork;
ULONG ulCountForPostWork;
ULONG xxx8;
ULONG ulOrigSysCallAddr; // 真實(shí)的系統(tǒng)調(diào)用地址
ULONG ulFakeSysCallAddr; // 假的系統(tǒng)調(diào)用地址
ULONG xxx11;
ULONG xxx12;
ULONG xxx13;
……
} FAKE_SYSCALL, *PFAKE_SYSCALL, **PPFAKE_SYSCALL;
因此 KiFastCallEntry_Filter 函數(shù)的所做的就是依據(jù)系統(tǒng)調(diào)用的功能號(hào)在 g_FakeSysCallTable 中索引出相應(yīng)的 pFakeSysCall 對(duì)象,然后推斷該系統(tǒng)調(diào)用是否須要hook,假設(shè)須要?jiǎng)t將真實(shí)的系統(tǒng)調(diào)用地址保存到 pFakeSysCall->ulOrigSysCallAddr 中,并將 pFakeSysCall->ulFakeSysCallAddr 作為假系統(tǒng)調(diào)用的地址返回。
這樣的調(diào)用過程中動(dòng)態(tài)獲取真實(shí)系統(tǒng)調(diào)用地址的方法使 TsFltMgr 的Hook框架有較高的兼容性,比如不會(huì)使載入順序晚于TsFltMgr的驅(qū)動(dòng)中的SSDT Hook失效,比如QQ電腦管家本身帶的TSKsp.sys驅(qū)動(dòng)。
對(duì)于我的測(cè)試系統(tǒng)(XP_SP2),TsFltMgr hook的函數(shù)有:
代碼:
// 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</p> <p>// ShadowSSDT中:
NtUserBuildHwndList、NtUserFindWindowEx、NtUserGetForegroundWindow、NtUserMoveWindow、NtUserQueryWindow、NtUserSendInput、NtUserSetParent、NtUserSetWindowLong、NtUserSetWindowPlacement、NtUserSetWindowPos、NtUserShowWindow、NtUserShowWindowAsync、NtUserWindowFromPoint
全部假系統(tǒng)函數(shù)都有統(tǒng)一的代碼框架,假系統(tǒng)函數(shù)的代碼框架大致例如以下:
代碼:
NTSTATUS __stdcall FakeNt_XXX(xxx)
{
PFAKE_SYSCALL pFakeSysCall;
ULONG ulXXX = 0;
ULONG ulStatus;
NTSTATUS status;
ULONGLONG ullTickCount;
pFakeSysCall = g_pFakeSysCall_Nt_XXX; // 該系統(tǒng)調(diào)用相應(yīng)的 pFakeSysCall 對(duì)象
status = STATUS_ACCESS_DENIED;
</p> <p> // 貌似是做性能測(cè)試時(shí)候須要的,實(shí)際版本號(hào)中 g_bPerformanceTest 為 FALSE
if ( g_bPerformanceTest ) {
ullTickCount = KeQueryInterruptTime();
}</p> <p>
// 系統(tǒng)調(diào)用的調(diào)用前處理!
// +++
InterlockedIncrement(&pFakeSysCall->ulCountForPreWork);
ulStatus = PreWork(&ulXXX, pFakeSysCall);
InterlockedDecrement(&pFakeSysCall->ulCountForPreWork);
// ---
if ( ulStatus != 0xEEEE0004 && ulStatus != 0xEEEE0005)
{
OrigSysCall * pOrigSysCall = pFakeSysCall->ulOrigSysCallAddr;</p> <p> // 調(diào)用原始系統(tǒng)調(diào)用!
if ( pOrigSysCall && NT_SUCCESS(pOrigSysCall(xxx)) )
{
// 系統(tǒng)調(diào)用的調(diào)用后處理!
// +++
InterlockedIncrement(&pFakeSysCall->ulCountForPostWork),
ulStatus = PostWork(&ulXXX),
InterlockedDecrement(&pFakeSysCall->ulCountForPostWork),
// ---
}
}</p> <p> // 0xEEEE0004 應(yīng)該是拒絕調(diào)用的意思,0xEEEE0005 應(yīng)該是同意調(diào)用的意思
if (ulStatus == 0xEEEE0005)
status = STATUS_SUCCESS;</p> <p> // PsGetCurrentProcessId 這個(gè)調(diào)用的返回值后面并沒實(shí)用到,可能是多余的
PsGetCurrentProcessId();</p> <p> // 貌似是做性能測(cè)試時(shí)候須要的
if ( g_pFakeSysCall_NtTerminateProcess->xxx5 && ullTickCount && g_bPerformanceTest) {
PerformanceTest(&g_pFakeSysCall_NtTerminateProcess->xxx13, ullTickCount);
}</p> <p> return status;
}
以上就是對(duì)TsFltMgr Hook框架的一些分析,祝大家元宵快樂~
相關(guān)文章
- 當(dāng)遇到USB接口驅(qū)動(dòng)異常時(shí),可以通過多種方法來解決,其中主要就包括重裝USB控制器、禁用USB選擇性暫停設(shè)置、更新或安裝新的主板驅(qū)動(dòng)等2025-04-23
解除U盤有寫保護(hù)的方法(詳細(xì)步驟與解決方案)
在日常使用U盤的過程中,許多用戶可能會(huì)遇到U盤突然無法寫入數(shù)據(jù)的問題,這通常是由于U盤被寫保護(hù)所致,寫保護(hù)功能雖然可以防止數(shù)據(jù)被意外修改或刪除,但在需要寫入新數(shù)據(jù)時(shí)2024-12-14- 最近配置了服務(wù)器,并做了磁盤陣列,突然有一天硬盤找不到了,然后重新陣列找回,但在磁盤管理器中發(fā)現(xiàn)雖然可以看到分區(qū)了,但提醒硬盤是只讀模式無法寫入文件,參考如下方2024-12-14
電腦無法正常啟動(dòng)開機(jī)怎么辦? 手把手教你排查故障
電腦是現(xiàn)代人生活中不可缺少的工具,但有時(shí)候我們會(huì)遇到電腦開機(jī)失敗的情況,這時(shí)候我們應(yīng)該怎么辦呢?本文將從多個(gè)方面為大家介紹解決辦法2024-10-26電腦藍(lán)屏代碼memory_management怎么解決? 系統(tǒng)藍(lán)屏原因
電腦突然藍(lán)屏,顯示memory management,上來就被這串英文鎮(zhèn)住了,藍(lán)屏memory management是什么?為什么會(huì)出現(xiàn)藍(lán)屏memory management呢?,詳細(xì)請(qǐng)看下文介紹2024-08-01如何解決wpcap.dll丟失? 電腦wpcap.dll文件破損的修復(fù)方法
如果文件wpcap.dll丟失有什么辦法可以解決,出現(xiàn)wpcap.dll丟失的的原因又是因?yàn)槭裁茨??今天就大家了解一下wpcap.dll文件,希望能夠你給在解決wpcap.dll文件的問題上有所幫2024-08-01pasmutility.dll缺失怎么辦? 電腦pasmutility.dll丟失的修復(fù)技巧
如果你在打開某些程序或者游戲時(shí)遇到了“缺失pasmutility.dll”的錯(cuò)誤提示,不要驚慌,這是一個(gè)非常普遍的問題,下面我們就來看看詳細(xì)的教程2024-08-01svcapicall.dll丟失怎么解決? 電腦提示svcapicall.dll文件損壞的修復(fù)技
在使用電腦的過程中,有時(shí)會(huì)遇到各種各樣的問題,其中之一就是dll文件丟失的情況,特別是當(dāng)出現(xiàn)svcapicall.dll丟失的問題時(shí),很多人可能會(huì)束手無策,,下面我們就來看看這個(gè)2024-07-30ser32.dll丟失怎么辦? 電腦提示ser32.dll文件丟失破損的修復(fù)方法
如果出現(xiàn)user32.dll丟失的情況,可能會(huì)影響操作系統(tǒng)的正常運(yùn)行,今天這篇文章本文將介紹電腦缺失user32.dll丟失的解決辦法,詳細(xì)說明解決步驟2024-07-30msstdfmt.dll文件損壞丟失怎么辦? 快速的修復(fù)msstdfmt.dll丟失的方法
你是否曾經(jīng)碰到過弄丟msstdfmt.dll文件的情況呢?如果你遇到此問題,不必驚慌,在本文中,將為您介紹幾種修復(fù)msstdfmt.dll文件的方法,幫助您解決這一問題2025-03-20