首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

Windows 驅動開發:Hook SSDT NtCreateSection 實現進程啟動監控與攔截

     編輯:VC 教學

本文展示一個核心模式驅動 (Kernel Mode Driver) 範例,透過修改 SSDT (System Service Descriptor Table) 將 NtCreateSection 重導向至自定義 Proxy 函數,檢測映射映像檔 (SEC_IMAGE) 行為以判斷進程即將啟動,並依使用者策略決定允許或拒絕 (STATUS_ACCESS_DENIED),實現類防毒軟體的進程攔截功能。

核心原理

  1. NtCreateSection 參數 SectionPageProtection 含 SEC_IMAGE (0x01000000) 且 AllocationAttributes 為 0 時,表示映射可執行映像 (EXE/DLL)。
  2. 透過 FileHandle 取得 FILE_OBJECT,進而獲取完整路徑,判斷副檔名是否為 .exe。
  3. 同步等待使用者模式決策 (事件機制),允許則跳轉原 NtCreateSection,拒絕則返回 0xC0000022。

關鍵驅動代碼節選

1. SSDT Hook 安裝 (IRP_MJ_DEVICE_CONTROL 處理)

// 用戶模式傳入目標服務索引 (從 ntdll.dll 的 MOV EAX, Index 取得)
if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_HOOK_SSDT) {
    UCHAR* buf = (UCHAR*)Irp->AssociatedIrp.SystemBuffer;
    ULONG index; RtlCopyMemory(&index, buf, 4); // 取得索引

    ULONG* pServiceTable = (ULONG*)KeServiceDescriptorTable->ServiceTableBase;
    ULONG targetAddr = pServiceTable[index];

    // 映射物理記憶體以繞過寫保護 (MmMapIoSpace)
    ULONG* pMapped = (ULONG*)MmMapIoSpace(MmGetPhysicalAddress((PVOID)targetAddr), 4, MmNonCached);
    
    _asm {
        mov eax, pMapped
        mov ebx, [eax]           // 保存原函數地址
        mov RealCallee, ebx
        mov ebx, Proxy           // 我們的 Hook 函數
        mov [eax], ebx           // 覆寫 SSDT 項
    }
    // ... 映射輸出緩衝區供用戶模式寫入決策 ...
}

2. Hook 處理函數 check() (判斷邏輯)

ULONG __stdcall check(PULONG args) {
    // args 為 NtCreateSection 參數陣列
    if ((args[4] & 0xF0) == 0) return 1;           // AllocationAttributes 檢查
    if ((args[5] & 0x01000000) == 0) return 1;     // SectionPageProtection 無 SEC_IMAGE

    HANDLE hFile = (HANDLE)args[6];                 // FileHandle
    PFILE_OBJECT pFileObj;
    ObReferenceObjectByHandle(hFile, 0, NULL, KernelMode, (PVOID*)&pFileObj, NULL);
    if (!pFileObj) return 1;

    // 轉 ANSI 路徑
    ANSI_STRING aStr; RtlUnicodeStringToAnsiString(&aStr, &pFileObj->FileName, TRUE);
    ObDereferenceObject(pFileObj);

    // 簡易判斷 .exe 副檔名
    char* p = aStr.Buffer + aStr.Length - 1;
    while (p > aStr.Buffer && *p != '.') p--;
    if (_stricmp(p, ".exe") != 0) { RtlFreeAnsiString(&aStr); return 1; }

    // 通知用戶模式決策 (共享緩衝區 output)
    strcpy(&output[8], aStr.Buffer); // 傳遞路徑
    RtlFreeAnsiString(&aStr);

    output[0] = 1; // 等待標誌
    KeWaitForSingleObject(&gEvent, Executive, KernelMode, FALSE, NULL); // 等待用戶回應

    ULONG decision; RtlCopyMemory(&decision, &output[4], 4); // 讀取用戶決定
    KeSetEvent(&gEvent, 0, FALSE);
    return decision; // 1=允許, 0=拒絕
}

3. 裸函數 Proxy (保存上下文、調用 check、決定跳轉)

__declspec(naked) void Proxy() {
    _asm {
        pushfd; pushad               // 保存所有暫存器/旗標
        mov ebx, esp; add ebx, 40    // 計算參數堆疊位址
        push ebx; call check         // 調用 C 函數 check(args)
        cmp eax, 1
        jne BlockExecution

        // 允許:恢復上下文,跳轉原函數
        popad; popfd; jmp RealCallee

    BlockExecution:
        // 拒絕:恢復上下文,返回 STATUS_ACCESS_DENIED
        popad
        mov ebx, [esp+8]             // 取得返回地址位置
        mov dword ptr [ebx], 0       // 清零返回值 (NTSTATUS 在 eax)
        mov eax, 0xC0000022L         // STATUS_ACCESS_DENIED
        popfd; ret 32                // 返回 8 參數 * 4 bytes
    }
}

用戶模式決策執行緒

DWORD WINAPI DecisionThread(LPVOID) {
    while (TRUE) {
        if (output[0] == 1) { // 驅動請求決策
            char* path = &output[8];
            BOOL allow = FALSE;
            // 檢查白名單...
            if (!InWhiteList(path)) {
                CString msg; msg.Format(_T("允許執行 %s ?"), path);
                allow = (IDYES == MessageBox(NULL, msg, _T("警告"), MB_YESNO|MB_ICONQUESTION|MB_TOPMOST));
                if (allow) AddToWhiteList(path);
            } else allow = TRUE;

            output[4] = allow; // 寫入決策
            output[0] = 0;     // 通知驅動可讀取
        }
        Sleep(50);
    }
    return 0;
}

關鍵技術點與風險提示

  • SSDT Hook 屬非文檔化、不穩定技術,Windows 版本升級 (尤其是 PatchGuard x64) 會導致藍屏或失效。現代方案請用 Mini-filter 驅動、ETW、Windows Defender API、AppLocker。
  • MmMapIoSpace 繞過寫保護僅適用於無 PatchGuard 環境 (x86 或關閉測試模式 x64)。
  • 核心模式同步等待用戶模式 (KeWaitForSingleObject) 極易造成系統卡死,生產環境必須設計超時機制與非同步決策。
  • 驅動簽名強制 (Win10+)、安全啟動、HVCI (VBS) 將徹底阻止此類非簽名/測試簽名驅動載入。

本代碼僅供教學研究理解 SSDT 機制與進程創建流程,請勿用於生產環境。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved