Skip to content

如何编写hook

序:如何使用hook

可以使用AG大佬的 https://github.com/ThirteenAG/Ultimate-ASI-Loader 项目

将下载的dll重命名为对应的文件名,可让游戏加载游戏目录中的ASI文件

适配任何 x64/x86游戏 免去注入器

事件sdk

hook通常可以用来开发sdk中的事件系统,说英文就是Event,在某个游戏事件发生时 执行指定的功能。

比如你要在游戏hud渲染时
渲染自己插件的贴图

如果直接写
在游戏主界面或者打开游戏就渲染你的贴图就不是你想要的效果

如果设置等待 那么效率会被影响
还会被其他线程影响

最好的办法 开发sdk的通常会封装事件函数
比如在sdk封装里提前hook游戏的hud渲染函数

hud事件函数就做好了
使用者直接使用这个函数注入自己的代码

每次游戏运行自己的hud渲染函数
会运行你的代码 实现在指定事件运行某个代码

然后事件封装里做成容器 使用vetcor list类型封装每个来自于插件的新函数

这样大家使用相同事件函数注入代码
就不会冲突
在链表里会依次执行这些函数

一个事件sdk就是这么实现的

公用CEvent事件

void hud::draw()

假设游戏使用这个函数渲染hud界面

A插件hook了这个函数 渲染自己的贴图

B插件也hook了这个函数
但没法保证使用的hook项目对同一个函数注入的兼容性

手动兼容很麻烦

那么假设有一个开发者做就一个sdk用于开发 或者做就一个公用库文件(dll和lib都行)
那么可以封装一个链表容器

只hook注入一次
所有来自于插件中的函数被放到容器里

每次运行这个函数依次取出容器里的函数运行
这样实现了兼容

hook最大的用处 就是事件系统

本身我们hook游戏的函数或者某个地址处的代码
就是实现改写和增加新功能

那么很难保证会不会有人对同一个地址反复hook
不利于兼容

写一个公用CEvent事件源更好

事件源可以增加很多事件

比如

  • hud渲染
  • 人物模型渲染
  • 菜单主界面渲染
  • 游戏读条界面
  • 人物死亡事件

这样的封装 能让编写者省事

而编写插件我们需要在某个时机实现自己的代码运行
就可以直接使用事件源完成

最终简单的脚本编写者可以脱离复杂的底层汇编

GTA系列几个游戏的sdk都是这么实现的

例子

最简单的例子就是

你写的dll在打开exe 游戏刚进去就已经在运行了

那么你不想它在这个时候运行
比如你操作了人物改写血量
可人物还没 创建呢 因为游戏刚打开

假设你能通过一些逆向工具
找到游戏在读条加载后进入的瞬间运行的人物渲染函数

hook这个函数 运行自己的代码
在对人物进行操作就解决了

ce脚本的实现 通常会改写固定的血量全局变量或者对汇编代码进行修改
以防止人物还没创建就去运行修改血量的问题