Windows 平台偵錯器三大類:
偵錯器本質是一個**事件處理迴圈**:
// 偽代碼:標準偵錯器主迴圈
DEBUG_EVENT de;
BOOL bContinue = TRUE;
DWORD dwContinueStatus = DBG_CONTINUE;
// 1. 啟動或附著進程
CreateProcess(..., DEBUG_PROCESS, ...) // 啟動新進程
// 或
DebugActiveProcess(dwProcessId); // 附著現有進程
// 2. 事件迴圈
while (bContinue) {
bContinue = WaitForDebugEvent(&de, INFINITE); // 等待偵錯事件
if (!bContinue) break;
// 3. 依事件類型分派處理
switch (de.dwDebugEventCode) {
case EXCEPTION_DEBUG_EVENT: HandleException(de); break;
case CREATE_THREAD_DEBUG_EVENT: HandleCreateThread(de); break;
case EXIT_THREAD_DEBUG_EVENT: HandleExitThread(de); break;
case CREATE_PROCESS_DEBUG_EVENT: HandleCreateProcess(de); break;
case EXIT_PROCESS_DEBUG_EVENT: HandleExitProcess(de); break;
case LOAD_DLL_DEBUG_EVENT: HandleLoadDll(de); break;
case UNLOAD_DLL_DEBUG_EVENT: HandleUnloadDll(de); break;
case OUTPUT_DEBUG_STRING_EVENT: HandleOutputDebugString(de); break;
case RIP_EVENT: HandleRipEvent(de); break;
default:
dwContinueStatus = DBG_CONTINUE;
}
// 4. 讓被偵錯進程繼續執行
ContinueDebugEvent(de.dwProcessId, de.dwThreadId, dwContinueStatus);
}
CreateProcess 帶 `DEBUG_PROCESS` / `DEBUG_ONLY_THIS_PROCESS` → `NtCreateProcessEx` → `PspCreateProcess` 在 `EPROCESS->DebugPort` 存入 **LPC 埠物件**。DebugActiveProcess → `DbgUiConnectToDbg` 連接系統偵錯子系統埠 `\DbgUiApiPort` → `DbgUiDebugActiveProcess` 激活目標進程偵錯埠。| API | 實現原理 | 繞過難度 |
|---|---|---|
| IsDebuggerPresent() | 讀取 `PEB->BeingDebugged` 旗標 (由 CreateProcessInternalW 設定) | 極低:偵錯器可直接修改 PEB 記憶體 |
| CheckRemoteDebuggerPresent() | `NtQueryInformationProcess(hProcess, ProcessDebugPort(7), &hPort, ...)` 檢查 `EPROCESS->DebugPort` 是否非 NULL | 中:需 Hook NtQueryInformationProcess 或隱藏 DebugPort |
| NtGlobalFlag | PEB->NtGlobalFlag 檢查 `FLG_HEAP_ENABLE_TAIL_CHECK (0x10)` 等堆積偵錯旗標 | 中高:需修改 PEB 或修補核心旗標 |
| 硬體斷點檢測 | 讀取 `DR0-DR3, DR6, DR7` 暫存器 | 高:偵錯器本身使用硬體斷點,難完美隱藏 |
| 時序檢測 (RDTSC) | 測量關鍵路徑執行時間,偵錯器單步會導致顯著延遲 | 高:需虛擬化時鐘或硬體加速 |
NTSTATUS DbgUiConnectToDbg() {
// 連接核心偵錯子系統埠
NTSTATUS st = NtConnectPort(&DbgUiApiPort, L"\\DbgUiApiPort", ..., &DbgStateChangeSemaphore);
if (NT_SUCCESS(st)) {
// 註冊執行緒終止埠,確保執行緒結束前通知偵錯器
NtRegisterThreadTerminatePort(DbgUiApiPort);
}
return st;
}
DbgUiDebugActiveProcess(hProcess) {
// 1. NtDebugActiveProcess(DbgUiApiPort) - 請求核心建立偵錯關係
// 2. DbgUiIssueRemoteBreakin(hProcess) - 向目標進程注入 DEBUG_BREAKPOINT (INT 3)
// 3. DbgUiStopDebugging(hProcess) - 完成附著手續
}
Win32 使用者模式偵錯器建立在**核心偵錯子系統**與 **LPC 埠通訊**之上,核心邏輯是**事件等待 → 分派處理 → 繼續執行**的迴圈。深入理解 `EPROCESS->DebugPort`、PEB 旗標、`DbgUi*` 內部流程,不僅能編寫功能完整的偵錯器,更能洞悉反偵錯對抗的本質。現代偵錯器開發建議基於 WinDbg 擴充模型或 DBGENG API,站在巨人肩膀上構建領域專用診斷工具。