5 分钟

定义

在基于事件驱动的 Windows 操作系统的图形子系统中,钩子(Hook) 是一种截获(Intercept)系统与应用程序之间消息传递流的机制

例如,WPF 框架中的 HwndSource.AddHook 接口,它允许开发者注册一个回调函数,建立一个 位于操作系统底层原始消息(Raw Messages)与高级 UI 框架事件系统(High-level Events)之间 的代理层

也就是说,钩子机制是连接底层 Win32 API 与上层 .NET 运行时的关键通信桥梁

诠释

在Windows操作系统中,对外界的响应是由消息(Message)构造的

移动鼠标、按下键盘、点击窗口等会生成一条消息发送到对应窗口

通常情况下,WPF应用框架会自发处理信息,比如将“左键按下”处理为Button_Click

对于希望在消息到达框架前拦截信息,或者未为框架提供接口时,就可以使用钩子来提前获取消息

即:在系统的消息传递路径上,“钩”住感兴趣的信息

举例

对于我正在推进的C#解决方案:

这段代码看不懂也没关系,毕竟我也看不懂,主要任务是理解钩子是个什么东西,是用来干什么的就行了

private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    const int WM_HOTKEY = 0x0312; // 热键消息
    if (msg == WM_HOTKEY && wParam.ToInt32() == HOTKEY_ID) // 如果符合热键设置
    {
        Dispatcher.Invoke(() =>
        {
            ... ...
        });// 触发目标函数
        handled = true; // 标记信息处理
    }
    return IntPtr.Zero; // 其余信息正常放行
}

将这一个函数注入到消息的传输路径:

protected override void OnSourceInitialized(EventArgs e)
{
    base.OnSourceInitialized(e);

    HwndSource source = HwndSource.FromHwnd(handle);
    source.AddHook(WndProc);// 就广义地理解为注入钩子好了
}

这样,在有“消息”传入的时候,就会自动调用这个函数,然后将数据流通,并触发相应功能


在其他领域,hook的作用大同小异

比如galgame常用的MisakaHookFinder

这个御坂钩子提取器就可以在galgame游戏进程里注入一个钩子,将系统前端信息通过钩子提取并显示

比如提取文本数据,或者读取画面框架等,虽然只是简单的显示,不过还是有很大的作用的

钩子提取出台词,就可以通过api使用翻译软件翻译,再注入到应用里,就能做到实时的生肉烤熟功能

所以,hook是一个广义概念,看怎样使用。基本的作用就是把要执行的命令注入到信息的传输路径中,先跑一遍再放行(交个过路费,也可以不交过路费

结语

本文探讨了C语言编程中hook的作用,即劫持信息流处理后选择性放行,来将信息先通过自己的程序,达到自定义功能的效果

在我的Pause_Everywhere项目中,就是热键劫持;在MisakaHookFinder中,就是文本劫持

所以后面(小可能)会讲到的“词典笔中使用Hook注入进程来外挂功能和自定义”就是这个意思

留下评论