注入(4)--訊息鉤子注入(SetWindowsHookEX)
阿新 • • 發佈:2019-01-31
SetWindowsHookEx函式是微軟提供給程式開發人員進行訊息攔截的一個API。不過,他的功能不僅可以用作訊息攔截,還可以進行DLL注入。
SetWindowsHookEx原型宣告如下:
idHook:指示將要安裝的掛鉤處理過程的型別。例如,idHook為“WH_CALLWNDPROC”時代表安裝一個掛鉤處理過程,在系統將訊息傳送至目標視窗處理過程之前對該訊息進行監視。
lpfn:指向相應的掛鉤處理過程。
hmod:指示了一個DLL控制代碼。該DLL包含引數lpfn所指向的掛鉤處理過程
dwThreadId:指示了一個執行緒標示符,掛鉤處理過程與執行緒相關。若此引數值為0,則該掛鉤處理過程與所有現存的執行緒相關。
如果去掉訊息鉤子,可以用UnhookWindowsHookEx函式
SetWindowsHookEx原型宣告如下:
WINUSERAPI
HHOOK
WINAPI
SetWindowsHookExW(
_In_ int idHook,
_In_ HOOKPROC lpfn,
_In_opt_ HINSTANCE hmod,
_In_ DWORD dwThreadId);
idHook:指示將要安裝的掛鉤處理過程的型別。例如,idHook為“WH_CALLWNDPROC”時代表安裝一個掛鉤處理過程,在系統將訊息傳送至目標視窗處理過程之前對該訊息進行監視。
lpfn:指向相應的掛鉤處理過程。
hmod:指示了一個DLL控制代碼。該DLL包含引數lpfn所指向的掛鉤處理過程
dwThreadId:指示了一個執行緒標示符,掛鉤處理過程與執行緒相關。若此引數值為0,則該掛鉤處理過程與所有現存的執行緒相關。
如果去掉訊息鉤子,可以用UnhookWindowsHookEx函式
Windows訊息處理流程:
插入SetWindowsHookEx之後流程:
下面來看程式碼:
// MessageHook.cpp : 定義控制檯應用程式的入口點。 // #include "stdafx.h" #include <Windows.h> #include <Tlhelp32.h> BOOL SetWinHookInject(WCHAR * wzDllPath, WCHAR * wzProcessName); UINT32 GetTargetThreadIdFromProcessName(WCHAR *ProcessName); int main() { WCHAR wzProcessName[0x20] = L"Target.exe"; WCHAR wzDllFullPath[0x20] = L"MessageHookDll.dll"; if (!SetWinHookInject(wzDllFullPath, wzProcessName)) { OutputDebugString(L"Set Hook Unsuccess!\r\n"); return 0; } OutputDebugString(L"Inject Success!\r\n"); return 0; } // //利用Windows API SetWindowsHookEx實現注入DLL // BOOL SetWinHookInject(WCHAR * wzDllPath, WCHAR * wzProcessName) { HMODULE ModuleHandle = NULL; BOOL bOk = FALSE; DWORD FunctionAddress = NULL; UINT32 dwThreadId = 0; HHOOK g_hHook = NULL; PVOID pShareM = NULL; OutputDebugString(L"[+] SetWinHKInject Enter!\n"); ModuleHandle = LoadLibrary(wzDllPath); if (!ModuleHandle) { OutputDebugString(L"[+] LoadLibrary error!\n"); goto Exit; } FunctionAddress = (DWORD)GetProcAddress(ModuleHandle, "MyMessageProc"); if (!FunctionAddress) { OutputDebugString(L"[+] GetProcAddress error!\n"); goto Exit; } dwThreadId = GetTargetThreadIdFromProcessName(wzProcessName); if (!dwThreadId) goto Exit; //設訊息鉤子 g_hHook = SetWindowsHookEx( WH_GETMESSAGE,//WH_KEYBOARD,//WH_CALLWNDPROC, (HOOKPROC)FunctionAddress, ModuleHandle, dwThreadId ); if (!g_hHook) { OutputDebugString(L"[-] SetWindowsHookEx error !\n"); goto Exit; } OutputDebugString(L"[!] SetWinHKInject Exit!\n"); bOk = TRUE; Exit: if (ModuleHandle) FreeLibrary(ModuleHandle); return bOk; } //通過程序名獲得執行緒ID UINT32 GetTargetThreadIdFromProcessName(WCHAR *ProcessName) { PROCESSENTRY32 pe; HANDLE SnapshotHandle = NULL; HANDLE ProcessHandle = NULL; BOOL Return, ProcessFound = FALSE; UINT32 pTID, ThreadID; SnapshotHandle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (SnapshotHandle == INVALID_HANDLE_VALUE) { MessageBox(NULL, L"Error: unable to create toolhelp snapshot", L"Loader", NULL); return FALSE; } pe.dwSize = sizeof(PROCESSENTRY32); Return = Process32First(SnapshotHandle, &pe); while (Return) { if (_wcsicmp(pe.szExeFile, ProcessName) == 0) { ProcessFound = TRUE; break; } Return = Process32Next(SnapshotHandle, &pe); pe.dwSize = sizeof(PROCESSENTRY32); } CloseHandle(SnapshotHandle); //通過fs暫存器獲取TID _asm { mov eax, fs:[0x18] add eax, 36 mov[pTID], eax } ProcessHandle = OpenProcess(PROCESS_VM_READ, FALSE, pe.th32ProcessID); ReadProcessMemory(ProcessHandle,(LPCVOID)pTID, &ThreadID, 4, NULL); CloseHandle(ProcessHandle); return ThreadID; }
// dllmain.cpp : 定義 DLL 應用程式的入口點。 #include "stdafx.h" #include <Windows.h> #pragma data_seg(SHARD_SEG_NAME) static HHOOK g_hHook; #pragma data_seg() BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: { // //加入你想在目標程序空間HOOK的程式碼 // MessageBox(NULL, L"Inject Success!", L"Message", 0); } case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } __declspec(dllexport)LRESULT MyMessageProcess(int Code, WPARAM wParam, LPARAM lParam) { // //你自己對訊息的處理 // return CallNextHookEx(g_hHook, Code, wParam, lParam); }