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

WSOCK32.DLL 攔截與 Hook 技術實戰:函數指標表重導向完整原始碼解析

     編輯:關於C語言

Hook 原理:DLL 導入表重寫 / 函數指標表替換

本範例展示使用者模式 Hook核心技術:建立一個同名 WSOCK32.DLL (或透過 AppInit_DLLs、KnownDLLs、IAT Hook 注入),在 DllMain 中:

  1. 載入真正的 WSOCK32.DLL (LoadLibrary)。
  2. 取得所有導出函數真實位址 (GetProcAddress) 存入函數指標陣列。
  3. 導出同名函數,內部:記錄日誌 → 呼叫真實函數 → 返回結果。

完整原始碼結構解析

1. 全域變數與函數指標宣告


#include 
#include 

void abc(char *p) { FILE *fp=fopen("c:\\z.txt","a+"); fprintf(fp,"%s",p); fclose(fp); } // 日誌函數

HMODULE g_hRealWsock32 = NULL; // 真實 WSOCK32 模組句柄

// 為每個導出函數宣告函數指標型別與變數
int (__stdcall *p_accept)(SOCKET, struct sockaddr*, int*);
int (__stdcall *p_bind)(SOCKET, const struct sockaddr*, int);
// ... 共 40+ 個函數指標 (見下表)

2. 核心導出函數範本


// 範例:accept Hook
int __stdcall accept(SOCKET s, struct sockaddr* addr, int* addrlen)
{
    abc("accept called\n"); // 記錄
    if (p_accept) return p_accept(s, addr, addrlen); // 呼叫真實函數
    return SOCKET_ERROR;
}

// 範例:send Hook (可檢查/修改資料)
int __stdcall send(SOCKET s, const char* buf, int len, int flags)
{
    char log[256];
    sprintf_s(log, "send: socket=%u, len=%d, data=%.50s\n", s, len, buf);
    abc(log);
    return p_send ? p_send(s, buf, len, flags) : SOCKET_ERROR;
}

3. DllMain 初始化邏輯


BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason, LPVOID lpReserved)
{
    if (ul_reason == DLL_PROCESS_ATTACH) {
        DisableThreadLibraryCalls(hModule);
        // 1. 載入真實 WSOCK32 (系統目錄)
        char sysPath[MAX_PATH];
        GetSystemDirectoryA(sysPath, MAX_PATH);
        strcat_s(sysPath, "\\wsock32.dll");
        g_hRealWsock32 = LoadLibraryA(sysPath);
        if (!g_hRealWsock32) return FALSE;

        // 2. 解析所有導出函數位址
        p_accept = (decltype(p_accept))GetProcAddress(g_hRealWsock32, "accept");
        p_bind = (decltype(p_bind))GetProcAddress(g_hRealWsock32, "bind");
        // ... 逐一解析 40+ 函數
    }
    else if (ul_reason == DLL_PROCESS_DETACH) {
        if (g_hRealWsock32) FreeLibrary(g_hRealWsock32);
    }
    return TRUE;
}

完整函數指標對照表 (節選)

函數名指標型別宣告用途
acceptint (__stdcall*)(SOCKET, sockaddr*, int*)接受連線
bindint (__stdcall*)(SOCKET, const sockaddr*, int)綁定地址
closesocketint (__stdcall*)(SOCKET)關閉 Socket
connectint (__stdcall*)(SOCKET, const sockaddr*, int)發起連線
gethostbynamehostent*(__stdcall*)(const char*)DNS 解析
getpeernameint (__stdcall*)(SOCKET, sockaddr*, int*)取得對端地址
getsocknameint (__stdcall*)(SOCKET, sockaddr*, int*)取得本端地址
getsockoptint (__stdcall*)(SOCKET, int, int, char*, int*)取選項
htonl / htonsu_long(__stdcall*)(u_long) / u_short(__stdcall*)(u_short)位序轉換
inet_addru_long(__stdcall*)(const char*)字串轉 IP
inet_ntoachar*(__stdcall*)(in_addr)IP 轉字串
ioctlsocketint (__stdcall*)(SOCKET, long, u_long*)I/O 控制
listenint (__stdcall*)(SOCKET, int)監聽
recv / recvfromint (__stdcall*)(SOCKET, char*, int, int)接收資料
selectint (__stdcall*)(int, fd_set*, fd_set*, fd_set*, timeval*)多工等待
send / sendtoint (__stdcall*)(SOCKET, const char*, int, int)發送資料
setsockoptint (__stdcall*)(SOCKET, int, int, const char*, int)設選項
shutdownint (__stdcall*)(SOCKET, int)關閉半連線
socketSOCKET(__stdcall*)(int, int, int)建立 Socket
WSAStartup / WSACleanupint(__stdcall*)(WORD, LPWSADATA) / int(__stdcall*)()啟動/清理
WSAGetLastErrorint(__stdcall*)()取錯誤碼
WSAAsyncSelectint(__stdcall*)(SOCKET, HWND, u_int, long)視窗異步
WSAAsyncGetHostByNameHANDLE(__stdcall*)(HWND, u_int, const char*, char*, int)非同步 DNS

進階 Hook 技術對比

技術原理優點缺點適用場景
IAT Hook (Import Address Table)修改目標模組導入表函數指標精準針對單一模組、無需系統級注入僅影響靜態導入、延遲載入需額外處理應用程式插件、熱修補
Inline Hook (Code Cave / JMP)修改目標函數前幾字節跳轉影響所有呼叫者、無視導入方式需處理指令長度、反病毒敏感、x64 相對跳轉複雜系統級監控、安全產品
DLL Proxy / Forwarder同名 DLL 插入搜尋路徑簡單、無需修改目標需控制載入順序、KnownDLLs 保護舊版相容、測試工具
Detours / MinHook 庫封裝 Inline Hook、支援 x86/x64成熟、處理指令解碼、事務提交引入第三方依賴生產級 Hook 開發

安全與相容性警示

  • KnownDLLs 機制:Windows 將 wsock32.dll 列入 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs,系統載入器會強制從 System32 載入,同名 DLL 放在應用目錄不會生效。需用 IAT Hook 或 AppInit_DLLs (需註冊表權限、影響全系統)。
  • x64 系統:wsock32.dll 為 32-bit 兼容層,64-bit 程式直接使用 ws2_32.dll。Hook 需分別處理。
  • 簽名驅動/保護進程:受保護進程 (PPL)、HVCI 環境下用戶模式 Hook 會被阻擋。
  • 多執行緒安全:初始化階段需鎖定,函數指標寫入需 InterlockedExchangePointer。

現代替代方案

  • Windows Filtering Platform (WFP):核心層網路過濾/記錄,官方支援、效能高、無 Hook 風險。
  • ETW (Event Tracing for Windows):Microsoft-Windows-Winsock 提供者,零侵入式追蹤 Socket 操作。
  • Detours / MinHook:若必須 Hook,使用成熟庫而非手寫組裝指令。

總結

本範例展示經典的 DLL Proxy Hook 技術:透過函數指標表轉發實現 WSOCK32.DLL 全函數攔截。理解其初始化流程、函數指標型別對應、轉發邏輯、KnownDLLs 限制、現代替代方案,能幫助您在除錯、監控、安全分析等場景選擇最適合的技術路徑。

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