WIN32 消息Hook API

Posted 不会写代码的丝丽

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WIN32 消息Hook API相关的知识,希望对你有一定的参考价值。

前言

Win32中存在一个消息机制,程序任何点击或者消息都会通过窗口过程下发,而微软提供SetWindowsHookExAPI来来允许我们进行相关事件监听,并且这个监听操作是优先于原始的函数调用的。

微软setwindowshookexa相关文档

HHOOK SetWindowsHookExA(
  int       idHook,
  HOOKPROC  lpfn,
  HINSTANCE hmod,
  DWORD     dwThreadId
);

微软把Hook分为两种:

  1. 线程钩子
  2. 全局钩子

线程钩子:HOOK自身程序消息
全局钩子:HOOK其他应用消息,内部机制是利用dll注入方式到其他程序。


Hook系统全局的方式

线程钩子

一个小Demo:


HHOOK g_hHook = NULL;
//每个键盘按下和弹起都会回调
LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam) {
	
	//文档说只能大于0才可以处理,否则传递事件
	if (code > 0)
	{
		char msg[100];
		sprintf_s(msg, "接收到的字符串 %c \\r\\n", wParam);
		OutputDebugString(msg);
	}



	return CallNextHookEx(g_hHook, code, wParam, lParam);
}

//开启键盘hook
void CMFCApplication2Dlg::OnBnClickedButton1()
{
	//调用微软函数提供Hook函数
	g_hHook = SetWindowsHookEx(
		WH_KEYBOARD,//这里设置你想Hook哪些消息,具体可参阅文档,WH_KEYBOARD表示键盘消息
		KeyboardProc,//这个WH_KEYBOARD消息回调的地址
		NULL,//如果仅仅Hook自己的应用固定传NULL即可
		GetCurrentThreadId()//如果HOOk是自身应用传入当前线程即可。
	);

	if (g_hHook == NULL)
	{
		::AfxMessageBox("hook失败了");
	}
	
}


void CMFCApplication2Dlg::OnBnClickedButton2()
{
	//卸载hook
	UnhookWindowsHookEx(g_hHook);
}

点击弹窗的安装Hook按钮然后输入键盘看日志如下:

全局钩子

首先要定义dll库内容如下:

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include<stdio.h>

HHOOK g_hHook = NULL;
//每个键盘按下和弹起都会回调
LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam) {

	if (code > 0)
	{
		char msg[100];
		sprintf_s(msg, "接收到的字符串 %c \\r\\n", wParam);
		OutputDebugString(msg);
	}

	return CallNextHookEx(g_hHook, code, wParam, lParam);
}

//开启键盘hook
__declspec(dllexport) void myInsject()
{
	//调用微软函数提供Hook函数
	g_hHook = SetWindowsHookEx(
		WH_KEYBOARD,//这里设置你想Hook哪些消息,具体可参阅文档,WH_KEYBOARD表示键盘消息
		KeyboardProc,//这个WH_KEYBOARD消息回调的地址
		GetModuleHandle("HookDll"),//如果需要hook全部进程,那么这里需要传入module句柄
		0//全局hook传入0
	);

	if (g_hHook == NULL)
	{
		::MessageBox(NULL,"hook失败了",NULL,MB_OK);
	}

}
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}


然后我们在另一个进程调用这个库函数

__declspec(dllimport) void  myInsject();
#pragma comment(lib,"..\\\\x64\\\\Debug\\\\HookDll.lib")

//开启键盘
void CMFCApplication2Dlg::OnBnClickedButton1()
{
	
	myInsject();
}


此时你可以Hook到其他程序的消息比如有道词典等

以上是关于WIN32 消息Hook API的主要内容,如果未能解决你的问题,请参考以下文章

Win32 程序的API内联与Hook

Win32 程序的API内联与Hook

.NET下如何拦截鼠标键盘消息?Win32NET来帮你

.NET下如何拦截鼠标、键盘消息?Win32NET来帮你

win32 API 笔记1

编程中常说的hook是啥意思?