searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

利用消息钩子进行注入

2023-08-31 04:18:12
17
0

在Windows系统中,消息钩子是一种能够获取和修改系统消息的机制。其中,WH_GETMESSAGE钩子是最常用的一种,它允许钩子程序获取发送到某个窗口的消息,包括用户输入、系统事件等。

下面的示例使用带有WH_GETMESSAGE钩子类型的SetWindowsHookEx将DLL注入到找到的第一个notepad进程中,并监视输入的所有键。这些键被发送到监视应用程序,该应用程序有效地查看用户在记事本中所做的每个按键。

这个示例包含两个项目。注入可执行文件(HookInject)和通过SetWindowsHookEx间接注入的DLL(HookDll).

要测试这个示例,首先运行notepad,然后运行HookInject。在记事本中输入。将在HookInject的控制台窗口中看到相同的文本.

其中,HookInject代码如下:

// HookInject.cpp : This file contains the 'main' function. Program execution begins and ends there.
//

#include <stdio.h>
#include <windows.h>
#include <assert.h>
#include <TlHelp32.h>
#include <Psapi.h>

int Error(const char* text) {
	printf("%s (%u)\n", text, ::GetLastError());
	return 1;
}

DWORD FindMainNotepadThread() {
	auto hSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
	if (hSnapshot == INVALID_HANDLE_VALUE)
		return 0;

	DWORD tid = 0;
	THREADENTRY32 th32;
	th32.dwSize = sizeof(th32);

	::Thread32First(hSnapshot, &th32);
	do {
		auto hProcess = ::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, th32.th32OwnerProcessID);
		if (hProcess) {
			WCHAR name[MAX_PATH];
			if (::GetProcessImageFileName(hProcess, name, MAX_PATH) > 0) {
				auto bs = ::wcsrchr(name, L'\\');
				if (bs && ::_wcsicmp(bs, L"\\notepad.exe") == 0) {
					tid = th32.th32ThreadID;
				}
			}
			::CloseHandle(hProcess);
		}
	} while (tid == 0 && ::Thread32Next(hSnapshot, &th32));
	::CloseHandle(hSnapshot);

	return tid;
}

int main() {
	DWORD tid = FindMainNotepadThread();
	if (tid == 0)
		return Error("Failed to locate Notepad");

	auto hDll = ::LoadLibrary(L"HookDll");
	if (!hDll)
		return Error("Failed to locate Dll\n");

	using PSetNotify = void (WINAPI*)(DWORD, HHOOK);
	auto setNotify = (PSetNotify)::GetProcAddress(hDll, "SetNotificationThread");
	if (!setNotify)
		return Error("Failed to locate SetNotificationThread function in DLL");

	auto hookFunc = (HOOKPROC)::GetProcAddress(hDll, "HookFunction");
	if (!hookFunc)
		return Error("Failed to locate HookFunction function in DLL");

	auto hHook = ::SetWindowsHookEx(WH_GETMESSAGE, hookFunc, hDll, tid);
	if (!hHook)
		return Error("Failed to install hook");

	setNotify(::GetCurrentThreadId(), hHook);
	::PostThreadMessage(tid, WM_NULL, 0, 0);

	MSG msg;
	while (::GetMessage(&msg, nullptr, 0, 0)) {
		if (msg.message == WM_APP) {
			printf("%c", (int)msg.wParam);
			if (msg.wParam == 13)
				printf("\n");
		}
	}
	::UnhookWindowsHookEx(hHook);
	::FreeLibrary(hDll);

	return 0;
}

HookDll代码如下:

// dllmain.cpp : Defines the entry point for the DLL application.

#include "pch.h"

#pragma data_seg(".shared")
DWORD g_ThreadId = 0;
HHOOK g_hHook = nullptr;
#pragma data_seg()
#pragma comment(linker, "/section:.shared,RWS")

BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, PVOID pReserved) {
	switch (reason) {
		case DLL_PROCESS_ATTACH:
			::DisableThreadLibraryCalls(hModule);
			break;
		case DLL_PROCESS_DETACH:
			::PostThreadMessage(g_ThreadId, WM_QUIT, 0, 0);
			break;

	}
	return TRUE;
}

extern "C" LRESULT CALLBACK HookFunction(int code, WPARAM wParam, LPARAM lParam) {
	if (code == HC_ACTION) {
		auto msg = (MSG*)lParam;
		if (msg->message == WM_CHAR) {
			::PostThreadMessage(g_ThreadId, WM_APP, msg->wParam, msg->lParam);
			// prevent A characters from getting to the app
			//if (msg->wParam == 'A' || msg->wParam == 'a')
			//	msg->wParam = 0;
		}
	}
	return ::CallNextHookEx(g_hHook, code, wParam, lParam);
}

extern "C" void WINAPI SetNotificationThread(DWORD threadId, HHOOK hHook) {
	g_ThreadId = threadId;
	g_hHook = hHook;
}
0条评论
0 / 1000