Windows消息钩取

消息钩子

消息钩子:钩取OS发送给应用程序的消息。

以键盘消息为例,常规的Windows消息流:

  • 发生键盘输入事件时,WM_KEYDOWN消息将被添加到[OS message queue]
  • OS判断发生事件的应用程序,从[OS message queue]取出消息,添加到相应应用程序的[application message queue]中
  • 应用程序监听自己的[application message queue],发现新添加的WM_KEYDOWN消息后,处理该消息

SetWindowsHookEx()

使用SetWindowsHookEx() API可以很容易地实现消息钩子:

HHOOK SetWindowsHookEx(
	int idHook,       //hook type
	HOOKPROC lpfn,    //hook procedure
	HINSTANCE hMod,   //hook procedure所属的DLL句柄
	DWORD dwThreadId  //想要挂钩的线程ID,0则为全局钩子
);

安装消息“钩子”时,“钩子”过程需要存在于某个DLL内部。

示例代码

HookMain.exe的源文件:

#include "stdio.h"
#include "conio.h"
#include "windows.h"

#define DEF_DLL_NAME "KeyHook.dll"
#define DEF_HOOKSTART "HookStart"
#define DEF_HOOKSTOP "HookStop"

typedef void(*PFN_HOOKSTART)();
typedef void(*PFN_HOOKSTOP)();

void main(){
	HMODULE hDll=NULL;
	PFN_HOOKSTART HookStart=NULL;
	PFN_HOOKSTOP HookStop=NULL;
	
	//加载KeyHook.dll
	hDll=LoadLibraryA(DEF_DLL_NAME);
	
	//获取导出函数地址
	HookStart=(PFN_HOOKSTART)GetProcAddress(hDll,DEF_HOOKSTART);
	HookStop=(PFN_HOOKSTOP)GetProcAddress(hDll,DEF_HOOKSTOP);
	
	//开始钩取
	HookStart();
	
	//等待用户输入“q”
	printf("press 'q' to quit!\n");
	while(_getch()!='q');
	
	//终止钩取
	HookStop();
	
	//卸载KeyHook.dll
	FreeLibrary(hDll);
}

KeyHook.dll的源码:

#include "stdio.h"
#include "windows.h"

#define DEF_PROCESS_NAME "notepad.exe"

HINSTANCE g_hInstance=NULL;
HHOOK g_hHook=NULL;
HWND g_hWnd=NULL;

BOOL WINAPI DLLMain(HINATANCE hinstDll, DWORD dwReason, LPVOID lpvReserved){
	switch(dwReason){
		case DLL_PROCESS_ATTACH:
			g_hInstance=hinstDll;
			break;
			
		case DLL_PROCESS_DETACH:
			break;
	}
	return TRUE;
}

LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam){
	char szPath[MAX_PATH]={0,};
	char *p=NULL;
	
	if(nCode=0){
		//0=key press, 1=key release
		if(!(lParam & 0x80000000)){   //释放键盘按钮时
			GetModuleFileNameA(NULL, szPath, MAX_PATH);
			p=strrchr(szPath,'\\');
			
			//比较当前进程名,若为notepad.exe则消息不会传递给应用程序
			if(!_stricmp(p+1, DEF_PROCESS_NAME))
				return 1;
		}
	}
	//若非notepad.exe,则调用CallNextHookEx()函数,将消息传给应用程序
	return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}

#ifdef __cplusplus
extern "C" {
#endif
__ declspec(dllexport) void HookStart(){
	g_hHook=SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, g_hInstance, 0);
}
__declspec(dllexport) void HookStop(){
	if(g_hHook){
		UnhookWindowsHookEx(g_hHook);
		g_hHook=NULL;
	}
}
#ifdef __cplusplus
}
#endif
参考文献

《逆向工程核心原理》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值