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

Windows Hook 技術實戰:打造程式執行監視與封鎖系統

     編輯:關於C++

專案概覽:系統級程式行為監控器

本專案展示如何利用 Windows 全域 Hook 機制,構建一套常駐後台的程式執行審計與封鎖系統。核心功能包含:

  • 全程記錄: 記錄系統啟動/關機、所有視窗程式的建立與關閉時間、視窗類別名與標題。
  • 黑名單封鎖: 依視窗類別名或標題比對設定檔,自動關閉禁止執行的程式 (如遊戲)。
  • 隱蔽常駐: 透過登機啟動項註冊、工具視窗樣式隱藏工作列圖示、單一執行個體鎖定、共享記憶體跨進程通訊。

核心架構三支柱

1. WH_SHELL Hook:監控視窗生命週期

SetWindowsHookEx(WH_SHELL, ...) 安裝全域 Shell Hook。當任何進程建立或銷毀主視窗 (Top-level Window) 時,系統會呼叫 Hook 回呼函式 HookedShellProc,傳遞 HSHELL_WINDOWCREATED / HSHELL_WINDOWDESTROYED 通知碼及視窗句柄 (wParam)。

這正是 Windows 工作列「按鈕」更新的底層機制——我們攔截它,即可實現自訂的視窗歷史記錄或干預。

2. DLL 承載 Hook 程序:跨進程注入的必要條件

全域 Hook 回呼函式**必須**位於 DLL 中,因為系統需將該 DLL 注入所有目標進程的位址空間執行。EXE 無法被其他進程載入。本專案結構:

  • hwhpdrv.dll:包含 Hook 回呼、共享資料結構定義、安裝/移除 Hook 匯出函式。
  • hwhpapp.exe:主控程式,負責 UI、日誌寫入、黑名單比對、載入 DLL 並觸發安裝 Hook。

3. 共享記憶體:打破進程隔離牆

Hook 回呼執行於**目標進程**內容中,無法存取主程式 (EXE) 的全域變數。解決方案:CreateFileMapping(INVALID_HANDLE_VALUE, ...) 建立「具名共享記憶體」,映射至所有進程虛擬位址空間同一邏輯位址。專案採用 Victor VCL 元件庫的 TSharedMemory 封裝,共享結構包含:

  • Hook 句柄 (hHook):供 CallNextHookEx 使用。
  • 主視窗句柄 (hMainForm):Hook 透過 PostMessage 將事件轉發給主程式處理 (寫日誌、比對黑名單)。
  • 其他擴充欄位...

關鍵技術實作細節

單一執行個體保護

啟動極早期 (WinMain 入口) 檢查共享記憶體是否已存在:

if (AppMem.Exists) { // 已有實例在跑
  if (stricmp(lpCmdLine, "/SHOW") == 0)
    PostMessage(AppMem.AppInfo->hMainForm, WM_USERCMD, UC_SHOWWIN, 0);
  return 0; // 直接退出
}

支援命令列參數 /SHOW 喚醒已隱藏主視窗。

徹底隱身:不出現在工作列與工作管理員

在 Application->Run() 前設定擴充視窗樣式:

SetWindowLong(Application->Handle, GWL_EXSTYLE,
  GetWindowLong(Application->Handle, GWL_EXSTYLE) | WS_EX_TOOLWINDOW);

WS_EX_TOOLWINDOW 讓視窗不顯示在工作列、Alt+Tab 切換清單、甚至工作管理員的「應用程式」分頁中。

日誌與設定檔偽裝

  • 日誌檔:hwhpapp.sys (偽裝系統檔,實為文字)。
  • 黑名單:hwhpapp.cfg (記事本可編輯),格式支援 CLASS=視窗類別名 或 CAPTION=視窗標題。

Hook 回呼與主程式協作流程

  1. DLL HookedShellProc 收到 HSHELL_WINDOWCREATED。
  2. 從共享記憶體讀取主程式視窗句柄 hMainWnd。
  3. PostMessage(hMainWnd, WM_USERCMD, UC_WINHOOK, hNewWnd) 非同步通知主程式。
  4. 主程式 WndProc 接收,呼叫 WinHookMessage:
    - GetWindowText/GetClassName 取得資訊。
    - 格式化時間戳、類別名、標題寫入 .sys 日誌。
    - ValidAppCheck 掃描 .cfg 黑名單,命中則 PostMessage(hwnd, WM_CLOSE, 0, 0) 關閉視窗並記錄「(關閉禁用程式)」。
  5. 回呼最後 CallNextHookEx 傳遞給下一個 Hook。

程式碼精華節錄 (C++ Builder)

DLL 端:Hook 安裝與共享資料初始化

void WINAPI THookedProcs::InitFuncs(void) {
  UninitFuncs();
  hThisHook = SetWindowsHookEx(WH_SHELL, (HOOKPROC)HookedShellProc, HInstance, 0);
  TSharedMemory AppMem(MYAPPMARK, 4096);
  THookSharedData *HookSharedData = (THookSharedData*)(AppMem.AppInfo->Data);
  HookSharedData->hHook = hThisHook; // 關鍵:將 Hook 句柄存入共享區供 CallNextHookEx 使用
}

EXE 端:事件處理與黑名單比對

void __fastcall TFormMain::WinHookMessage(long Param) {
  HWND hWnd = (HWND)Param;
  char szClass[256], szCaption[256];
  GetClassName(hWnd, szClass, 256);
  GetWindowText(hWnd, szCaption, 256);

  AnsiString log = FormatDateTime("yyyy-mm-dd hh:nn:ss ", Now()) +
                   "\"" + szClass + "\" -> \"" + szCaption + "\"";
  if (!ValidAppCheck(hWnd, szClass, szCaption))
    log += " (關閉禁用程式)";
  log += "\r\n";
  TBinFileFuncs::WriteLogFileInfo(TRelPath().Extension("sys").c_str(), log.c_str());
}

bool __fastcall TFormMain::ValidAppCheck(HWND hwnd, char *cls, char *cap) {
  // 讀取 .cfg,逐行比對 CLASS= 或 CAPTION=,命中即 PostMessage(WM_CLOSE) 並回傳 false
}

部署與檔案清單

檔案說明
hwhpapp.exe主程式,需放入啟動項 HKLM\...\Run
hwhpdrv.dllHook DLL,與 EXE 同目錄
hwhpapp.cfg黑名單設定,文字編輯即可
hwhpapp.sys自動產生日誌,記事本可讀

安全性與倫理提醒

此技術屬系統級監控,具備攔截、記錄所有視窗程式的能力。開發類似工具時,請嚴格遵守:

  • 僅用於合法授權環境 (企業資產管理、家長控制、個人效率分析)。
  • 日誌檔加密保護,防止隱私洩露。
  • 提供使用者知情權與退出機制 (本範例支援 /SHOW 顯示介面關閉)。
  • 惡意軟體常濫用 Hook + 隱身技術,**切勿用於非法監控或竊取資料**。

延伸應用方向

  • 整合 WH_KEYBOARD_LL/WH_MOUSE_LL 實現鍵盤/滑鼠記錄器 (需簽署驅動程式或 UAC 提權)。
  • 結合 AppInit_DLLs 或驅動程式實現更早期、更難移除的注入。
  • 日誌送往資料庫/雲端,構建集中式稽核平台。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved