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內(nèi)存地址的確定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所在了。 代碼只需要一句 mov eax, [ebp+4] 就可以了。 KiFastCallEntry是一個非常復(fù)雜的函數(shù),掛載位置很重要。 我們對比一下360安全衛(wèi)士掛載前和掛載后的函數(shù)。 掛載前: 8053d7dc ff0538f6dfff inc dword ptr
ds:[0FFDFF638h] 掛載后: 8053d7dc ff0538f6dfff inc dword ptr
ds:[0FFDFF638h] 根據(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ì)的注釋。 |
|