Hook入门
Hook入门
2014-07-24
基本概念[1]
Windows消息机制[5]
Windows操作系统是建立在事件驱动机制之上的,系统各部分之间的沟通也都是通过消息的相互传递而实现的。但在通常情况下,应用程序只能处理来自进程内部的消息或是从其他进程发过来的消息(借助进程间通信技术,如剪贴板,管道等)。
图1 Windows应用程序消息处理机制
(1)操作系统接收到应用程序的窗口消息,将消息投递到该应用程序的消息队列中。[5]
(2)应用程序在消息循环中调用GetMessage 函数从消息队列中取出一条一条的消息。取出消息后,应用程序可以对消息进行一些预处理,例如,放弃对某些消息的响应,或者调用TranslateMessage 产生新的消息。
(3)应用程序调用DispatchMessage,将消息回传给操作系统。消息是由MSG 结构体对象来表示的,其中就包含了接收消息的窗口的句柄。因此,DispatchMessage 函数总能进行正确的传递。DispatchMessage 函数分派一个消息到窗口过程,由窗口过程函数对消息进行处理。DispachMessage 实际上是将消息回传给操作系统,由操作系统调用窗口过程函数对消息进行处理(响应)。”
(4)系统利用WNDCLASS 结构体的lpfnWndProc 成员保存的窗口过程函数的指针调用窗口过程,对消息进行处理(即“系统给应用程序发送了消息”)。”
Hook(钩子)
如果需要对在进程外传递的消息进行拦截处理就必须采取一种称为HOOK的技术。HOOK作为Windows操作系统中非常重要的一种系统接口,用它可以轻松截获并处理在其他应用程序之间传递的消息,并由此可以完成一些普通应用程序难以实现的特殊功能。
Hook就是在图1中的第(2)步和第(4)步之间进行的额外工作(个人猜想,有待考证)。
运行机制[1]
钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。
每一个HOOK实质上都由系统维护着一个指针列表,其指针指向HOOK的各个处理函数,我们称之为HOOK子程。当与指定的Hook类型关联的消息发生时,系统就把这个消息传递到Hook子程。一些Hook子程可以只监视消息,或者修改消息,或者停止消息的前进,避免这些消息传递到下一个Hook子程或者目的窗口。
Hook子程是一个应用程序定义的回调函数(CALLBACK Function),不能定义成某个类的成员函数,只能定义为普通的C函数。用以监视系统或某一特定类型的事件,这些事件可以是与某一特定线程关联的,也可以是系统中所有线程的事件。
最近安装的Hook放在链的开始,而最早安装的钩子放在最后,也就是后加入的先获得控制权。
Windows 并不要求Hook子程的卸载顺序一定得和安装顺序相反。每当有一个钩子被卸载,Windows 便释放其占用的内存,并更新整个Hook链表。如果程序安装了钩子,但是在尚未卸载钩子之前就结束了,那么系统会自动为它做卸载钩子的操作。
在使用钩子时根据其监视范围的不同可以将其分为全局钩子和线程钩子两大类,其中线程钩子指定某个线程ID(可以是当前线程),只能监视该线程;全局钩子可以对同一个窗口下的所有线程进行监视。这里的全局HOOK的本质还是由触发HOOK机制的线程调用自身进程空间中的代码进行处理,所以我们的HOOK子程代码必须映射进该线程所在的进程的地址空间,即通过DLL的方式实现。下面描述实现过程:
首先我们编写HOOK驱动器,将HOOK.dll映射进内存中,安装好HOOK后,进行HOOK监视:
核心函数[1]
使用Windows HOOK所需要的核心函数不多,只有四个:
- SetWindowsHookEx():安装一个HOOK
- HOOK 子程:HOOK的处理函数,如GetMsgProc, KeyboardProc等
- CallNextHookEx():调用HOOK链的下一个HOOK子程
- UnhookWindowsHookEx():卸载一个HOOK
函数SetWindowsHookEx:
HHOOK SetWindowsHookEx(
//idHook用来标识HOOK类型,比如鼠标信息用WH_MOUSE,键盘消息用WH_KEYBOARD等
int idHook,
//lpfn指向一个具体的HOOK子程,用于实际处理拦截的消息
HOOKPROC lpfn,
//hMod用来标识HOOK子程所在的模块,\
//如果是一个全局HOOK,则是一个载入内存的DLL句柄(使用GetModuleHandle得到);如果是一个内部线程HOOK,则为NULL即可。
HINSTANCE hMod,
//dwThread指明HOOK的范围,
//如果是0则表示监视运行在同一个窗口下的所有线程,否则指定一个具体的线程ID即可。
DWORD dwThreadId
);
函数UnhookWindowsHookEx:
BOOL UnhookWindowsHookEx(
//参数为SetWindowsHookEx()的返回值
HHOOK hhk
);
函数CallNextHookEx
LRESULT CallNextHookEx(
//参数为SetWindowsHookEx()的返回值
HHOOK hhk,
//NCode为传给钩子过程的事件代码。
int nCode,
//wParam和lParam 分别是传给钩子子程的wParam值,其具体含义与钩子类型有关。
WPARAM wParam,
LPARAM lParam
);
HOOK 子程,函数KeyboardProc:
LRESULT CALLBACK KeyboardProc(
int code,
WPARAM wParam,
LPARAM lParam
);
C# hook示例
step 1:创建一个WinForm应用程序,把与hook相关的方法放在一个文件‘GlobalHook.cs’中:
using System; using System.Runtime.InteropServices;
using System.Reflection;
using System.Windows.Forms; namespace Test
{
//Declare wrapper managed KeyboardHookStruct class.
[StructLayout(LayoutKind.Sequential)]
public class KeyboardHookStruct
{
public int vkCode; //Specifies a virtual-key code. The code must be a value in the range 1 to 254.
public int scanCode; // Specifies a hardware scan code for the key.
public int flags; // Specifies the extended-key flag, event-injected flag, context code, and transition-state flag.
public int time; // Specifies the time stamp for this message.
public int dwExtraInfo; // Specifies extra information associated with the message.
} public class GlobalHook
{
#region native methods
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int SetWindowsHookEx(int idHook, GlobalHookProc lpfn, IntPtr hInstance, int threadId); [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern bool UnhookWindowsHookEx(int idHook); [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);
#endregion #region fileds
private const int WM_KEYDOWN = 0x100;
private const int WM_SYSKEYDOWN = 0x104; static int hKeyboardHook = ; //Declare keyboard hook handle as int.
//values from Winuser.h in Microsoft SDK.
public const int WH_KEYBOARD_LL = ; //keyboard hook constant
#endregion #region delegates and events
public event KeyEventHandler KeyDown; public delegate int GlobalHookProc(int nCode, Int32 wParam, IntPtr lParam);
GlobalHookProc KeyboardHookProcedure; //Declare KeyboardHookProcedure as HookProc type.
#endregion #region methods
public void Start()
{
// install Keyboard hook
if (hKeyboardHook == )
{
KeyboardHookProcedure = new GlobalHookProc(KeyboardHookProc); hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL,
KeyboardHookProcedure,
//IntPtr.Zero,
Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[]),
); //If SetWindowsHookEx fails.
if (hKeyboardHook == )
{
throw new Exception("SetWindowsHookEx ist failed.");
}
}
} public void Stop()
{
bool retKeyboard = true; if (hKeyboardHook != )
{
retKeyboard = UnhookWindowsHookEx(hKeyboardHook);
hKeyboardHook = ;
} //If UnhookWindowsHookEx fails.
if (!retKeyboard)
throw new Exception("UnhookWindowsHookEx failed.");
} private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
{
// it was ok and someone listens to events
if ((nCode >= ) && (KeyDown != null))
{
KeyboardHookStruct MyKeyboardHookStruct =
(KeyboardHookStruct)Marshal.PtrToStructure(lParam,
typeof(KeyboardHookStruct)); // raise KeyDown
if (KeyDown != null && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN))
{
Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;
KeyEventArgs e = new KeyEventArgs(keyData);
KeyDown(this, e);
}
}
//消息不再传递给下一个HOOK子程,也不会再发送给目的窗口
return ;
//消息传递给下一个HOOK子程
//return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
}
#endregion
} }
Step 2:在现有个Form1.cs[Design]界面中拖入一个控件‘Lable’,它的代码文件‘Form1.cs’内容如下:
using System;
using System.Text;
using System.Windows.Forms; namespace Test
{
public partial class Form1 : Form
{
private GlobalHook hook; public Form1()
{
InitializeComponent();
}
private void MyKeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
this.label1.Text = e.KeyCode.ToString();
} private void FormMain_Load(object sender, EventArgs e)
{
//全局钩子
hook = new GlobalHook();
hook.KeyDown += new KeyEventHandler(this.MyKeyDown);
hook.Start();
} private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
{
hook.Stop();
}
}
}
Step 3:为Form1界面把Step 2 加入处理方法注册到事件:FormClosing = FormMainClosing,Load=FormMain_Load。
Step 4:Build project,打开生成的Test.exe,当我们操作键盘时,无论Test.exe当前是active状态,或notepad当前是active状态,Test.exe的label控件都会显示出你键盘输入的字符。
注意:
- 当debug时,会在step 1代码66行抛错。
- 由于在HOOK子程KeyboardHookProc最后return 1,即消息不再传递给下一个HOOK子程,也不会再发送给目的窗口,因此,在若想notepad用键盘输入信息,它不会显示。
参考
[2] HOOK专题[来自微软中国社区]
[3] HOOK技术的一些简单总结
[4] windows钩子程序入门(一)
[5] dows编程 第三回 windows程序的生与死(中)
Hook入门的更多相关文章
- 2015某编程网易语言vip课堂全套教程 包含post,hook入门到精通等
2015某编程网易语言vip课堂全套教程 包含post,hook入门到精通等 官方论坛弄来的 如果在官方下载需要权限的 挺不错教程 想学习易语言入门到精通 post hook js改写的可以看 ...
- 小白也能看懂的插件化DroidPlugin原理(二)-- 反射机制和Hook入门
前言:在上一篇博文<小白也能看懂的插件化DroidPlugin原理(一)-- 动态代理>中详细介绍了 DroidPlugin 原理中涉及到的动态代理模式,看完上篇博文后你就会发现原来动态代 ...
- React Hook 入门使用
React Hook 是什么 1.没有比官网说的更好的 HOOK 1. React Hook 官方 2. 用我们自己的话说,它是一个钩子函数,用来处理组件间的状态的一个方法,暂时理解为一个高阶函数吧. ...
- 简单全局HOOK拦截大部分键盘消息
前言:学习HOOK中,万一老师讲解HOOK入门教程:http://www.cnblogs.com/del/category/124150.html http://www.cnblogs.com/del ...
- 小白也能看懂的插件化DroidPlugin原理(三)-- 如何拦截startActivity方法
前言:在前两篇文章中分别介绍了动态代理.反射机制和Hook机制,如果对这些还不太了解的童鞋建议先去参考一下前两篇文章.经过了前面两篇文章的铺垫,终于可以玩点真刀实弹的了,本篇将会通过 Hook 掉 s ...
- Android Hook神器:XPosed入门与登陆劫持演示
前段时间写了一篇关于Cydia Substrate广告注入的文章,大家都直呼过瘾.但是,真正了解这一方面的同学应该知道,其实还有一个比Cydia Substrate更出名的工具:XPosed. 不是因 ...
- HOOK API入门之Hook自己程序的MessageBoxW(简单入门)
说到HOOK,我看了很多的资料和教程,无奈就是学不会HOOK,不懂是我的理解能力差,还是你们说的 不够明白,直到我看了以下这篇文章,终于学会了HOOK: http://blog.sina.com.cn ...
- 【安全性测试】利用反编译查看对应activity的方法采用hook技术绑定劫持_入门
本次主要为了研究手机端的安全性而写的一篇文章,在基于自己对手机安全性的研究下,想到了这些工具之间的结合,当然这也算是第一次对手机安全研究勇敢地踏出一步,也不知道是否成功,还是准备撞南墙撞到底吧! 使用 ...
- HDU 1698 Just a Hook (线段树区间更新入门题)
Just a Hook Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
随机推荐
- NYOJ-975 关于521 AC 分类: NYOJ 2014-02-25 22:14 349人阅读 评论(0) 收藏
#include<stdio.h> struct AC { int x,y; }a[1000004]; int main() { int i,j,k=0;a[125].x=1,a[521] ...
- vector内存分配
vector,map 这些容器还是在堆上分配的内存,在析构时是释放空间 vector在提高性能可以先reserve在push_back() reserve:决定capacity,但没有真正的分配内存, ...
- 腾讯开源的轻量级CSS3动画库:JX.Animate
JX.Animate 是由腾讯前端团队 AlloyTeam 推出的一个 CSS3 动画库,通过 JX(腾讯的前端框架)插件的形式提供. Why CSS3 众所周知在支持HTML5的浏览器中 ...
- jquery的ajax同步和异步的理解及示例
之前一直在写JQUERY代码的时候遇到AJAX加载数据都需要考虑代码运行顺序问题.最近的项目用了到AJAX同步.这个同步的意思是当JS代码加载到当前AJAX的时候会把页面里所有的代码停止加载,页面出去 ...
- JDK各个版本下载页面
http://www.oracle.com/technetwork/java/javase/downloads/java-archive-downloads-javase7-521261.html 需 ...
- Ckeditor注册事件
这段时间使用js+cookies进行自动草稿保存,个人觉的,这些全在客户端处理比较的好,所以没有使用AJAX+数据库的自动草稿保存方法. 结果出现Ckeditor无法绑定onkeyup,onselec ...
- HDU3507 Print Article(斜率优化dp)
前几天做多校,知道了这世界上存在dp的优化这样的说法,了解了四边形优化dp,所以今天顺带做一道典型的斜率优化,在百度打斜率优化dp,首先弹出来的就是下面这个网址:http://www.cnblogs. ...
- iOS应用间的跳转和传值
在第一个应用程序中info.plist设置 URL Identifier: 该字符串是你自定义的 URL scheme 的名字 注意: URL Schemes 是一个数组,允许应用定义多个 URL s ...
- LINUX输入输出与文件
1 文件描述符 内核为每个进程维护一个已打开文件的记录表(实现为结构体数组),文件描述符是一个较小的正整数(0-1023)(结构体数组下标),它代表记录表的一项,通过文件描述符和一组基于文件描述符的文 ...
- Chrome 开发工具指南
Chrome 开发工具指南 谷歌 Chrome 开发工具,是基于谷歌浏览器内含的一套网页制作和调试工具.开发者工具允许网页开发者深入浏览器和网页应用程序的内部.该工具可以有效地追踪布局问题,设置 Ja ...