注入(4)--消息鉤子注入(SetWindowsHookEX)

SetWindowsHookEx函數是微軟提供給程序開發人員進行消息攔截的一個API。不過,他的功能不僅可以用作消息攔截,還可以進行DLL注入。
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);
}

發佈了43 篇原創文章 · 獲贊 15 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章