同事一WindowsXP系統,正常執行,關閉后,第二天無法啟動,詳細癥狀為:
(1)安全模式以及帶網絡功能的安全模式都能夠進入;
(2)正常模式,還沒出現WindowXP滾動欄就開始重新啟動;
(3)進安全模式,禁用自己主動重新啟動后,再正常啟動,出現藍屏,報TsFltMgr.sys內存錯誤!
經過互聯網查詢,和不斷摸索,最后發現居然是可惡的QQ軟件管家惹的禍,進安全模式果斷卸載QQ軟件管家后,再重新啟動,系統全然正常了。
以下轉載了一篇分析QQ電腦管家的文章,請參考:
QQ電腦管家中的TsFltMgr?Hook框架分析
新版的QQ電腦管家中多了一個名字叫TsFltMgr.sys的驅動(應該是Sysnap大牛開發的,膜拜),對該驅動進行了一些簡單的分析,看見了一套美麗的Hook框架,發出來與大家分享。分析不正確的地方請多多包涵。
首先TsFltMgr掛鉤了KiFastCallEntry函數,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
該jmp會跳轉到?KiFastCallEntry_Detour?函數中,KiFastCallEntry_Detour?函數代碼例如以下:
//?保存現場
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
KiFastCallEntry_Filter?是真正實現過濾的函數,該函數的參數和返回值上文已經說明了,其詳細實現分析整理后,C語言描寫敘述例如以下:
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;
}
當中?FAKE_SYSCALL?結構大致例如以下(當中非常多域的作用沒弄明確):
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;
這樣的調用過程中動態獲取真實系統調用地址的方法使?TsFltMgr?的Hook框架有較高的兼容性,比如不會使載入順序晚于TsFltMgr的驅動中的SSDT?Hook失效,比如QQ電腦管家本身帶的TSKsp.sys驅動。
對于我的測試系統(XP_SP2),TsFltMgr?hook的函數有:
//?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;
}
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

