360安全衛(wèi)士并沒有使用通常的方式——直接修改SSDT和SSDTShadow進(jìn)行掛鉤。由于兩個表中的函數(shù)最終是由系統(tǒng)未導(dǎo)出的函數(shù)KiFastCallEntry調(diào)用的,所以360在適當(dāng)?shù)奈恢脪燧d了KiFastCallEntry函數(shù),達(dá)到了過濾的目的。大多數(shù)ARK軟件只檢測了兩個表是否被更改,所以不能檢測出360的HOOK。
上面介紹的MyHookMgr結(jié)構(gòu)之所以占據(jù)近6K的連續(xù)內(nèi)存空間,是因為KiFastCallEntry是一個頻繁被系統(tǒng)調(diào)用的函數(shù),所以鉤子的效率十分重要,使用連續(xù)的空間可以節(jié)省出大量尋址時間,是一種空間換時間的做法。
KiFastCallEntry并沒有被系統(tǒng)模塊導(dǎo)出,360采取了一個比較巧妙的方法簡介獲得其地址。
1. 常規(guī)方法掛載ZwSetEvent函數(shù),代理函數(shù)為hookprot.sys模塊中的_HookKiFastCallEntryKnrl。
2. 之后馬上調(diào)用ZwSetEvent函數(shù)。
可以看到這里的handle為0x288C58F1,顯然是一個不合法的句柄。這里起到一個標(biāo)志,所用,我們的_HookKiFastCallEntryKnrl函數(shù)看到這個handle就會做一些特殊處理來尋找KiFastCallEntry的地址啦。
1. 然后會跳轉(zhuǎn)到_HookKiFastCallEntryKnrl中,如果句柄是0x288C58F1則恢復(fù)剛才的SSDT鉤子。并對KiFastCallEntry進(jìn)行掛載。
由于_HookKiFastCallEntryKnrl是KiFastCallEntry調(diào)用的,所以我們可以從棧針中找到的返回地址也就是KiFastCallEntry所在了。
代碼只需要一句 moveax, [ebp+4] 就可以了。
KiFastCallEntry是一個非常復(fù)雜的函數(shù),掛載位置很重要。
我們對比一下360安全衛(wèi)士掛載前和掛載后的函數(shù)。
掛載前:
8053d7dc ff0538f6dfff inc dword ptrds:[0FFDFF638h]
8053d7e2 8bf2 mov esi,edx
8053d7e4 8b5f0c mov ebx,dword ptr [edi+0Ch]
8053d7e7 33c9 xor ecx,ecx
8053d7e9 8a0c18 mov cl,byte ptr [eax+ebx]
8053d7ec 8b3f mov edi,dword ptr [edi]
8053d7ee 8b1c87 mov ebx,dword ptr [edi+eax*4]
8053d7f1 2be1 sub esp,ecx
8053d7f3 c1e902 shr ecx,2
8053d7f6 8bfc mov edi,esp
8053d7f8 3b35b48b5580 cmp esi,dword ptr [nt!MmUserProbeAddress(80558bb4)]
8053d7fe 0f83a8010000 jae nt!KiSystemCallExit2+0x9f (8053d9ac)
8053d804 f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
8053d806 ffd3 call ebx
8053d808 8be5 mov esp,ebp
8053d80a 8b0d24f1dfff mov ecx,dword ptr ds:[0FFDFF124h]
掛載后:
8053d7dc ff0538f6dfff inc dword ptrds:[0FFDFF638h]
8053d7e2 8bf2 mov esi,edx
8053d7e4 8b5f0c mov ebx,dword ptr [edi+0Ch]
8053d7e7 33c9 xor ecx,ecx
8053d7e9 8a0c18 mov cl,byte ptr [eax+ebx]
8053d7ec 8b3f mov edi,dword ptr [edi]
8053d7ee 8b1c87 mov ebx,dword ptr [edi+eax*4]
8053d7f1 e93289ca01 jmp 821e6128
8053d7f6 8bfc mov edi,esp
8053d7f8 3b35b48b5580 cmp esi,dword ptr [nt!MmUserProbeAddress(80558bb4)]
8053d7fe 0f83a8010000 jae nt!KiSystemCallExit2+0x9f (8053d9ac)
8053d804 f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
8053d806 ffd3 call ebx
8053d808 8be5 mov esp,ebp
8053d80a 8b0d24f1dfff mov ecx,dword ptr ds:[0FFDFF124h]
8053d810 8b553c mov edx,dword ptr [ebp+3Ch]
根據(jù)WRK的代碼我們知道,這時所有調(diào)用需要的環(huán)境都已經(jīng)準(zhǔn)備好了。360這里替換了
8053d7f1 2be1 sub esp,ecx
8053d7f3 c1e902 shr ecx,2
這兩條指令,實現(xiàn)了jmp,將這兩條指令放到Hook后的函數(shù)中處理,這里就不詳細(xì)敘述了。IDB文件中有比較詳細(xì)的注釋。