HOOK函数(一)——进程内HOOK

时间:2022-09-25 14:04:08

  什么是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的更多相关文章

  1. 钩子编程(HOOK) 安装进程内键盘钩子 &lpar;1&rpar;

    摘要:钩子能够监视系统或进程中的各种事件消息.截获发往目标窗体的消息并进行处理.这样,我们就能够在系统中安装自己定义的钩子,监视系统中特定事件的发生.完毕特定的功能,比方截获键盘.鼠标的输入.屏幕取词 ...

  2. Linux进程内消息总线设计

    文章目录 Windows平台进程内消息总线 如果没有消息总线,会产生什么问题 死循环包含关系 高耦合.低内聚 消息总线 结构图 原理 生产者与总线的关系 总线与消费者的关系 Linux进程内消息总线设 ...

  3. &lbrack;Hook&rsqb; 免root,自己进程内,startActivity hook的几种姿势

    首先关于startActivity 我们平时会经常使用到 在activity内 直接startActivity(intent) 其实这里还有一种start方式 我们可能没怎么用过 getApplica ...

  4. ZeroMQ接口函数之 :zmq&lowbar;inproc – &&num;216&semi;MQ 本地进程内(线程间)传输方式

    ZeroMQ API 目录 :http://www.cnblogs.com/fengbohello/p/4230135.html ——————————————————————————————————— ...

  5. 利用Objective-C运行时hook函数的三种方法

    版权声明:转载请注明出处:http://blog.csdn.net/hursing 方法一,hook已有公开头文件的类: 首先写一个Utility函数: #import <objc/runtim ...

  6. &lbrack;PyTorch 学习笔记&rsqb; 5&period;2 Hook 函数与 CAM 算法

    本章代码: https://github.com/zhangxiann/PyTorch_Practice/blob/master/lesson5/hook_fmap_vis.py https://gi ...

  7. HOOK API (一)——HOOK基础&plus;一个鼠标钩子实例

    HOOK API (一)——HOOK基础+一个鼠标钩子实例 0x00 起因 最近在做毕业设计,有一个功能是需要实现对剪切板的监控和进程的防终止保护.原本想从内核层实现,但没有头绪.最后决定从调用层入手 ...

  8. HOOK API(三)—— HOOK 所有程序的 MessageBox

    HOOK API(三) —— HOOK 所有程序的 MessageBox 0x00 前言 本实例要实现HOOK MessageBox,包括MessageBoxA和MessageBoxW,其实现细节与H ...

  9. HOOK API(二)—— HOOK自己程序的 MessageBox

    HOOK API(二) —— HOOK自己程序的 MessageBox 0x00 前言 以下将给出一个简单的例子,作为HOOK API的入门.这里是HOOK 自己程序的MessageBox,即将自己程 ...

随机推荐

  1. nodeJS 简单的模块。

    nodeJS是的模块流程: 第一步:创建模块,如:student.js 第二步:导出模块,如:exports.add = function(){} 第三步:加载模块,如:var student = r ...

  2. 描述Linux shell中单引号,双引号及不加引号的简单区别(计时2分钟)

    简要总结: 单引号: 可以说是所见即所得:即将单引号内的内容原样输出,或者描述为单引号里面看到的是什么就会输出什么. 双引号: 把双引号内的内容输出出来:如果内容中有命令.变量等,会先把变量.命令解析 ...

  3. python requests 配置超时及重试次数

    import requests from requests.adapters import HTTPAdapter s = requests.Session() s.mount('http://', ...

  4. AWVS介绍

    使用AWVS对域名进行全局分析,深入探索: 首先,介绍一下AWVS这个工具. Acunetix Web Vulnerability Scanner(简称AWVS)是一款知名的网络漏洞扫描工具,它通过网 ...

  5. WebView js 调用Java本地方法

    webView = (WebView) this.findViewById(R.id.webview); WebSettings webSettings = webView.getSettings() ...

  6. oracle&lowbar;解锁表&lowbar;解锁用户

    1.解锁用户 以dba身份登录   sqlplus / as sysdba alter user scott account unlock; 2.解锁表 alter   system   kill   ...

  7. 201521123019 《Java程序设计》第3周学习总结

    1. 本周学习总结 2. 书面作业 (1)代码阅读 public class Test1 { private int i = 1;//这行不能修改 private static int j = 2; ...

  8. PHP windowns安装扩展包

    1.  php_msgpack.dll php.ini 添加  extension=php_msgpack.dll 下载dll: http://pecl.php.net/package/msgpack ...

  9. 【Python 】selenium 简介

    从源码中可以找到selenium 2.48.0支持的浏览器如下: [python] view plain copy Firefox Chrome ChromeOptions Ie Edge Opera ...

  10. python --常用内置模块01

    1.简单了解模块         模块就是我们把装有特定功能的代码进行归类的解构,从代码编写的单位来看我们的程序 从小到大的顺序:一条代码< 语句块<代码块(函数,类) < 模块 我 ...