HOOK函数(一)——进程内HOOK
什么是HOOK呢?其实很简单,HOOK就是对Windows消息进行拦截检查处理的一个函数。在Windows的消息机制中,当用户产生消息时,应用程序通过调用GetMessage函数取出消息,然后把消息放入到消息队列,再使用消息调度函数DispatchMessage函数讲消息调度给系统,Windows系统会调用创建窗口类时制定的窗口过程中进行次消息的处理。而HOOK函数的话,就可以对此消息进行拦截。经过此HOOK函数的处理后,再决定是屏蔽掉此消息,还是继续往下传递。至于为什么叫“钩子”,可能就是因为它可以像钩子一样把消息给钩住。话说四川话里面的“钩子”却是屁股的意思...哈哈,四川的同学读钩子肯定多了几份趣味
钩子函数的实现分为以下步骤:
1 安装钩子函数
安装钩子函数是通过函数SetWindowHookEx来实现的:
HHOOK WINAPI SetWindowsHookExW(__in int idHook, __in HOOKPROC lpfn,__in_opt HINSTANCE hmod, __in DWORD dwThreadId);
此函数的第一个参数idHook指定将要安装的钩子过程的类型,如果我们安装键盘钩子,则设为WH_KEYBOARD,鼠标钩子则设为WH_MOUSE。 lpfn指向了相应的钩子函数,如果dwThreadId为0,或者指定了一个其他进程创建的线程之标识符,则lpfn必须指向一个位于某动态链接库中的钩子函数。如果为进程外钩子,hMod指向的是钩子函数所在的DLL的句柄,如果为进程内钩子,则设为NULL。dwThreadId指定与钩子过程相关的线程表示,为0表示与所有线程相关。函数成功返回所安装的钩子函数的句柄,否则返回NULL。PS:最后安装的钩子函数总是排在钩子链的最前面。
2 添加全局变量
HHOOK g_hMouse = NULL;
HHOOK g_hKeyboard = NULL;
HWND g_hWnd = NULL;
全局句柄g_hMouse、g_hKeyboard分别代表我们所要安装的鼠标钩子和键盘钩子过程的句柄,g_hWnd用来保存当前的窗口句柄。
3 声明钩子函数
如果想要监视鼠标消息,需要定义相应的鼠标钩子过程。同样,要监视键盘消息,也需要定义相应的键盘钩子过程。该钩子函数的形式必须如下:
LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam);
在当前钩子函数中处理完信息后,如果想把信息继续传递给下一个钩子函数,可以调用CallNextHookEx函数来实现:
LRESULT
WINAPI CallNextHookEx( __in_opt HHOOK hhk, __in int nCode, __in WPARAM wParam, __in LPARAM lParam
CallNextHookEx函数的第一个参数是钩子的句柄,就是我们调用SetWindowHookEx函数返回的句柄,其他几个参数和HookProc中是一样的。
4 卸载钩子函数
当我们不需要再使用钩子函数的时候,可以将其卸载,调用函数:
BOOL WINAPI UnhookWindowsHookEx( __in HHOOK hhk);
函数的唯一参数便为钩子函数的句柄。
说一千道一万,不如一个程序来的实在。下面便是一个实现进程内钩子函数的MFC例子。步骤如下:
1 新建一个名字CInnerHookDlg的MFC工程。
2 在CInnerHookDlgDlg.cpp中添加钩子的全局变量和当前句柄
HHOOK g_hMouse = NULL;
HHOOK g_hKeyboard = NULL;
HWND g_hWnd = NULL;
3 然后再分别实现键盘和鼠标钩子函数,我们在键盘钩子函数中显示出当前按下去的键盘。而在鼠标钩子函数中,当我们双击右键时候,会显示出对话框。
//鼠标钩子函数
LRESULT CALLBACK MouseProc( int nCode, WPARAM wParam, LPARAM lParam )
{
...
} //键盘钩子函数
LRESULT CALLBACK KeyBoardProc( int nCode, WPARAM wParam, LPARAM lParam )
{
...
}
4 在CCInnerHookDlgDlg的OnInitDialog()中设置钩子,添加如下代码
//设置鼠标钩子
g_hMouse = SetWindowsHookEx(WH_MOUSE, MouseProc, NULL,GetCurrentThreadId()); //设置键盘钩子
g_hKeyboard = SetWindowsHookEx(WH_KEYBOARD, KeyBoardProc, NULL, GetCurrentThreadId()); //获取当前句柄
g_hWnd = m_hWnd;
5 最后在CCInnerHookDlgDlg的OnSysCommand()中卸载钩子,添加如下代码:
UnhookWindowsHookEx(g_hMouse);
UnhookWindowsHookEx(g_hKeyboard);
下面是所有的代码啦!
// CInnerHookDlgDlg.cpp : 实现文件
// #include "stdafx.h"
#include "CInnerHookDlg.h"
#include "CInnerHookDlgDlg.h" #ifdef _DEBUG
#define new DEBUG_NEW
#endif HHOOK g_hMouse = NULL;
HHOOK g_hKeyboard = NULL;
HWND g_hWnd = NULL; // 用于应用程序“关于”菜单项的 CAboutDlg 对话框 class CAboutDlg : public CDialog
{
public:
CAboutDlg(); // 对话框数据
enum { IDD = IDD_ABOUTBOX }; protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现
protected:
DECLARE_MESSAGE_MAP()
}; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
} void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
} BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP() // CCInnerHookDlgDlg 对话框
CCInnerHookDlgDlg::CCInnerHookDlgDlg(CWnd* pParent /*=NULL*/)
: CDialog(CCInnerHookDlgDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
} void CCInnerHookDlgDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
} BEGIN_MESSAGE_MAP(CCInnerHookDlgDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
END_MESSAGE_MAP() //鼠标钩子函数
LRESULT CALLBACK MouseProc( int nCode, WPARAM wParam, LPARAM lParam )
{
LPMOUSEHOOKSTRUCT pMouseHook = (MOUSEHOOKSTRUCT*)(lParam); if (nCode >= 0)
{
//双击右键弹出当前窗口的窗口名
if (wParam == WM_RBUTTONDBLCLK)
{
HWND hWnd = pMouseHook->hwnd; //鼠标所在的窗口
HWND hParent; //获取顶层窗口
while(hWnd != NULL)
{
hParent = GetParent(hWnd);
if (hParent == NULL)
break;
hWnd = hParent;
} if (hWnd != NULL)
{
//得到窗口名
TCHAR strDlgName[MAX_PATH] = {0};
GetWindowText(hWnd,strDlgName, MAX_PATH);
AfxMessageBox( strDlgName );
}
}
} return CallNextHookEx(g_hMouse,nCode, wParam, lParam);
} //键盘钩子函数
LRESULT CALLBACK KeyBoardProc( int nCode, WPARAM wParam, LPARAM lParam )
{
LRESULT lReturnValue;
lReturnValue = CallNextHookEx(g_hKeyboard, nCode, wParam, lParam); //键盘按键是否已经松动
if ( (lParam & 0x80000000) && (HC_ACTION == nCode))
{
char c = (char) lParam;
CString strText(_T("按下了键"));
strText += c;
AfxMessageBox(strText); //显示当前的按键
} //如果按下F4,则退出程序
if (wParam == VK_F4)
{
SendMessage(g_hWnd, WM_CLOSE,0,0);
} return lReturnValue;
} // CCInnerHookDlgDlg 消息处理程序 BOOL CCInnerHookDlgDlg::OnInitDialog()
{
CDialog::OnInitDialog(); // 将“关于...”菜单项添加到系统菜单中。 // IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
} // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码 //设置鼠标钩子
g_hMouse = SetWindowsHookEx(WH_MOUSE, MouseProc, NULL,GetCurrentThreadId()); //设置键盘钩子
g_hKeyboard = SetWindowsHookEx(WH_KEYBOARD, KeyBoardProc, NULL, GetCurrentThreadId()); //获取当前句柄
g_hWnd = m_hWnd; return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
void CCInnerHookDlgDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
} UnhookWindowsHookEx(g_hMouse);
UnhookWindowsHookEx(g_hKeyboard);
} // 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。 void CCInnerHookDlgDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), ); // 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + ) / ;
int y = (rect.Height() - cyIcon + ) / ; // 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
} //当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CCInnerHookDlgDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
HOOK函数(一)——进程内HOOK的更多相关文章
- 钩子编程(HOOK) 安装进程内键盘钩子 (1)
摘要:钩子能够监视系统或进程中的各种事件消息.截获发往目标窗体的消息并进行处理.这样,我们就能够在系统中安装自己定义的钩子,监视系统中特定事件的发生.完毕特定的功能,比方截获键盘.鼠标的输入.屏幕取词 ...
- Linux进程内消息总线设计
文章目录 Windows平台进程内消息总线 如果没有消息总线,会产生什么问题 死循环包含关系 高耦合.低内聚 消息总线 结构图 原理 生产者与总线的关系 总线与消费者的关系 Linux进程内消息总线设 ...
- [Hook] 免root,自己进程内,startActivity hook的几种姿势
首先关于startActivity 我们平时会经常使用到 在activity内 直接startActivity(intent) 其实这里还有一种start方式 我们可能没怎么用过 getApplica ...
- ZeroMQ接口函数之 :zmq_inproc – ØMQ 本地进程内(线程间)传输方式
ZeroMQ API 目录 :http://www.cnblogs.com/fengbohello/p/4230135.html ——————————————————————————————————— ...
- 利用Objective-C运行时hook函数的三种方法
版权声明:转载请注明出处:http://blog.csdn.net/hursing 方法一,hook已有公开头文件的类: 首先写一个Utility函数: #import <objc/runtim ...
- [PyTorch 学习笔记] 5.2 Hook 函数与 CAM 算法
本章代码: https://github.com/zhangxiann/PyTorch_Practice/blob/master/lesson5/hook_fmap_vis.py https://gi ...
- HOOK API (一)——HOOK基础+一个鼠标钩子实例
HOOK API (一)——HOOK基础+一个鼠标钩子实例 0x00 起因 最近在做毕业设计,有一个功能是需要实现对剪切板的监控和进程的防终止保护.原本想从内核层实现,但没有头绪.最后决定从调用层入手 ...
- HOOK API(三)—— HOOK 所有程序的 MessageBox
HOOK API(三) —— HOOK 所有程序的 MessageBox 0x00 前言 本实例要实现HOOK MessageBox,包括MessageBoxA和MessageBoxW,其实现细节与H ...
- HOOK API(二)—— HOOK自己程序的 MessageBox
HOOK API(二) —— HOOK自己程序的 MessageBox 0x00 前言 以下将给出一个简单的例子,作为HOOK API的入门.这里是HOOK 自己程序的MessageBox,即将自己程 ...
随机推荐
- Datatable转换成List实体对象列表 几个实例
一, /// <summary> /// 将Datatable转换为List集合 /// </summary> /// <typeparam name="T&q ...
- 【原】1.1RDD源码解读(二)
(6)transformation 操作,通过外在的不同RDD表现形式来达到内部数据的处理过程.这类操作并不会触发作业的执行,也常被称为lazy操作. 大部分操作会生成并返回一个新的RDD,例sort ...
- mongodb基础系列——数据库查询数据返回前台JSP(一)
经过一段时间停顿,终于提笔来重新整理mongodb基础系列博客了. 同时也很抱歉,由于各种原因,没有及时整理出,今天做了一个demo,来演示,mongodb数据库查询的数据在JSP显示问题. 做了一个 ...
- (一)Redis初学教程之安装篇
1.下载windows下Redis服务安装程序(有32位的和64位的,识操作系统安装) 下载地址:https://github.com/dmajkic/redis/downloads 2.安装教程(详 ...
- IOS开发之tableview只选中一行
场景:一个弹出层,包含一个Tableview,每一行为一个选择条件,且只能选择一个.选中后文体有颜色变化,后面还会有对勾.选择另一个后,前一个恢复成普通状态. 示例代码: -(void)tableVi ...
- windows 文件名太长无法删除的解决方法
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...
- powershell创建并加载配置文件
$pshome :powershell的主目录 $profile :显示 Windows PowerShell 配置文件的路径 test-path $profile :确定是否已经在系统上创建了 Wi ...
- Discuz建站教程:本地安装discuz网站
网站建目前都很简单,建站容易,管理难,网站做大优化更难.本人有建站经验,目前给大家分享一下如何建站,当然,目前使用的是本地建站,因为非本地建站需要购买域名和网站空间,当然,朋友们想真正建站的,对于一些 ...
- qt学习笔记(五) QGraphicsPixmapItem与QGraphicsScene的编程实例 图标拖动渐变效果
应大家的要求,还是把完整的project文件贴出来,大家省点事:http://www.kuaipan.cn/file/id_48923272389086450.htm 先看看执行效果,我用的群创7寸屏 ...
- Sql Server2005 Transact-SQL 窗口函数(OVER)
1.简介: SQL Server 2005中的窗口函数帮助你迅速查看不同级别的聚合,通过它可以非常方便地累计总数.移动平均值.以及执行其它计算.窗口函数功能非常强大,使用起来也十分容易.可以使用这个技 ...