「Win」HOOK钩子技术

news2024/12/26 4:39:37

在这里插入图片描述

✨博客主页:何曾参静谧的博客
📌文章专栏:「Win」Windows程序设计


相关术语

HOOK技术:是一种在Windows系统中常用的技术,它可以截获并修改操作系统或应用程序的行为。通过使用Hook技术,我们可以实现以下功能:

  • 监视和记录系统和应用程序的行为。
  • 修改系统和应用程序的行为,以满足特定需求。
  • 在系统和应用程序的行为发生时,执行自定义代码。

全局钩子(Global Hook):是指在整个系统中安装的钩子。全局钩子可以截获并修改所有应用程序的行为。全局钩子通常用于实现系统级别的功能,如监视和记录用户输入、拦截和修改系统消息等。
局部钩子(Local Hook):是指在特定应用程序中安装的钩子。局部钩子只能截获并修改特定应用程序的行为。局部钩子通常用于实现应用程序级别的功能,如拦截和修改应用程序消息、增强用户体验等。(在使用时需要指定应用程序的句柄)

钩子类型对应ID
消息钩子WH_GETMESSAGE(全局)
键盘钩子WH_KEYBOARD(局部)
WH_KEYBOARD_LL(全局)
鼠标钩子WH_MOUSE(局部)
WH_MOUSE_LL(全局)
线程钩子WH_CALLWNDPROC(全局)
进程钩子WH_CBT(全局)

一、全局钩子和局部钩子

#include <Windows.h>
#include <iostream>

using namespace std;

// 全局钩子回调函数
LRESULT CALLBACK GlobalKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode == HC_ACTION)
    {
        KBDLLHOOKSTRUCT* pKeyboard = (KBDLLHOOKSTRUCT*)lParam;
        if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)
        {
            // 按下键盘键
            cout << "Global Key down: " << pKeyboard->vkCode << endl;
        }
        else if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP)
        {
            // 松开键盘键
            cout << "Global Key up: " << pKeyboard->vkCode << endl;
        }
    }
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

// 局部钩子回调函数
LRESULT CALLBACK LocalKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode == HC_ACTION)
    {
        KBDLLHOOKSTRUCT* pKeyboard = (KBDLLHOOKSTRUCT*)lParam;
        if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)
        {
            // 按下键盘键
            cout << "Local Key down: " << pKeyboard->vkCode << endl;
        }
        else if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP)
        {
            // 松开键盘键
            cout << "Local Key up: " << pKeyboard->vkCode << endl;
        }
    }
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

int main()
{
    // 安装全局钩子
    HHOOK hGlobalHook = SetWindowsHookEx(WH_KEYBOARD_LL, GlobalKeyboardProc, GetModuleHandle(NULL), 0);

    // 安装局部钩子
    HHOOK hLocalHook = SetWindowsHookEx(WH_KEYBOARD, LocalKeyboardProc, GetModuleHandle(NULL), GetCurrentThreadId());

    // 消息循环
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    // 卸载全局钩子和局部钩子
    UnhookWindowsHookEx(hGlobalHook);
    UnhookWindowsHookEx(hLocalHook);

    return 0;
}

二、消息钩子

实现现一个消息钩子回调函数 MessageProc,用于拦截窗口消息。然后,在 main 函数中,我们使用 SetWindowsHookEx 函数安装了一个 WH_GETMESSAGE 消息钩子,并在消息循环中等待消息的到来。在消息钩子回调函数中,我们判断收到的消息是否为键盘消息,如果是则打印出消息类型。最后,在消息循环结束时,我们调用 UnhookWindowsHookEx 函数卸载消息钩子。

#include <Windows.h>
#include <iostream>

using namespace std;

// 消息钩子回调函数
LRESULT CALLBACK MessageProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode == HC_ACTION)
    {
        MSG* pMsg = (MSG*)lParam;
        if (pMsg->message == WM_KEYDOWN || pMsg->message == WM_KEYUP)
        {
            // 拦截键盘消息
            cout << "Message Hook: " << pMsg->message << endl;
        }
    }
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

int main()
{
    // 安装消息钩子
    HHOOK hHook = SetWindowsHookEx(WH_GETMESSAGE, MessageProc, GetModuleHandle(NULL), 0);

    // 消息循环
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    // 卸载消息钩子
    UnhookWindowsHookEx(hHook);

    return 0;
}

三、键盘钩子

首先定义了一个全局的键盘钩子句柄 g_hHook,并在 main 函数中通过 SetWindowsHookEx 函数安装了一个全局键盘钩子。然后,在键盘钩子回调函数 KeyboardProc 中,我们捕获并处理了键盘事件,并在控制台上显示了按下或松开的键盘键。最后,在消息循环结束时,我们调用 UnhookWindowsHookEx 函数卸载全局键盘钩子。

#include <Windows.h>
#include <iostream>

using namespace std;

// 定义全局的键盘钩子句柄
HHOOK g_hHook = NULL;

// 键盘钩子回调函数
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode == HC_ACTION)
    {
        KBDLLHOOKSTRUCT* pKeyboard = (KBDLLHOOKSTRUCT*)lParam;
        if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)
        {
            // 按下键盘键
            cout << "Key down: " << pKeyboard->vkCode << endl;
        }
        else if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP)
        {
            // 松开键盘键
            cout << "Key up: " << pKeyboard->vkCode << endl;
        }
    }
    return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}

int main()
{
    // 安装全局键盘钩子
    g_hHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, GetModuleHandle(NULL), 0);

    // 消息循环
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    // 卸载全局键盘钩子
    UnhookWindowsHookEx(g_hHook);
    return 0;
}

四、鼠标钩子

代码实现了一个鼠标钩子回调函数 MouseProc,用于拦截鼠标事件。然后,在 main 函数中,我们使用 SetWindowsHookEx 函数安装了一个 WH_MOUSE_LL 鼠标钩子,并在消息循环中等待消息的到来。在鼠标钩子回调函数中,我们判断收到的消息类型并打印出鼠标位置。最后,在消息循环结束时,我们调用 UnhookWindowsHookEx 函数卸载鼠标钩子。

#include <Windows.h>
#include <iostream>

using namespace std;

// 鼠标钩子回调函数
LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode == HC_ACTION)
    {
        MOUSEHOOKSTRUCT* pMouseStruct = (MOUSEHOOKSTRUCT*)lParam;
        if (wParam == WM_MOUSEMOVE)
        {
            // 拦截鼠标移动事件
            cout << "Mouse Hook: WM_MOUSEMOVE, x=" << pMouseStruct->pt.x 
                << ", y=" << pMouseStruct->pt.y << endl;
        }
        else if (wParam == WM_LBUTTONDOWN)
        {
            // 拦截鼠标左键按下事件
            cout << "Mouse Hook: WM_LBUTTONDOWN, x=" << pMouseStruct->pt.x 
                << ", y=" << pMouseStruct->pt.y << endl;
        }
        else if (wParam == WM_RBUTTONDOWN)
        {
            // 拦截鼠标右键按下事件
            cout << "Mouse Hook: WM_RBUTTONDOWN, x=" << pMouseStruct->pt.x 
                << ", y=" << pMouseStruct->pt.y << endl;
        }
    }
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

int main()
{
    // 安装鼠标钩子
    HHOOK hHook = SetWindowsHookEx(WH_MOUSE_LL, MouseProc, GetModuleHandle(NULL), 0);

    // 消息循环
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    // 卸载鼠标钩子
    UnhookWindowsHookEx(hHook);

    return 0;
}

注意事项

需要注意的是,使用消息钩子需要谨慎,因为它可以拦截窗口消息,可能会对应用程序的正常运行产生影响。因此,在使用消息钩子时,应该根据实际需求选择合适的钩子类型,并谨慎对待其中的风险和安全问题。


在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/623177.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网络编程重点

1> OIS 7层模型 TCP/IP 4层模型 5层模型 2> 传输层的功能 网络层的功能&#xff1f;以及分别是第几层 传输层&#xff1a;提供端到端的可靠传输&#xff0c;指定哪个进程哪个发送进程接收 第四层 网络层&#xff1a;寻址和路由选择 第三层 3>MAC地址&#xff1a; a. …

JAVA 巧用 Robot 类(应用于网课)

目录 前言&#xff1a;理论依据&#xff1a;现实依据&#xff1a;朴素版只能循环阅读不能翻页&#xff1a;升级版 翻页 阅读&#xff1a;如何使用&#xff1a; 前言&#xff1a; 最近发现有个阅读得读300分钟&#xff0c;懒得去找软件&#xff0c;于是就自己写了一个代码去实现…

(1Gb)S28HS01GTGZBHA030/ S28HS01GTGZBHV033/ S28HS01GTGZBHA033 FLASH - NOR闪存器件

产品简介&#xff1a; Infineon 带有HyperBus™的S26HSxT以及S26HLxT Semper™闪存是一种高性能、安全可靠的NOR闪存解决方案。 这些组件集成了关键的安全功能&#xff0c;用于汽车、工业、通信等行业的各种应用。S26HSxT和S26HLxT Semper闪存采用HyperBus接口&#xff0c;符…

仙境传说RO:添加限购物品刷新物品库存教程

仙境传说RO&#xff1a;添加限购物品刷新物品库存教程 大家好我是艾西&#xff0c;在游戏中我们会有普通的基础装备那么必然就会有到顶的套装&#xff0c;往往可能一套到顶的套装就可能霸服。那么就需要GM去做游戏的设定以及限制&#xff0c;上一篇文章中我给大家讲述了如果创…

风控系统设计

一、思路 要实现一个简单的业务风控组件,要做什么工作呢? 1.风控规则的实现 a.需要实现的规则: 自然日计数 自然小时计数 自然日自然小时计数 自然日自然小时计数 这里并不能单纯地串联两个判断,因为如果自然日的判定通过,而自然小时的判定不通过的时候,需要回退,自然日…

NetApp 混合云技术

为何选择 NetApp 的混合云 NetApp 可帮助您构建一个现代化的混合云&#xff0c;从而统一您的基础架构&#xff0c;并让您的数据可以自由流动到所需的任何位置&#xff0c;确保以数据为中心的业务能够快速应对变化&#xff0c;灵活调整方向&#xff0c;并获得竞争优势。 什么是…

界面控件DevExtreme工具栏 - 拥有全新的自适应模式/弹出窗口

本文涵盖了最近对DevExtreme JavaScript工具栏组件(v22.2)所做的更改&#xff0c;并简要描述了相关的实现细节。 DevExtreme拥有高性能的HTML5 / JavaScript小部件集合&#xff0c;使您可以利用现代Web开发堆栈&#xff08;包括React&#xff0c;Angular&#xff0c;ASP.NET C…

对话人工智能 |新时代AI如何“落地“

前言&#xff1a; Comate代码助手推出&#xff0c;现场生成了贪吃蛇游戏&#xff0c;我们距离AI自动编程还有多远&#xff1f; 文章目录 序章正文背景基础坚实文心大模型飞浆深度学习框架 Comate的出现优质的智能助理和伙伴多场景适用优势特征Demo演示视频&#xff1a; 总结 序…

【C++学习】C++入门(1)

写在前面 欢迎来到C的世界&#xff0c;这是一门令人兴奋的语言。 好吧&#xff0c;每当我开始阅读C的书籍的时候&#xff0c;开头的第一句话必定是这个&#xff0c; 也不知道其他语言的编程书籍是不是这样&#xff0c;那就让这句话也作为我C分享之路上的第一句话吧。 目录 …

mac配置iterm2

1、iTerm2 - macOS Terminal Replacement 下载 2、设置默认 3、配置主题theme 这里选择用Solarized Dark theme&#xff0c;下载地址&#xff1a;http://ethanschoonover.com/solarized&#xff0c;解压。 我这里失效了&#xff0c;选择从github上下载Solarized Dark这个主题…

拼图游戏-第14届蓝桥杯国赛Scratch真题初中级组第5题

[导读]&#xff1a;超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成&#xff0c;后续会不定期解读蓝桥杯真题&#xff0c;这是Scratch蓝桥杯真题解析第147讲。 拼图游戏&#xff0c;本题是2023年5月28日上午举行的第14届蓝桥杯国赛Scratch图形化编程初中级组真题第5题&…

国产Gauss 分布式数据库概述

一、前言 GaussDB 是华为2023年6月7日发布新一代分布式数据库&#xff0c;采用share-nothing架构&#xff0c;数据自动分片&#xff0c;通过GTM-Lite技术实现事务强一致&#xff0c;无中心节点性能瓶颈&#xff0c;是华为基于openGauss自主创新研发的一款分布式关系型数据库&am…

spark的使用

国内源下载 https://mirrors.cloud.tencent.com/apache/spark/ 环境配置(三台机器都要配置) 修改/etc/profile export JAVA_HOME/export/server/jdk export HADOOP_HOME/export/server/hadoopexport SPARK_HOME/export/server/spark export PYSPARK_PYTHON/pythonenv/pyspark…

苹果MR Vision Pro将会带动哪些零部件出货?

苹果如何重新定义AR? 在如今以智能手机为主的消费电子市场下行阶段&#xff0c;市场急需开辟一个新的领域带来新的增长点&#xff0c;以往被寄予厚望的VR/AR等头显设备在经历了数年发展后&#xff0c;依旧难堪大任&#xff0c;业界都把希望寄托在苹果身上。 简单来说&#xf…

学习Java一年的程序员的Python学习记录(转行了,校招Java根本找不到工作)

文章目录 一 基础语法二 集合三 函数四 IO五 项目结构六 面向对象 一 基础语法 Python如果是部署在Linux上&#xff0c;是需要通过源码去编译安装的&#xff0c;在编译的过程中&#xff0c;会以来一些第三方的软件。所以这些软件需要提前安装一下。 yum install wget zlib-deve…

VS报错集锦 --- 出现:error LNK2005: _DllMain@12 已经在 *****.obj 中定义 错误

出现的问题&#xff1a; 1>mfcs140d.lib(dllmodul.obj) : error LNK2005: DllMain 已经在 DllMain.obj 中定义 解决方法&#xff1a; 项目 -- 属性 -- c/c -- 预处理器 -- 将预处理定义中的_USRDLL 删除即可

“大四在读生”都四面成功拿到字节跳动Offer了,你还有什么理由去摸鱼?

博主大四在读&#xff0c;投的是字节 Data 的软件测试岗位实习生&#xff0c;base 杭州。 时间线&#xff1a; 4.12 投递4.13 安排简历筛选4.14 安排面试4.19 16:00 一面4.22 16:00 二面 4.23 8:00 三面4.23 16:00 HR 面4.23 16:30 Offer 一面 你对字节跳动的了解和认知有哪…

Allegro16.6详细教程(四)

(2) PIN的定義 如果用第一種方式產生Netlist的話,就要對於一些Power pin加以定義。 1.滑鼠點選想定義的零件。 2.點選選單中Edit>Part。 3.用滑鼠點選想定義的Pin腳。 4.點選功能表中Edit>Properties,透過這些步驟就看到了下面的這個對話方塊了。 在這裏主要是把T…

Apache Flink 1.17

Apache Flink 1.17 1. Flink 1.17 Overview2. Flink 1.17 Overall Story3. Flink 1.17 Key Features4. Summary5. Q&A 1. Flink 1.17 Overview Flink 1.17 版本完成了 7 个 FLIP&#xff0c;累计贡献者 170&#xff0c;解决 600Issue 以及 1100Commits&#xff0c;整体来看…

ppt如何录屏?电脑怎么录制ppt文稿?

案例&#xff1a;在电脑上怎么录制PPT文稿&#xff0c;具体怎么操作&#xff1f; 【我工作的时候经常需要用到ppt文稿&#xff0c;有时还需要对PPT文稿进行录制&#xff0c;但我不知道如何操作。有小伙伴知道在电脑上如何录制ppt文稿吗&#xff1f;需要用到什么工具&#xff1…