钩子(hook)编程

一、钩子介绍

1.1钩子的实现机制

钩子英文名叫Hook,是一种截获windows系统中某应用程序或者所有进程的消息的一种技术。下图是windows应用程序传递消息的过程:

如在键盘中按下一键,操作系统将收到键按下消息,把消息放入消息队列,然后消息队列对消息进行派发,发给相应的应用程序,经过应用程序处理后发给操作系统,操作系统再调用相应的应用程序的创建的窗口过程。

我们可能通过钩子截获这些消息,让消息不再往下传递,或者说截获到感兴趣的消息后做点什么。

1.2钩子分类与实现

钩子分进程内钩子与全局钩子,进程内钩子是截取某一指定的进程的消息,直接在进程内创建与消除钩子即可。全局钩子是截取所有进程的消息,得以动态库的方式实现。

实现一个钩子一般有三个步骤,首先创建钩子,有专门的API:SetWindowsHookEx,创建成功后,消息将会传给SetWindowsHookEx的形参指定的处理函数。然后在消息处理函数中分析收到的消息,做相应的处理。最后,钩子用完后,用API(UnhookWindowsHookEx)消毁钩子。

二、创建钩子

2.1钩子的创建

SetWindowsHookEx安装一个应用程序定义的钩子过程,并把创建的钩子过程放在钩子链中,可以安装多个钩子,多个钩子就形成了钩子链,最后安装的钩子总是在最前面。创建钩子的函数如下:

创建钩子,返回钩子句柄,否则返回NULL。形参定义如下:

idHook:钩子过程类型,如:鼠标消息钩子、键盘消息钩子、消息队列监控钩子等等。具体取值如下:

lpfn:相应的钩子过程,也就是一个处理消息的回调函数名而已,如果参数dwThreadId为0,或者dwThreadId指向的是其他进程创建的线程标志符,那么lpfn必须指向一个位于某一动态库中的钩子过程。其他情况下,lpfn可以指向本进程内的某一钩子过程。

hMod:指向钩子过程所在的应用程序实例句柄,如:钩子过程所在的DLL的句柄。如果dwThreadId指定的线程是由当前进程创建,并且钩子过程在当时进程中,那么hMod必须设置为NULL。

dwThreadId:指定与钩子相关的线程标志。如果为0,那么钩子将与桌面上运行的所有线程相关。

钩子过程可以与特定线程相关也可以与所有线程相关,取决于dwThreadId的取值。

2.2钩子过程分析

钩子过程,是处理钩子截取的消息的一个回调函数,即SetWindowsHookEx函数中的第二个形参。格式如下:

LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam);形参含义并不是都一样的,不同钩子过程形参表示的意义不一样,我们以鼠标钩子为例说明,参数含义如下:

nCode:指示钩子过程如何处理当前的消息,如果钩子是鼠标消息钩子的话,有两种含义:

wParam:指示鼠标消息标志。

lParam:指向MOUSEHOOKSTRUCT结构体指针。以下是MOUSEHOOKSTRUCT结构体,包含着鼠标消息。

typedef struct {

POINT pt;//光标包含x,y,是屏幕坐标。

HWND hwnd;//目标窗口句柄

UINT wHitTestCode;

ULONG_PTR dwExtraInfo;

} MOUSEHOOKSTRUCT, *PMOUSEHOOKSTRUCT;

通过这三个参数,可对消息进行分析处理。

其他钩子过程参数的含义可以通过MSDN文档查看详细说明,如KeyboardProc、MessageProc等。

2.3消毁钩子

BOOL UnhookWindowsHookEx(HHOOK hhk);此API的功能是把SetWindowsHookEx创建的钩子从钩子链中移除。形参是SetWindowsHookEx返回的钩子句柄。

三、进程内钩子

进程内钩子一般是为了截获当前应用程序的消息,一般会可以在应用程序初始化的时候创建,当然也可以在自己想创建的时候创建,只是创建之前的消息无法截获。

3.1鼠标钩子过程函数

以下为鼠标钩子过程代码:

HWND            g_DestWndH = NULL;

HHOOK          g_hHookDm = NULL;

LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)

{            //此区间内的消息都是鼠标消息

if (WM_MOUSEMOVE <= wParam && wParam <= WM_MOUSEWHEEL) {

if(g_DestWndH != NULL) {

::SendMessage(g_DestWndH, wParam, wParam, lParam);

//鼠标钩子,lParam是MOUSEHOOKSTRUCT结构指针

PMOUSEHOOKSTRUCT lpMsg = (PMOUSEHOOKSTRUCT)lParam;

lpMsg->hwnd = NULL;    //把目的窗口置NULL

lpMsg->dwExtraInfo = 0L;

lpMsg->pt = CPoint(0, 0);

lpMsg->wHitTestCode = 0L;

}

return 1;//如果想让此消息不再往下传,返回非0

}

else//不感兴趣的消息往下传

return ::CallNextHookEx(g_hHookDm, nCode, wParam, lParam);

}

3.2创建钩子过程

以下为创建钩子过程的代码:

if(g_hHookDm == NULL) {

//如果dwThreadId指定的线程是由当前进程创建,并且钩子过程在当时进程中,那么hMod必须设置为NULL。

g_hHookDm = ::SetWindowsHookEx(WH_MOUSE,MouseProc, NULL, GetCurrentThreadId());

if (NULL != g_hHookDm)//创建成功

g_DestWndH = m_hWnd;//保存目的窗口句柄

}

3.3消毁进程内钩子

把钩子过程从钩子链中拿下来,调用一个API即可:

if (NULL != g_hHookDm) {

UnhookWindowsHookEx(g_hHookDm);

g_DestWndH = NULL;

}

到此进程内钩子的创建与执行到消毁整个过程都完成了。

四、全局钩子

4.1键盘钩子过程函数

以上进程内钩子只是截获本进程的消息,如果要截获桌面全部线程的消息则要通过全局钩子。全局钩子必须在DLL上实现,钩子过程不能在本进程代码中实现,所以先得写一个DLL,代码见”HookDll”,以键盘钩子为例:

nCode:与鼠标钩子是一样的含义,有HC_ACTION与HC_NOREMOVE两个值。

Param:代表具体的虚拟键,如:VK_TAB、VK_RETURN分别代表Tab键、Enter键按下,其他虚拟键消息可查看MSDN的”virtual-key code”.

lParam:存放一些扩展信息,如:按键重复数据、29位表示ALT键的按下情况。

参数的具体含义可查MSDN。关于组合键的问题,参看以下键盘钩子函数的示例代码:

HHOOK g_HookKeyBoard = NULL;

LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)

{

//wParam表示虚拟键,lparam第29位表示ALT键按下状态(按下为1,否则为0),

//GetKeyState可以获得对应键的状态,所以收下表示Control + ALT + Z组合键按下

if ('Z' == wParam && GetKeyState(VK_CONTROL) < 0 && (lParam >> 29 & 1)) {

::SendMessage(g_DestWnd, WM_KEYDOWN, wParam, lParam);

return 1;

}

else

return CallNextHookEx(g_HookKeyBoard, nCode, wParam, lParam);

}

注:全局钩子在某版本的系统中,调试状态下,如果调试程序窗口没有获得焦点,在设置断点的方不会停留,如果获得焦点才会停留,也就是说,在调试状态下,不属于本进程的消息断点处不会停留。

4.2创建全局钩子接口

创建全局钩子的方法在DLL中,所以得引出一个接口,代码如下:

BOOL SetHook(HWND hWnd){

if (NULL == hWnd)

return FALSE;

g_DestWnd = hWnd;

//第三个参数可通过些方法获得:GetModuleHandle("MouseHook.dll")

return (NULL != (g_HookKeyBoard = ::SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, g_hInst, 0)));

}

其形参是一窗口句柄,指示截获的兴趣消息需传向的窗口的句柄,其中MetWindowsHookE的第三个参数是DLL的应用程序实例句柄,可通过DllMain的传入参数得到,亦可通过GetModuleHandle方法得到,第四个参数必须为0,才能获得全部桌面线程的消息。成功将返回TRUE否则FALSE。

4.3消毁全局钩子接口

在DLL中也得引出一接口消毁全局钩子,代码如下:

void DestroyHook(){

if (NULL != g_HookKeyBoard) {

UnhookWindowsHookEx(g_HookKeyBoard);

g_DestWnd = NULL;

}

}

4.4使用DLL创建全局钩子

以下为创建与消毁全局钩子的实现,代码如下:

HINSTANCE hIst = NULL;

void CHookTestDlg::OnCreateDllHook()

{

hIst = ::LoadLibrary("..\\HookDll\\Debug\\HookDll.dll");

if (NULL != hIst) {

typedef BOOL (*pFunSetHook)(HWND);

pFunSetHook pSetHook = (pFunSetHook)GetProcAddress(hIst, "SetHook");

if (NULL != pSetHook) {

if(pSetHook(m_hWnd))

AfxMessageBox("创建全局钩子成功...");

}

}

}

void CHookTestDlg::OnDestroyDllHook()

{

if (NULL != hIst) {

typedef void (*pFunDestroyHook)();

pFunDestroyHook pDestryHook = (pFunDestroyHook)GetProcAddress(hIst, "DestroyHook");

if (NULL != pDestryHook) {

pDestryHook();

::FreeLibrary(hIst);

hIst = NULL;

}

}

}

配套源码链接:http://download.csdn.net/detail/mingojiang/4526390

转载请注明出处:http://blog.csdn.net/mingojiang

java hook全局钩子_钩子(hook)相关推荐

  1. java正则全局匹配_正则表达式全局匹配模式(g修饰符)

    正则表达式g修饰符: g修饰符用语规定正则表达式执行全局匹配,也就是在找到第一个匹配之后仍然会继续查找. 语法结构: 构造函数方式: new RegExp("regexp",&qu ...

  2. java hook全局钩子,牛逼骚操作:Java 虚拟机关闭钩子(Shutdown Hook)!

    码农每日一题 长按关注,工作日每天分享一个技术知识点. Shutdown Hooks 是一种特殊的结构,它允许开发人员插入 JVM 关闭时执行的一段代码. 用途 Application 正常退出(所有 ...

  3. 日志钩子(JournalRecord Hook)的使用

    -- 钩子是WINDOWS中消息处理机制的一个要点,通过安装各种钩子,应用程序能够设置相应的子例程来监视系统里的消息传递以及在这些消息到达目标窗口程序之前处理它们.钩子的种类很多,每种钩子可以截获并处 ...

  4. 钩子运行机制HOOK

    转载 javanetc 代码频道 :http://www.javanetc.com/vc/vc_1749.html 基本概念 钩子(Hook)是Windows消息处理机制的一个平台,应用程序可以在上面 ...

  5. 守护线程(Daemon)、钩子线程(Hook)简述

    1. 简述 守护线程 守护线程在主线程退出时候会随主线程一起结束,而不会阻塞主线程的退出 钩子线程 钩子线程可以在*JVM正常退出*的时候自动触发 2. 代码演示 public static void ...

  6. JavaScript中的钩子(钩子机制\钩子函数\hook)是什么?

    我的博客https://www.ideaopen.cn/ 首先,看到我们的标题: JavaScript中的钩子(钩子机制\钩子函数\hook) 是什么? 我们前端的JavaScript中,经常提到钩子 ...

  7. 使用钩子函数[3] - 建立一个全局的鼠标钩子

    分两步: 一.建立 DLL, 并在 DLL 实现钩子的设置.释放和钩子函数; 二.再建一个工程调用测试. 第一步: 做 DLL 先建立一个 DLL 工程, 自动初始的代码如下(去掉注释了): libr ...

  8. Java中的JVM关闭钩子

    java面试题网站:www.javaoffers.com Java中的JVM关闭钩子 (翻译篇)关机钩子 也叫 关闭钩子 关机钩子是一种特殊的构造,允许开发人员插入一段代码,以便在JVM关闭时执行.当 ...

  9. C/C++ HOOK 全局 API

    全局 Hook 不一定需要用到 Dll ,比如全局的鼠标钩子.键盘钩子都是不需要 Dll 的,但是要钩住 API,就需要 Dll 的协助了,下面直接放上 Dll 的代码:(注意这里使用的是 MFC D ...

最新文章

  1. 多屏互动电脑版_MAXHUB无线双频同屏器HDMI连接投影仪手机电视机笔记本电脑投屏器多屏互动 MAXHUB传屏盒子WB01标配2个无线传屏...
  2. 如何破解天翼HG260光纤猫【转】
  3. java中list排序
  4. C++ Opengl 球形环境映射源码
  5. xmpp 与服务器连接并身份验证成功
  6. vmware配置centos7网络
  7. python与云计算的关系_python map reduce与云计算map/reduce之间的关系?
  8. 【codevs1226】倒水问题,BFS练习
  9. matlab条形图颜色矩阵,matlab中的条形图开关颜色
  10. webpack对模块查找的优化
  11. passwd命令修改密码_Linux passwd命令–更改用户密码
  12. 【推荐系统】那些年, 引用量超1000的经典推荐系统论文
  13. 用python写个类似浏览器的下载器,超简单的
  14. 条码标签制作软件导入数据库(TXT)批量打印条码
  15. html中选择器的优先级别是,CSS优先级之计算选择器的特殊性( Selector’s specificity )...
  16. 秦皇岛公积金计算 Python
  17. 抢票 | AI未来说学术论坛第11期 信息检索与知识图谱专场
  18. 利用随机森林进行特征选择
  19. 基于OpenCV的视频场景切割神器
  20. 初识JAVA及JAVA基本数据类型介绍!

热门文章

  1. 材料专业未来比较好的发展方向是什么
  2. 硬件太差不要慌 做时间的朋友
  3. STM32——看门狗
  4. String.valueOf() 方法的使用
  5. 【面试】Spring MVC面试题
  6. javascript 实现本地存储
  7. 网 络 工 程 师 之 独 孤 九 剑
  8. 《JSP程序设计》手机销售网后台设计方案1
  9. RIP的概念与技术指标
  10. 图形学 - 法线矩阵