纯C#实现Hook功能详解
什么是Hook
在计算机编程领域,Hook是指拦截某个操作,加入自定义的操作或者修改已有操作的过程。
Hook的种类
Windows系统中可用的Hook种类有三种:
- 全局钩子(Global Hook)
全局钩子会影响整个操作系统,可以拦截鼠标、键盘、消息、Shell等等所有操作,需要管理员权限安装和使用,且有一定的性能损失。
- 线程钩子(Thread Hook)
线程钩子只会钩住单个线程,不会影响整个操作系统,可以拦截鼠标、键盘等操作。
- 应用程序钩子(Application Hook)
应用程序钩子只会钩住单个应用程序,通过DLL注入的方式实现。可拦截路径、文件等。
C#实现Hook
C#语言可以通过托管代码结合C++ dll的方式实现Hook。
-
创建一个Class Library项目,将Hook功能封装在其中
-
在该项目中添加一个C++ CLR Class
在项目中添加一个类,选择C++/CLR语言,作为Hook操作的实现。在其中定义好相关的钩子事件,如键盘事件等。
- 在Hook类中增加Hook函数
Hook函数主要实现了Hook种类、DLL注入等。
- 在Hook类中增加钩子事件
定义钩子事件,该事件会在接收到需要Hook的操作时被触发。
- 在Hook类中增加处理函数
处理函数主要实现了Hook收到事件时需要采取的操作,如输出日志等。
示例1:全局钩子
下面是一个全局钩子示例代码:
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace GlobalHook
{
public class GlobalKeyboardHook : IDisposable
{
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, HookCallBack lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
delegate IntPtr HookCallBack(int nCode, IntPtr wParam, IntPtr lParam);
const int WH_KEYBOARD_LL = 13;
const int WM_KEYDOWN = 0x100;
private IntPtr hookId = IntPtr.Zero;
private HookCallBack hookProc;
private EventHandler<KeyEventArgs> keyPressed;
private bool disposed = false;
public GlobalKeyboardHook()
{
hookProc = new HookCallBack(HookCallback);
hookId = SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, IntPtr.Zero, 0);
keyPressed = new EventHandler<KeyEventArgs>(OnKeyPressed);
}
public event EventHandler<KeyEventArgs> KeyPressed
{
add { keyPressed += value; }
remove { keyPressed -= value; }
}
protected virtual void OnKeyPressed(object sender, KeyEventArgs e)
{
if (keyPressed != null)
{
keyPressed(this, e);
}
}
private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
OnKeyPressed(this, new KeyEventArgs((Keys)vkCode));
}
return CallNextHookEx(hookId, nCode, wParam, lParam);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
if (keyPressed != null)
{
foreach (EventHandler<KeyEventArgs> handler in keyPressed.GetInvocationList())
{
keyPressed -= handler;
}
}
}
UnhookWindowsHookEx(hookId);
disposed = true;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~GlobalKeyboardHook()
{
Dispose(false);
}
}
}
示例2:线程钩子
下面是一个线程钩子示例代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ThreadHookDemo
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[DllImport("user32.dll")]
public static extern int SetWindowsHookEx(int hookType, HookProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll")]
public static extern int CallNextHookEx(int hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
public static extern int UnhookWindowsHookEx(int hhk);
public static int WH_MOUSE_LL = 14;
public static int WH_KEYBOARD_LL = 13;
public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
IntPtr hookId;
HookProc hook = MouseHookProc;
private void button1_Click(object sender, EventArgs e)
{
if (hookId == IntPtr.Zero)
{
IntPtr hInstance = Marshal.GetHINSTANCE(this.GetType().Module);
hookId = (IntPtr)SetWindowsHookEx(WH_MOUSE_LL, hook, hInstance, 0);
if(hookId == IntPtr.Zero)
{
MessageBox.Show("Failed to hook the mouse");
}
else
{
button1.Text = "Unhook";
}
}
else
{
UnhookWindowsHookEx((int)hookId);
hookId = IntPtr.Zero;
button1.Text = "Hook";
}
}
private static int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode == 0)
{
int x = Marshal.ReadInt32(lParam);
int y = Marshal.ReadInt32(lParam + 4);
Debug.Print("X: {0}, Y: {1}", x, y);
}
return CallNextHookEx(0, nCode, wParam, lParam);
}
}
}
总结
Hook是一种非常重要的技术,可以拦截并修改操作系统的行为,改善用户的操作体验。通过上述示例代码,我们可以更深入理解Hook的实现方法,同时也可以据此开发类似的功能。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:纯C#实现Hook功能详解 - Python技术站