百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

浅谈c++ hook 钩子的使用介绍 c#钩子

liebian365 2024-11-12 13:07 28 浏览 0 评论

一、基本概念:

Hook是Windows平台的消息处理机制。 应用程序可以在其上设置子例程来监视指定窗口的某些消息,并且被监视的窗口可以由其他进程创建。 当消息到达时,它会在目标窗口处理函数之前被处理。 钩子机制允许应用程序拦截并处理窗口消息或特定事件。

钩子实际上是处理消息的程序段。 它通过系统调用挂接到系统中。 每当发送特定消息时,钩子程序在到达目标窗口之前捕获该消息,即钩子函数首先获得控制权。 此时,钩子函数可以处理(改变)消息,不处理而继续投递消息,或者强制结束消息投递。

2、运行机制:

1、hook列表和hook子流程:

每个 Hook 都有一个与其关联的指针列表,称为钩子列表,由系统维护。 该列表的指针指向Hook子例程调用的指定的、应用程序定义的回调函数,即Hook的各个处理子例程。 当与指定的 Hook 类型关联的消息发生时,系统将消息传递给 Hook 子例程。 有些Hook子进程只能监听消息,或者修改消息,或者停止消息的进程,以防止这些消息被传递到下一个Hook子进程或者目标窗口。 最近安装的钩子放在链的开头,最早安装的钩子放在链的末尾,即后添加的先获得控制权。

Windows 不要求钩子子进程的卸载顺序必须与安装顺序相反。 每当卸载一个钩子时,Windows都会释放它占用的内存并更新整个钩子列表。 如果程序安装了一个钩子,但在卸载该钩子之前结束,系统会自动为其卸载该钩子。

挂钩子例程是应用程序定义的回调函数(CALL 编程Inn BACK 函数)。 它不能定义为某个类的成员函数,只能定义为普通的C函数。 用于监视系统或特定类型的事件。 这些事件可以与特定线程相关联,也可以是系统中所有线程的事件。

钩子子例程必须遵循以下语法:

 LRESULT CALLBACK HookProc  int nCode,    wpARAM wParam,  
  LPARAM lParam 
 ); 

HookProc 是应用程序定义的名称。

nCode参数是Hook代码,Hook子程序通过这个参数来确定任务。 该参数的值取决于 Hook 类型。 每种类型的Hook都有自己的Hook代码特征字符集。

安卓

wParam和lParam参数的值取决于Hook代码,但它们的典型值包含有关发送或接收消息的信息。

2、Hook安装与释放:

使用 API 函数 SetWindowsHookEx() 将应用程序定义的挂钩子例程安装到挂钩列表中。 SetWindowsHookEx 函数始终将 Hook 子例程安装在 Hook 链的开头。 当指定类型的Hook监听的事件发生时,系统会调用与该Hook关联的Hook链开头的Hook子例程。 Hook链中的每个Hook子进程决定是否将此事件传递给下一个Hook子进程。 Hook子例程需要调用CallNextHookEx函数将事件传递给下一个Hook子例程。

HHOOK SetWindowsHookEx(       int idHook,   // 钩子的类型,即它处理的消息类型       HOOKPROC lpfn,  // 钩子子程的地址指针。如果dwThreadId参数为0  
   // 或是一个由别的进程创建的线程的标识,  
   // lpfn必须指向DLL中的钩子子程。  
   // 除此以外,lpfn可以指向当前进程的一段钩子子程代码。  
   // 钩子函数的入口地址,当钩子钩到任何消息后便调用这个函数。  
     HINSTANCE hMod, // 应用程序实例的句柄。标识包含lpfn所指的子程的DLL。  
   // 如果dwThreadId 标识当前进程创建的一个线程,  
   // 而且子程代码位于当前进程,hMod必须为NULL。  
   // 可以很简单的设定其为本应用程序的实例句柄。  
     DWORD dwThreadId // 与安装的钩子子程相关联的线程的标识符。  
   // 如果为0,钩子子程与所有的线程关联,即为全局钩子。  
           );  

如果函数成功,则返回钩子子进程的句柄,如果失败,则返回NULL。

上述钩子子进程与线程的关联是指发送给钩子链中的线程的消息同时发送给钩子子进程并由钩子子进程首先处理。

调用钩子子例程中已获得控制权的钩子函数。 消息处理完成后,如果想让消息继续投递,那么就必须调用另一个SDK中的API函数CallNextHookEx来传递给它执行钩子列表。 下一个钩子子程序。 成功时,该函数返回钩子链中下一个钩子进程的返回值。 返回值的类型取决于钩子的类型。 该函数的原型如下:

LRESULT CallNextHookEx 
  ( 
  HHOOK hhk; 
  int nCode; 
  WPARAM wParam; 
  LPARAM lParam; 
  ); 

hhk是当前钩子的句柄编程栈,编程栈由SetWindowsHookEx()函数返回。

NCode 是传递给钩子进程的事件代码。

wParam和lParam分别是传递给hook子进程的wParam值,其具体含义与hook类型有关。

钩子函数还可以通过直接返回TRUE来丢弃消息并阻止消息的传递。 否则,其他挂钩的应用程序将不会收到挂钩通知,并且可能会产生不正确的结果。

该钩子使用后需要用UnHookWindowsHookEx()卸载,否则会造成麻烦。 释放钩子比较简单,UnHookWindowsHookEx()只有一个参数。 函数原型如下:

UnHookWindowsHookEx
 (
 HHOOK hhk;
 );

如果成功,该函数返回 TRUE,否则返回 FALSE。

3、部分运行机制:

在Win16环境下,DLL的全局数据对于每个加载它的进程都是相同的; 在Win32环境中,情况发生了变化,DLL函数中的代码创建的任何对象(包括变量)都由调用它的线程或进程拥有。 当进程加载DLL时,操作系统自动将DLL地址映射到进程的私有空间,即进程的虚拟地址空间,同时还将DLL的全局数据复制一份到进程空间。 也就是说,每个进程拥有的同一个DLL的全局数据具有相同的名称,但其值不一定相同,并且它们之间互不干扰。

因此,如果要在Win32环境下的多个进程之间共享数据,就必须进行必要的设置。 访问同一个Dll的进程之间共享内存是通过内存映射文件技术实现的。 还可以将需要共享的数据分开,放在一个独立的数据段中,并将该段的属性设置为共享。 这些变量必须被赋予初始值,否则编译器会将没有初始值的变量放置在一个称为uninitialized的数据段中。

#pragma data_seg 预处理指令用于设置共享数据段。 例如:

#pragma data_seg("SharedDataName")
HHOOK hHook=NULL;
#pragma data_seg()

#pragma data_seg("SharedDataName") 和 #pragma data_seg() 之间的所有变量都将被访问 Dll 的所有进程看到和共享。

当进程隐式或显式调用动态库中的函数时,系统必须将动态库映射到进程的虚拟地址空间(以下简称“地址空间”)。 这使得 DLL 成为进程的一部分,作为该进程执行,并使用该进程的堆栈。

要创建全局钩子,我们需要使用DLL注入。 Hook的DLL工程主要代码如下:

#include  
 
#pragma data_seg("HookWnd") 
HHOOK   g_HookWnd   = NULL;  //钩子句柄 
HWND   g_DestWnd   = NULL;  //目的窗口句柄,就是截获的消息要发往什么窗口 
HINSTANCE g_hInst    = NULL; 
#pragma data_seg() 
 
#pragma comment( linker, "/section:HookWnd,RWS" ) 
 
__declspec(dllexport) BOOL SetHook(HWND hWnd); 
__declspec(dllexport) void DestroyHook(); 
 
#define WM_MYMESSAGE (WM_USER + 1) 
 
BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved) 
{ 
  g_hInst = hinstDll;//保存应用程序实例 
  return TRUE; 
} 
 
 
LRESULT CALLBACK MyWndProc(int nCode, WPARAM wParam, LPARAM lParam) 
{ 
  CWPSTRUCT *pCwp = reinterpret_cast(lParam); 
  if (pCwp->message == WM_SHOWWINDOW) 
  { 
    ::SendMessage(g_DestWnd, WM_MYMESSAGE, wParam, reinterpret_cast(pCwp->hwnd)); 
    return 0; 
  } 
  else 
    return CallNextHookEx(g_HookWnd, nCode, wParam, lParam); 
} 
 
BOOL SetHook(HWND hWnd) 
{ 
  if (NULL == hWnd) 
    return FALSE; 
   
  g_DestWnd = hWnd; 
 
  //第三个参数还可通过些方法获得:GetModuleHandle("HookTest.dll") 
  return (NULL != (g_HookWnd = ::SetWindowsHookEx(WH_CALLWNDPROC, MyWndProc, g_hInst, 0))); 
} 
 
void DestroyHook() 
{ 
  if (NULL != g_HookWnd)  
  { 
    UnhookWindowsHookEx(g_HookWnd); 
    g_DestWnd = NULL; 
  } 
}

4.系统钩子和线程钩子:

SetWindowsHookEx()函数的最后一个参数决定这个钩子是系统钩子还是线程钩子。

线程钩子用于监视指定线程的事件消息。 线程钩子通常位于当前线程或从当前线程派生的线程内。

系统挂钩监视来自系统中所有线程的事件消息。 由于系统钩子影响系统中的所有应用程序,因此钩子函数必须放置在单独的动态链接库(DLL)中。 系统自动将包含“钩子回调函数”的DLL映射到所有受钩子函数影响的进程的地址空间中,即将这个DLL注入到那些进程中。

一些注意事项:

(1)如果针对同一个事件(如鼠标消息)同时安装了线程钩子和系统钩子,系统会自动先调用线程钩子,然后调用系统钩子。

(2)对于同一个事件消息可以安装多个钩子处理进程,这些钩子处理进程形成钩子链。 当前钩子处理完成后,应该将钩子信息传递给下一个钩子函数。

(3) Hooks,尤其是系统Hooks,会消耗消息处理时间,降低系统性能。 仅在必要时安装挂钩,并在使用后立即卸载。

3. 挂钩式

每种类型的 Hook 都使应用程序能够监视不同类型的系统消息处理机制。 所有可用的 Hook 类型如下所述。

1. WH_CALLWNDPROC 和 WH_CALLWNDPROCRET 钩子

WH_CALLWNDPROC 和 WH_CALLWNDPROCRET 挂钩允许您监视发送到窗口过程的消息。 系统在消息发送到接收窗口过程之前调用WH_CALLWNDPROC Hook子例程,并在窗口过程处理完消息之后调用WH_CALLWNDPROCRET Hook子例程。

WH_CALLWNDPROCRET Hook 将指针传递给 CWPRETSTRUCT 结构,然后将其传递给 Hook 子例程。 CWPRETSTRUCT 结构包含处理该消息的窗口过程的返回值,以及与该消息关联的消息参数。

2.WH_CBT钩子

系统将在以下事件之前调用 WH_CBT Hook 子例程,其中包括:

1.激活、创建、销毁、最小化、最大化、移动、改变大小等窗口事件;

2、完整的系统使用说明;

3.来自系统消息队列的鼠标移动和键盘事件;

4.设置输入焦点事件;

5. 同步系统消息队列事件。

Hook 子例程的返回值决定系统是否允许或阻止其中一项操作。

3.WH_DEBUG钩子

在系统调用与系统中其他Hook关联的Hook子例程之前,系统会调用WH_DEBUG Hook子例程。 您可以使用此 Hook 来决定是否允许系统调用与其他 Hook 关联的 Hook 子例程。

4. WH_FOREGROUNDIDLE 钩子

当应用程序的前台线程空闲时,可以使用 WH_FOREGROUNDIDLE Hook 来执行低优先级任务。 当应用程序的前台线程即将空闲时,系统将调用WH_FOREGROUNDIDLE Hook子例程。

5. WH_GETMESSAGE 钩子

应用程序使用 WH_GETMESSAGE Hook 来监视从 GetMessage 或 PeekMessage 函数返回的消息。 您可以使用 WH_GETMESSAGE Hook 来监视鼠标和键盘输入,以及发送到消息队列的其他消息。

6. WH_JOURNALPLAYBACK 钩子

WH_JOURNALPLAYBACK Hook 使应用程序能够将消息插入到系统消息队列中。 您可以使用此 Hook 来回放使用 WH_JOURRNALRECORD Hook 记录的连续鼠标和键盘事件。 只要安装了WH_JOURNALPLAYBACK Hook,普通的鼠标和键盘事件就无效。 WH_JOURNALPLAYBACK Hook 是全局 Hook,不能像线程特定 Hook 一样使用。 WH_JOURNALPLAYBACK Hook 返回一个超时值,该值告诉系统在处理来自播放 Hook 的当前消息之前需要等待多长时间(以毫秒为单位)。 这使得 Hooks 可以控制实时事件的播放。 WH_JOURNALPLAYBACK 是系统范围的本地挂钩,它们不会注入任何行程地址空间。

7. WH_JOURNALRECORD 钩子

WH_JOURNALRECORD Hook 用于监视和记录输入事件。 通常,您可以使用此 Hook 记录连续的鼠标和键盘事件,然后使用 WH_JOURNALPLAYBACK Hook 回放它们。 WH_JOURNALRECORD Hook 是全局 Hook,不能像线程特定 Hook 一样使用。 WH_JOURNALRECORD 是系统范围的本地挂钩,它们不会注入任何行程地址空间。

8.WH_KEYBOARD挂钩

在应用程序中,WH_KEYBOARD Hook用于监视WM_KEYDOWN和WM_KEYUP消息,这些消息通过GetMessage或PeekMessage函数返回。 您可以使用此 Hook 来监视输入到消息队列中的键盘消息。

9. WH_KEYBOARD_LL 钩子

WH_KEYBOARD_LL Hook 监视输入到线程消息队列的键盘消息。

10.WH_MOUSE钩子

WH_MOUSE Hook 监视从 GetMessage 或 PeekMessage 函数返回的鼠标消息。 使用此 Hook 可以监视输入到消息队列的鼠标消息。

11. WH_MOUSE_LL 钩子

WH_MOUSE_LL Hook 监视输入到线程消息队列的鼠标消息。

12. WH_MSGFILTER 和 WH_SYSMSGFILTER 钩子

WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks 允许我们监视菜单、滚动条、消息框、对话框消息并发现用户使用 ALT+TAB 或 ALT+ESC 组合键来切换窗口。 WH_MSGFILTER Hook 只能监视传递到菜单、滚动条、消息框的消息以及传递到由安装了 Hook 子例程的应用程序创建的对话框的消息。 WH_SYSMSGFILTER Hook 监视所有应用程序消息。

WH_MSGFILTER 和 WH_SYSMSGFILTER Hook 允许我们在模式循环期间过滤消息,这相当于在主消息循环中过滤消息。

WH_MSGFILTER Hook可以通过调用CallMsgFilter函数直接调用。 通过使用此函数,应用程序可以在模式循环期间使用与主消息循环中相同的代码来过滤消息。

13.WH_SHELL钩子

Shell 应用程序可以使用 WH_SHELL Hook 来接收重要通知。 当 shell 应用程序处于活动状态并且顶层窗口被创建或销毁时,系统将调用 WH_SHELL Hook 子例程。

WH_SHELL一共有5种情况:

1. 只要一个顶级的、无主的窗口被创建、激活或销毁;

2、当任务栏需要重绘按钮时;

3、当系统需要在任务栏上显示程序的最小化形式时;

4.当前键盘布局状态发生变化时;

5、当用户按Ctrl+Esc执行任务管理器(或同级程序)时。

按照惯例,没有 shell 应用程序会接收 WH_SHELL 消息。 因此,在应用程序可以接收WH_SHELL消息之前,应用程序必须调用SystemParametersInfo函数来注册自己。

以上就是本文的全部内容。 希望对大家的学习有所帮助,也希望大家支持我们。

本文标题:浅谈c++ hooks的使用

相关推荐

4万多吨豪华游轮遇险 竟是因为这个原因……

(观察者网讯)4.7万吨豪华游轮搁浅,竟是因为油量太低?据观察者网此前报道,挪威游轮“维京天空”号上周六(23日)在挪威近海发生引擎故障搁浅。船上载有1300多人,其中28人受伤住院。经过数天的调...

“菜鸟黑客”必用兵器之“渗透测试篇二”

"菜鸟黑客"必用兵器之"渗透测试篇二"上篇文章主要针对伙伴们对"渗透测试"应该如何学习?"渗透测试"的基本流程?本篇文章继续上次的分享,接着介绍一下黑客们常用的渗透测试工具有哪些?以及用实验环境让大家...

科幻春晚丨《震动羽翼说“Hello”》两万年星间飞行,探测器对地球的最终告白

作者|藤井太洋译者|祝力新【编者按】2021年科幻春晚的最后一篇小说,来自大家喜爱的日本科幻作家藤井太洋。小说将视角放在一颗太空探测器上,延续了他一贯的浪漫风格。...

麦子陪你做作业(二):KEGG通路数据库的正确打开姿势

作者:麦子KEGG是通路数据库中最庞大的,涵盖基因组网络信息,主要注释基因的功能和调控关系。当我们选到了合适的候选分子,单变量研究也已做完,接着研究机制的时便可使用到它。你需要了解你的分子目前已有哪些...

知存科技王绍迪:突破存储墙瓶颈,详解存算一体架构优势

智东西(公众号:zhidxcom)编辑|韦世玮智东西6月5日消息,近日,在落幕不久的GTIC2021嵌入式AI创新峰会上,知存科技CEO王绍迪博士以《存算一体AI芯片:AIoT设备的算力新选择》...

每日新闻播报(September 14)_每日新闻播报英文

AnOscarstatuestandscoveredwithplasticduringpreparationsleadinguptothe87thAcademyAward...

香港新巴城巴开放实时到站数据 供科技界研发使用

中新网3月22日电据香港《明报》报道,香港特区政府致力推动智慧城市,鼓励公私营机构开放数据,以便科技界研发使用。香港运输署21日与新巴及城巴(两巴)公司签署谅解备忘录,两巴将于2019年第3季度,开...

5款不容错过的APP: Red Bull Alert,Flipagram,WifiMapper

本周有不少非常出色的app推出,鸵鸟电台做了一个小合集。亮相本周榜单的有WifiMapper's安卓版的app,其中包含了RedBull的一款新型闹钟,还有一款可爱的怪物主题益智游戏。一起来看看我...

Qt动画效果展示_qt显示图片

今天在这篇博文中,主要实践Qt动画,做一个实例来讲解Qt动画使用,其界面如下图所示(由于没有录制为gif动画图片,所以请各位下载查看效果):该程序使用应用程序单窗口,主窗口继承于QMainWindow...

如何从0到1设计实现一门自己的脚本语言

作者:dong...

三年级语文上册 仿写句子 需要的直接下载打印吧

描写秋天的好句好段1.秋天来了,山野变成了美丽的图画。苹果露出红红的脸庞,梨树挂起金黄的灯笼,高粱举起了燃烧的火把。大雁在天空一会儿写“人”字,一会儿写“一”字。2.花园里,菊花争奇斗艳,红的似火,粉...

C++|那些一看就很简洁、优雅、经典的小代码段

目录0等概率随机洗牌:1大小写转换2字符串复制...

二年级上册语文必考句子仿写,家长打印,孩子照着练

二年级上册语文必考句子仿写,家长打印,孩子照着练。具体如下:...

一年级语文上 句子专项练习(可打印)

...

亲自上阵!C++ 大佬深度“剧透”:C++26 将如何在代码生成上对抗 Rust?

...

取消回复欢迎 发表评论: