为什么全局钩子必须写到dll里面?

简介

通过钩子技术(HOOK)可以把一段代码插入到当前线程或插入到桌面上的所有其他线程。其中插入到当前线程的钩子叫局部钩子,插入到桌面上所有线程的钩子叫全局钩子。
全局钩子之所以要位于动态链接库中,是因为所有的GUI线程要想调钩子函数就需要把钩子的dll模块加载到自己的内存空间。

Windows子系统

Windows子系统进程(csrss.exe)是桌面操作系统的核心进程,所有打开的窗口都属于该进程的管辖范围,每个窗口都是Windows子系统中的对象,由win32k.sys来管理的内核对象,没错就是c++或面向对象编程的灵魂“万物万事皆对象”的那个对象。下图的箭头就是指向我当前打开的写文章的窗口,00070E90是窗口的句柄。
在这里插入图片描述

下图是windows键鼠事件的消息流,键鼠消息通过RIT线程放到输入消息队列,最后到GUI线程进行处理。Windows子系统对每个GUI线程维护了一个钩子数组,我们用户模式的钩子函数入口会被放到这个数组中。也部署钩子就是我们注册了回调函数,供系统内核调用。
在这里插入图片描述

下图为内核触发钩子函数,由内核态切换到用户态执行用户模式下钩子函数的执行过程。
在这里插入图片描述

举例说明系统这样设计的原因

SetWindowsHookExA函数的第四个参数为0时,表示“lpfn对应的钩子程序”与所有桌面线程都关联,
比如某流氓软件PP.exe写了钩子函数HOOK_PassWord(),当我们运行微信.exe输入密码时,HOOK_PassWord()要被成功执行,系统就得把函数实现加载到内存中去,如果钩子函数写在PP.exe难不成系统要再把PP.exe再加载一遍到内存中么? 既费内存,又引入了风险。DLL的优势就是模块化,随用随加载,只不过被注册回调之后被系统自动调用了,不必大惊小怪。

HHOOK SetWindowsHookExA(
  [in] int       idHook,
  [in] HOOKPROC  lpfn,//钩子程序
  [in] HINSTANCE hmod,
  [in] DWORD     dwThreadId//线程ID
);

版权声明:本文为qq_25231249原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。