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

VC++ 實作 MSN Messenger Hook 程式:DLL 注入與 WH_MOUSE 鉤子實戰

     編輯:VC 教學

前言:為什麼要 Hook MSN?

研究如何攔截其他應用程式訊息,最直觀的練習目標就是常用的 MSN Messenger。雖無實際商業價值,但能完整體驗DLL 注入、全域鉤子、跨程序記憶體操作的核心流程。本文記錄完整實作過程。

核心原理:DLL 注入與 Hook 機制

兩個進程擁有獨立位址空間,無法直接存取彼此記憶體。SetWindowsHookEx 配合 DLL 實現注入:

  1. 應用程式呼叫 SetWindowsHookEx(WH_MOUSE, GetMsgProc, hDll, dwThreadId)。
  2. 系統將指定 DLL 載入目標執行緒所屬程序空間。
  3. 目標程序內的滑鼠訊息觸發 GetMsgProc 回呼(在目標程序記憶體中執行)。
  4. 回呼函數可存取目標程序視窗、控件、記憶體。

Hook DLL 實作 (MSNHook.h / MSNHook.cpp)

共享資料段:跨程序傳遞資料

#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 入口點與匯出函數

HINSTANCE g_hinstDll = NULL;

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

// 安裝鉤子
__declspec(dllexport) BOOL WINAPI SetMsnHook(DWORD dwThreadId)
{
    if (dwThreadId == 0) return FALSE;
    g_dwThreadIdMsn = GetCurrentThreadId();
    g_hhook = SetWindowsHookEx(WH_MOUSE, GetMsgProc, g_hinstDll, dwThreadId);
    if (g_hhook) PostThreadMessage(dwThreadId, WM_NULL, 0, 0);  // 激活訊息泵
    return (g_hhook != NULL);
}

// 移除鉤子
__declspec(dllexport) BOOL WINAPI UnsetMsnHook()
{
    if (g_hhook) return UnhookWindowsHookEx(g_hhook);
    return FALSE;
}

// 鉤子處理函數
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);
            g_Hwnd = hWnd;
            // 示範:將文字改為固定內容
            SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM)"Hooked!");
        }
    }
    return CallNextHookEx(g_hhook, nCode, wParam, lParam);
}

// 供 EXE 讀取共享資料
__declspec(dllexport) void WINAPI GetText(int& x, int& y, char** ptext)
{
    x = g_MouseLoc.x; y = g_MouseLoc.y; *ptext = g_text;
}
__declspec(dllexport) HWND WINAPI GetMyHwnd() { return g_Hwnd; }

EXE 控制程式實作

#include "MSNHook.h"
#pragma comment(lib, "MSNHook.lib")

// 對話框成員
CEdit m_Edit;
CButton m_btnStart, m_btnStop;

void CTestMSNHookDlg::OnBnClickedStart()
{
    // 透過 Spy++ 取得 MSN 聊天視窗類別名
    CWnd* pMsnWin = FindWindow(_T("IMWindowClass"), NULL);
    if (!pMsnWin) { AfxMessageBox(_T("找不到 MSN 視窗")); return; }

    DWORD dwThreadId = GetWindowThreadProcessId(pMsnWin->GetSafeHwnd(), NULL);
    if (SetMsnHook(dwThreadId)) {
        SetTimer(101, 100, NULL);  // 定時輪詢共享資料
        m_btnStart.EnableWindow(FALSE);
        m_btnStop.EnableWindow(TRUE);
    } else {
        AfxMessageBox(_T("Hook 安裝失敗"));
    }
}

void CTestMSNHookDlg::OnTimer(UINT_PTR nIDEvent)
{
    if (nIDEvent == 101) {
        char* pText = NULL;
        int x = 0, y = 0;
        GetText(x, y, &pText);
        if (x || y) {
            CString str;
            str.Format(_T("滑鼠位置: %d, %d\n文字: %s"), x, y, pText);
            m_Edit.SetWindowText(str);
        }
        HWND hWnd = GetMyHwnd();
        if (hWnd) {
            CWnd* pWnd = CWnd::FromHandle(hWnd);
            CString wndText;
            pWnd->GetWindowText(wndText);
            // 可顯示視窗標題等資訊
        }
    }
    CDialog::OnTimer(nIDEvent);
}

void CTestMSNHookDlg::OnBnClickedStop()
{
    KillTimer(101);
    UnsetMsnHook();
    m_btnStart.EnableWindow(TRUE);
    m_btnStop.EnableWindow(FALSE);
}

關鍵技術點總結

技術點說明
WH_MOUSE攔截滑鼠訊息,MOUSEHOOKSTRUCT 含座標與視窗句柄
共享資料段#pragma data_seg + /section:Shared,rws 實現跨程序變數共享
隱式連結 DLL__declspec(dllimport) + #pragma comment(lib) 簡化呼叫
PostThreadMessage(WM_NULL)確保目標執行緒有訊息泵,讓 Hook 生效
WindowFromPoint從螢標座標取得視窗句柄,進而 WM_GETTEXT 取得文字

遺留問題與延伸

作者嘗試用 WM_GETTEXT 取得 MSN 聊天輸入框文字但失敗,推測 MSN 使用自繪控件或內部儲存機制不同。後續可嘗試:

  • Hook WM_CHAR/WM_KEYDOWN 攔截鍵盤輸入。
  • 使用 UI Automation / MSAA 存取控件文字。
  • 記憶體掃描定位聊天緩衝區(需逆向分析)。

結語

本範例展示了最經典的「DLL 注入 + 全域鉤子」技術棧,是理解 Windows 進程間攔截機制的最佳入門專案。實務應用中請遵守法律法規與用戶隱私,僅用於合法除錯、測試、輔助工具開發。

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