用于 64 位操作系统的系统范围挂钩

Posted

技术标签:

【中文标题】用于 64 位操作系统的系统范围挂钩【英文标题】:system-wide hook for 64-bit operating systems 【发布时间】:2011-02-28 07:15:18 【问题描述】:

我想在 64 位操作系统上执行系统范围的挂钩(使用 SetWindowHook)。

我知道 64 位进程 (= proc64) 只能加载 64 位 dll (= dll64),而 32 位进程 (= proc32) 只能加载 32 位 dll (= dll32)。

目前我计划调用 SetWindowHook 两次,一次使用 dll32,一次使用 dll64,预计 proc64s 将加载 dll64,proc32s 将加载 dll32(而 proc64s 的 dll32 和 proc32s 的 dll64 将失败)。

这是正确的做法,还是有“更正确”的做法?

谢谢! :-)

【问题讨论】:

【参考方案1】:

您所描述的方法是正确的并记录在案。

来自http://msdn.microsoft.com/en-us/library/ms644990(v=vs.85).aspx:

SetWindowsHookEx可以用来注入 一个DLL到另一个进程。一个 32 位 DLL 不能注入到 64 位 进程,并且不能使用 64 位 DLL 注入32位进程。如果 应用程序需要使用钩子 在其他过程中,需要 一个 32 位应用程序调用 SetWindowsHookEx 注入 32 位 DLL 转换为 32 位进程,以及 64 位应用程序调用 SetWindowsHookEx 注入 64 位 DLL 转换为 64 位进程。 32 位 和 64 位 DLL 必须有不同的 名字。

请注意最后一条语句,即 32 位和 64 位 DLL 的名称必须不同。

【讨论】:

【参考方案2】:

您可能需要查看EasyHook 来省去一大堆麻烦。

【讨论】:

我不想使用 easyhook 来完成这项任务,因为 SetWindowHook 足以完成这项工作......【参考方案3】:

您应该在代码中测试机器以查看字长是 32 位还是 64 位。 64 位机器将通过扩展字长来处理 32 位指令集,但是传递 64 位指令集的 32 位机器......可能会导致非常糟糕的事情。

在C标准库的limits.h头文件中——INT_MAX会给你最大尺寸,测试看看

bool is32 = true;

if ( INT_MAX == 2^63 − 1 ) 
  is32 = false;

一旦你有了你的标志,你就会知道要包含哪个文件,并且你可以使用你的标志来包含它。

【讨论】:

如果 INT_MAX 是无符号的,你需要测试它是否等于 2^64 - 1,不记得是否。 既然有单独的 32 位和 64 位版本的 DLL,为什么还要这样做? 这样您的程序就不会尝试在 32 位机器上使用 64 位 dll。在大多数情况下,32 位机器会将 64 位指令切成两半并处理它们,这相当于在 c 中创建指针,而不是将其清空或初始化并在其上运行进程......你不知道会发生什么发生。 首先,这个问题明确说明了存在 64 位操作系统的事实。其次,有更多相关的方法可以在编译时查看平台是否为 AMD64。第三个也是最后一个 - 32 位 DLL 不会从 64 位进程加载,就像 64 位 DLL 不会从 32 位进程加载一样。所以没有机会得到你描述的组合。

以上是关于用于 64 位操作系统的系统范围挂钩的主要内容,如果未能解决你的问题,请参考以下文章

计算机系统,16位,32位,64位啥意思?

Win64与Win32的本质区别

使用非托管 DLL 来自 .NET 的系统范围外壳挂钩

在32位64位操作系统下各数据类型所占的字节数

用于检测系统是 32 位还是 64 位的 Shell 脚本 [重复]

32位操作系统与64位操作系统内存比较