browser icon
You are using an insecure version of your web browser. Please update your browser!
Using an outdated browser makes your computer unsafe. For a safer, faster, more enjoyable user experience, please update your browser today or try a newer browser.

内联挂钩的注意事项

Posted by on 2009 年 02 月 09 日

你可以任意转载本文,但请在转载后的文章中注明作者和原始链接。
媒体约稿请联系 titilima_AT_163.com(把“_AT_”换成“@”)。

这是今天网友九九归一提出的问题,我觉得还是很有代表性的,所以将这个问题分析如下。
相应的示例代码为:http://www.phpweblog.net/GaRY/archive/2008/03/18/1272.html

如果你在运行的时候也无法正确完成内联挂钩,那么大多是这一句出了问题:

1
2
// 保存原始操作码
memcpy(orig_code, (BYTE *)func, 5);

这行代码看似简单,却有两个隐患:

  1. 以固定的 5 个字节为长度来保存原始操作码并不可靠,比如这里要挂钩的 func 函数:

    显然,如果强行挂钩的话,将会造成代码截断。
  2. 保存原始操作码不宜使用 memcpy 直接复制,而应该加以分析。例如,在默认的 Debug 配置下,程序本身是带有 ILT 的。换句话说,func 这个符号代表的并不是函数 func 的真实地址,而是 func 在 ILT 中的表项。

    由于 ILT 中是相对跳转,因此如果不特殊处理的话,那么执行原始函数的时候将会跳飞。

特别要强调的是上面的第 2 个隐患,由于这个隐患在 Release 配置下是不会出现的,因此会被很多人忽视。但是,如果你的目标环境是 Windows 内核,而且是一个安装有杀毒软件的 Windows 系统的话,那么你要挂钩的目标函数很有可能是被杀毒软件提前挂钩了的,要是这里最终跳飞的话,结果就只有蓝屏了。
值得一提的是,众多网友反映过的 July 插件 RunBlocker 与超级巡警冲突的问题就是因为 RunBlocker 在挂钩的时候没有分析代码的重定位,最终导致返回的跳转迷路了。

订阅本站

没有评论

(Required)
(Required, will not be published)