基于VEH&調(diào)試寄存器實現(xiàn)無痕HOOK(5)

作者?| 榴蓮
編輯?| 楌橪
Windows操作系統(tǒng)中存在多種異常處理,我們現(xiàn)在需要的是其中的VEH(VectoredExceptionHandler)異常處理,也就是向量化異常處理。我們之所以可以使用VEH異常來進行HOOK的主要原因,在于兩點。其一,VEH異常處理的優(yōu)先級是高于SEH異常處理的,也就是說可以先手拿到異常,確保不會被其他異常處理流程將異常截獲而導致HOOK失敗。其二就是在VEH異常處理的回調(diào)函數(shù)中,可以獲取及修改異常發(fā)生處的上下文環(huán)境,這就意味著我們可以操作的東西會非常多,例如通過上下文環(huán)境中的ESP(棧頂指針寄存器)就可以拿到HOOK位置觸發(fā)異常時的堆棧數(shù)據(jù)。而我們設置的HOOK位置通常位于函數(shù)內(nèi)部的起始位置,這就意味著我們可以直接通過堆棧里的數(shù)據(jù)獲取到被HOOK函數(shù)的參數(shù),并且可以對其進行修改。
在我們之前的文章中,我們已經(jīng)使用過利用軟件斷點(int 3 0xCC)觸發(fā)異常,實現(xiàn)HOOK。
但是這種方法也是有一定缺陷的。例如,如果目標進程具有CRC32一類的完整性檢查,int3 軟件斷點又會修改指令。這樣就無法通過完整性檢查了。所以,我們這一次,提出一種新的方式。依然是基于VEH異常的,但是可以實現(xiàn)“無痕”的效果。不修改任何一個字節(jié)就完成HOOK。那么,這種方式就是基于硬件調(diào)試寄存器實現(xiàn)的。也就是硬件斷點。因為硬件斷點的地址是存儲在寄存器里的,所以不會修改內(nèi)存。
那么在學習具體的HOOK方法之前,我們首先需要了解一下硬件斷點的基本知識:

上圖就是Intel手冊中對于調(diào)試斷點的說明圖,下面我們對其字段進行一定解釋:
DR0 - DR3就是用來保存硬件斷點的地址的,這個地址是線性地址而不是物理地址,因為CPU是在線性地址被翻譯成物理地址之前出處理斷點的,也因此,我們在保護模式內(nèi)不能用調(diào)試寄存器對物理內(nèi)存地址設置斷點。
DR4和DR5是保留的,如果調(diào)試擴展開啟了(CR4的DE位設置成1就是開啟了),任何對DR4和DR5的調(diào)用都會導致一個非法指令異常#UD,如果調(diào)試擴展禁用了,那么DR4和DR5其實就是DR6和DR7的別名寄存器。
DR7寄存器是調(diào)試控制寄存器:
R/W0 - R/W3?讀寫域 四個讀寫域分別與DR0-DR3寄存器所對應,用來指定被監(jiān)控地點的訪問類型。
占兩位,所以有以下四種狀態(tài):
00:僅執(zhí)行對應斷點的時候中斷(執(zhí)行斷點)
01:僅寫數(shù)據(jù)中斷(寫入斷點)
10:(需要開啟CR4的DE【調(diào)試擴展】)I/O時中斷
11:讀寫數(shù)據(jù)都中斷,但是讀指令除外(訪問斷點)
LEN0 - LEN3?長度域 四個長度域分別與DR0-DR3寄存器所對應,用來指定監(jiān)控區(qū)域的長度
占兩位,所以有以下四種狀態(tài):
00:1字節(jié)長
01:2字節(jié)長
10:8字節(jié)長
11:4字節(jié)長
如果R/W位是00,那么這里應該設置成0
L0-L3?局部斷點啟用 分別與DR0-DR3寄存器所對應,對應項為1就是開啟斷點,為0就是關閉斷點,執(zhí)行后自動清除該位
G0-G3?全部斷點啟用 分別與DR0-DR3寄存器所對應,對應項為1就是開啟斷點,為0就是關閉斷點,CPU不會主動清除
LE和GE 忽略即可,高版本CPU不用了,486之前才會用
GD啟用訪問檢測,如果GD是1,那么CPU遇到修改DR寄存器的指令,會產(chǎn)生一條異常。
DR6寄存器是調(diào)試狀態(tài)寄存器
B0-B3?分別與DR0-DR3寄存器所對應,如果B0被置1了,那說明R/W0 len0 DR0的條件都被滿足了
BD?與DR7的GD位相關聯(lián),當CPU發(fā)現(xiàn)了需要修改DR寄存器的指令,那么就會停止執(zhí)行,把BD設置成1,然后交給#DB的處理程序
BS?單步 與EFLAGS里的TF位相關聯(lián),如果這一位是1,則表示是單步觸發(fā)的
BT?任務切換 與任務段相關,TSS的T標志(調(diào)試陷阱)相關聯(lián),當任務切換,發(fā)現(xiàn)下一個TSS的T是1,那么就會中斷到調(diào)試中斷程序里
那么以MessageBoxA為例,我們實際上來體驗一下無痕HOOK的實現(xiàn)方式。
首先,我們需要一個目標程序,代碼如下:

然后我們來看一下HOOK后的效果:
正常情況下:

HOOK后:

?
接下來,我們將使用代碼實現(xiàn)IAT Hook,我這里采用的操作系統(tǒng)是Windows 10 20H2(19042.1288),集成開發(fā)環(huán)境采用的是Visual Studio 2017。
閱讀全文
??公眾號:極安御信安全研究院(即可獲得文章全部內(nèi)容)