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

Windows Hook技術實戰:DLL注入攔截MSN Messenger訊息完整教學

     編輯:關於C語言

一、核心挑戰:跨進程訊息攔截

目標:從我們的應用程式攔截另一個進程 (MSN Messenger) 的視窗訊息。難點:雙方擁有獨立虛擬位址空間,無法直接修改目標進程的視窗程序。

解法:**Windows Hook + DLL注入**。Hook機制允許將自訂DLL注入目標進程位址空間,在該進程上下文中執行攔截邏輯。

二、Hook DLL實作 (MSNHook.dll)

共享資料區 (關鍵:跨進程資料同步)


#pragma data_seg("Shared")  // 命名共享區段
HHOOK g_hhook = NULL;
DWORD g_dwThreadIdMsn = 0;
POINT g_MouseLoc = {0,0};
char g_text[256] = {0};
HWND g_Hwnd = NULL;
#pragma data_seg()

#pragma comment(linker, "/section:Shared,rws")  // 告訴連結器:可讀寫共享

所有注入進程的DLL實例映射到同一塊物理記憶體,實現跨進程全域變數共享。

DLL進入點與Hook安裝


HINSTANCE g_hinstDll = NULL;

BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason, LPVOID) {
    if (ul_reason == DLL_PROCESS_ATTACH) g_hinstDll = (HINSTANCE)hModule;
    return TRUE;
}

LRESULT WINAPI GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam);  // 前置宣告

BOOL WINAPI SetMsnHook(DWORD dwThreadId) {
    if (dwThreadId == 0) return FALSE;
    g_dwThreadIdMsn = GetCurrentThreadId();  // 記錄註入者執行緒ID

    // 安裝WH_MOUSE Hook,攔截滑鼠訊息
    g_hhook = SetWindowsHookEx(WH_MOUSE, GetMsgProc, g_hinstDll, dwThreadId);
    if (!g_hhook) return FALSE;

    // 發送空訊息確保Hook鏈啟動
    return PostThreadMessage(dwThreadId, WM_NULL, 0, 0);
}

Hook處理函數:攔截滑鼠並竄改視窗文字


LRESULT WINAPI GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam) {
    if (nCode == HC_ACTION) {
        MOUSEHOOKSTRUCT* pMouse = (MOUSEHOOKSTRUCT*)lParam;
        g_MouseLoc = pMouse->pt;  // 記錄滑鼠位置

        // 取得滑鼠下的視窗控制代碼
        HWND hWnd = WindowFromPoint(pMouse->pt);
        if (hWnd) {
            // 取得視窗文字
            SendMessage(hWnd, WM_GETTEXT, 256, (LPARAM)g_text);
            // 竄改視窗文字 (示範用)
            SendMessage(hWnd, WM_SETTEXT, 256, (LPARAM)g_text);
            g_Hwnd = hWnd;
        }
    }
    return CallNextHookEx(g_hhook, nCode, wParam, lParam);  // 必須傳遞給下一個Hook
}

導出函數供主程式呼叫


void WINAPI GetText(int& x, int& y, char** ptext) {
    x = g_MouseLoc.x; y = g_MouseLoc.y; *ptext = g_text;
}
HWND WINAPI GetMyHwnd() { return g_Hwnd; }

三、主程式 (注入啟動器)

隱式連結DLL


#include "MSNHook.h"
#pragma comment(lib, "MSNHook.lib")  // 連結導入庫

__declspec(dllimport) BOOL WINAPI SetMsnHook(DWORD);
__declspec(dllimport) void WINAPI GetText(int&, int&, char**);
__declspec(dllimport) HWND WINAPI GetMyHwnd();

尋找MSN視窗並安裝Hook


void CTestMSNHookDlg::OnBnClickedOk() {
    // Spy++可見MSN聊天視窗類別為 "IMWindowClass"
    CWnd* pMsnWin = FindWindow(_T("IMWindowClass"), NULL);
    if (!pMsnWin) return;

    // 取得該視窗所屬執行緒ID
    DWORD dwThreadId = GetWindowThreadProcessId(pMsnWin->GetSafeHwnd(), NULL);
    
    // 安裝Hook (此時DLL注入MSN進程)
    SetMsnHook(dwThreadId);
    
    MSG msg; GetMessage(&msg, NULL, 0, 0);  // 訊息迴路保持Hook存活
    SetTimer(101, 100, NULL);  // 定時器輪詢共享資料
}

void CTestMSNHookDlg::OnTimer(UINT_PTR) {
    char* pText = NULL; int x=0, y=0;
    GetText(x, y, &pText);
    if (x==0 && y==0) return;
    
    CString str; str.Format(_T("%d:%d:%s"), x, y, pText);
    m_Edit = str; UpdateData(FALSE);
    
    // 同步顯示視窗文字
    HWND hWnd = GetMyHwnd();
    if (hWnd) {
        CWnd* pWnd = CWnd::FromHandle(hWnd);
        pWnd->GetWindowText(m_Edit);
    }
}

void CTestMSNHookDlg::OnBnClickedButton1() {  // 停止
    KillTimer(101);
    SetMsnHook(0);  // 協助DLL卸載
    OnCancel();
}

四、關鍵技術點總結

技術點說明
WH_MOUSE攔截滑鼠訊息 (移動、按下、釋放、雙擊等)
SetWindowsHookEx參數:Hook類型、處理函數、DLL實例、目標執行緒ID (0=全系統)
共享資料區#pragma data_seg + linker /section:rws 實現跨進程全域變數
CallNextHookEx**必須呼叫**,維持Hook鏈完整性,否則系統不穩定
DLL_PROCESS_ATTACH每個被注入進程皆會觸發,初始化g_hinstDll
PostThreadMessage(WM_NULL)喚醒目標執行緒訊息迴路,確保Hook生效

五、已知限制與延伸

  • 範例僅示範滑鼠Hook與視窗文字竄改,**無法直接攔截MSN聊天輸入框文字** (WM_GETTEXT取不到RichEdit內容)
  • 進階方向:WH_GETMESSAGE攔截所有訊息、WH_CALLWNDPROC監控視窗程序呼叫、結合UI Automation/API Hooking取得編輯控制項內容
  • 64位元系統需編譯64位元DLL注入64位元進程

總結

Windows Hook + DLL注入是跨進程訊息攔截的經典技術。核心在於:共享資料區實現跨進程通訊、SetWindowsHookEx將DLL注入目標執行緒、Hook處理函數在目標進程上下文執行。範例雖簡單,但完整展示了從DLL建立、共享記憶體設計、Hook安裝/卸載到主程式協調的完整生命週期。

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