Hook拦截键盘输入实验

Hook拦截键盘输入实验

实验环境:

  1. VS 2022
  2. Windows 11
  3. ProcessExplorer

1. 知识储备

(1) hook(消息钩子)

Hook,是Windows消息处理机制的一个平台,应用程序可以在上面设置子程序以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理window消息或特定事件。

(2) 相关函数

  • SetWindowsHookEx()
    消息钩子注入原理是利用Windows 系统中SetWindowsHookEx()这个API,他可以拦截目标进程的消息到指定的DLL中导出的函数,利用这个特性,我们可以将DLL注入到指定进程中。是所有类型的钩子基本上都需要的基础函数。

  • KeyboardProc()
    应用程序应接受来自键盘和鼠标的用户输入。 应用程序以发布到其窗口的消息的形式接收键盘输入。是拦截键盘信息的必备函数。相关定义在:https://learn.microsoft.com/zh-cn/windows/win32/inputdev/about-keyboard-input中可以查阅。
    这里给出两个必须要用到的信息首先是传入函数的参量:lParam
    如下图所示,是相关信息
    在这里插入图片描述
    以及键盘信息对应的二进制数值,以便于判断并拦截相关输入信息。如下图所示。
    在这里插入图片描述

2. Dll动态链接库编写

有了以上知识储备开始编写相关动态链接库。在vs2022中创建动态链接库项目。如下图所示,
在这里插入图片描述
Dlltest.cpp内容如下:


#include "pch.h"
#include<stdio.h>
#include<windows.h>

#define HOOK_PROCESS_NAME "notepad.exe"

HINSTANCE hInstance = NULL;
HHOOK hHook = NULL;
HWND hWnd = NULL;

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID IpvReserved)
{
	switch (dwReason)
	{
	case DLL_PROCESS_ATTACH:
		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 (!(lParam & 0x80))//释放按键时
	{
		GetModuleFileNameA(NULL, szPath, MAX_PATH);
		p = strrchr(szPath, '\\');
		//比较进程名称
		if (!_stricmp(p + 1, HOOK_PROCESS_NAME))
		{
			return 1;
		}
	}
	//不是hook的程序,则传递到出去
	return CallNextHookEx(hHook, nCode, wParam, lParam);
}
extern "C" __declspec(dllexport) void HookStart()
{
	hHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, hInstance, 0);
}

extern "C" __declspec(dllexport) void HookStop()
{
	if (hHook)
	{
		UnhookWindowsHookEx(hHook);
		hHook = NULL;
	}
}

点击生成解决方案,会得到hookkeyboard.lib以及hookkeybboard.dll两个项目。(这两个项目需要保存下来,以便后续自己编写的程序能够成功调用这个我们自己编写的动态链接库)。

3. 相关程序编写

程序编写,没有什么需要特别注意的内容,创建相关win32项目,即可。编写代码如下:

#include<stdio.h>
#include<conio.h>
#include<windows.h>

#define DLL_NAME   "HookKeyBoard.dll"
#define HOOK_START "HookStart"
#define HOOK_STOP  "HookStop"

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

int main()
{
    HMODULE hDll = NULL;
    PFN_HOOKSTART HookStart = NULL;
    PFN_HOOKSTOP  HookStop = NULL;
    char ch = 0;

    //加载dll
    hDll = LoadLibraryA(DLL_NAME);

    //获取导出函数的地址 	
    HookStart = (PFN_HOOKSTART)GetProcAddress(hDll, HOOK_START);
    HookStop = (PFN_HOOKSTOP)GetProcAddress(hDll, HOOK_STOP);

    //开始hook
    HookStart();

    //输入Q退出hook
    printf("输入Q退出hook!\n");
    while (1)
    {
        char h = _getch();
        _putch(h);
        if (h == 'Q')
            break;
    }
    //结束hook
    HookStop();

    //卸载dll
    FreeLibrary(hDll);
    return 0;
}

完成相应编写后,需要将刚刚生成的项目放在现在这个项目的目录下,具体如下图所示。
在这里插入图片描述
放入目录后,在属性中添加相关信息。
在这里插入图片描述
此时运行这个程序,再打开记事本,向记事本内输入,无法显示(记得调成英文输入,中文输入由于输入法可能拦截不了)。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值