windows 消息钩取

windows 消息钩取

当键盘发生输入事件时,键盘消息钩子就会提前获得消息的内容、类型

并且可以对其做出修改

实现消息钩子的api:SetWindowsHookEx

HHOOK WINAPI SetWindowsHookEx(
  _In_  int    idHook,            设置钩子的类型.意思就是我要设置的钩子是什么钩子. 可以是监视窗口过程.可以是监视消息队列.
  _In_ HOOKPROC lpfn,             根据钩子类型.设置不同的回调函数.
  _In_ HINSTANCE hMod,            钩子设置的Dll实例句柄,就是DLL的句柄
  _In_ DWORD dwThreadId             设置钩子的线程ID. 如果为0 则设置为全局钩子.
);

KeyBoardProc(钩子过程函数)

LRESULT CALLBACK KeyboardProc( 
    int code,
    WPARAM wParam,
    LPARAM lParam
);

参数说明

code [in]

类型: int

挂钩过程用来确定如何处理消息的代码。 如果 代码 小于零,则挂钩过程必须将消息传递给 CallNextHookEx 函数而不进行进一步处理,并应返回 CallNextHookEx 返回的值。 此参数的取值可为下列值之一:

含义
HC_ACTION 0WParamlParam 参数包含有关击键消息的信息。
HC_NOREMOVE 3WParamlParam 参数包含有关击键消息的信息,而击键消息尚未从消息队列中删除。 (名为 PeekMessage 函数的应用程序,指定 PM_NOREMOVE 标志。 )

wParam [in]

类型: WPARAM

生成击键消息的密钥的 虚拟键代码

lParam [in]

类型: LPARAM

重复次数、扫描代码、扩展键标志、上下文代码、上一个键状态标志和转换状态标志。 有关 lParam 参数的详细信息,请参阅 击键消息标志。 下表描述了此值的位数。

Bits说明
0-15重复计数。 值是用户按住该键时,击键重复的次数,即。
16-23扫描代码。 该值取决于 OEM。
24指示密钥是否为扩展键,如数字键盘上的函数键或键。 如果键是扩展键,则值为 1; 否则为。否则,为0。
25-28保留。
29上下文代码。 如果 ALT 键为关闭状态,则值为 1; 否则为。否则,为0。
30之前的键状态。 如果在发送消息之前键关闭,则值为 1; 否则为。如果键已启动,则为0。
31转换状态。 如果正在按下键,则该值为 0; 如果正在释放,则该值为1。

分析源代码

hookmain.exe

先加载keyhook.dll文件

然后调用hoolstart函数开始钩取

输入q终止

#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;
    char            ch = 0;


    hDll = LoadLibraryA(DEF_DLL_NAME);//加载KeyHook.dll,获得dll的句柄
    if (hDll == NULL)
    {
        printf("LoadLibrary(%s) failed!!! [%d]", DEF_DLL_NAME, GetLastError());
        return;
    }

    HookStart = (PFN_HOOKSTART)GetProcAddress(hDll, DEF_HOOKSTART);//利用GetProcAddress()获得HookStart的函数地址
    HookStop = (PFN_HOOKSTOP)GetProcAddress(hDll, DEF_HOOKSTOP);//利用GetProcAddress()获得HookStop的函数地址

    HookStart();//开始钩取函数

    printf("press 'q' to quit!\n");
    while (_getch() != 'q');//遇到键盘输入q就退出

    HookStop();//退出钩取函数

    FreeLibrary(hDll);
}

KeyHook

调用导出函数HookStart时,SetWindowsHookEX函数就会将KeyBoardProc函数添加到键盘钩链

#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(HINSTANCE 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 )
	{
		// bit 31 : 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

调试分析

具体看书,这里列出主要内容

先调试HookMain.exe

通过od搜索字符串找到核心的代码部分并设置断点

在这里插入图片描述

继续调试,先经过401006处调用函数进入KeyHook函数EP

之后在40104B处调用ebx处函数:KeyHook中的HookStart函数,进入看看
在这里插入图片描述

接下来的四行push指令传入SetWindowsHookEXW的第4,3,2,1个参数,根据本文上面的参数说明,第二个参数:回调函数的地址

所以回调函数地址是10001020(钩子过程的地址)

再调试notepad.exe进程中的KeyHook.dll

拖入od f9 运行

然后在选项中设置:

在这里插入图片描述

这样当程序有dll载入时会自动暂停调试到dll的入口

接着运行HookMain.exe

在notepad中输入,没有显示,但od自动停在了dll 的 ep

在这里插入图片描述

接着找到刚才获得的HookStart函数地址10001020(KeyboardProc):
在这里插入图片描述

堆栈中还能看到KeyboardProc参数;
在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Windows钩子函数是一种Windows API机制,它允许程序在操作系统中拦截和监视特定事件或消息。这些事件或消息可以是键盘、鼠标、消息队列等。钩子函数通常用于记录用户输入,或者在特定条件下触发自定义操作。 实现Windows钩子函数需要以下步骤: 1. 定义钩子函数 钩子函数是一个回调函数,当特定事件或消息发生时,操作系统将调用该函数。钩子函数需要根据钩子类型和事件类型进行定义,例如键盘钩子函数可以监视按键事件,鼠标钩子函数可以监视鼠标事件等。 2. 安装钩子 安装钩子需要使用`SetWindowsHookEx`函数。该函数需要三个参数:钩子类型、钩子函数地址、以及钩子函数所属进程的句柄。钩子类型可以是全局钩子或局部钩子,具体取决于监视的事件或消息。 3. 卸载钩子 卸载钩子需要使用`UnhookWindowsHookEx`函数。该函数需要一个参数,即之前安装钩子时返回的句柄。 下面是一个示例键盘钩子函数的实现: ```c++ LRESULT CALLBACK KeyboardHook(int nCode, WPARAM wParam, LPARAM lParam) { if (nCode >= 0) { // 拦截到键盘事件 PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)lParam; if (wParam == WM_KEYDOWN) { // 按键按下事件 // 处理按键事件 } } return CallNextHookEx(NULL, nCode, wParam, lParam); // 调用下一个钩子 } int main() { HHOOK hook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHook, NULL, 0); // 安装键盘钩子 // ... UnhookWindowsHookEx(hook); // 卸载键盘钩子 return 0; } ``` 在上面的示例中,`KeyboardHook`函数是一个键盘钩子函数,它拦截键盘事件并进行处理。在`main`函数中,使用`SetWindowsHookEx`函数安装了一个全局键盘钩子,并使用`UnhookWindowsHookEx`函数卸载了该钩子。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zsc_02

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值