7

我正在开发一个捕获所有用户交互的项目。MSDN告诉(这个

SetWindowsHookEx 可用于将 DLL 注入另一个进程。32位DLL不能注入64位进程,64位DLL不能注入32位进程。如果应用程序需要在其他进程中使用钩子,则需要 32 位应用程序调用 SetWindowsHookEx 将 32 位 DLL 注入 32 位进程,64 位应用程序调用 SetWindowsHookEx 将 64 位DLL 转换为 64 位进程。

我的问题是,如果应用程序是针对Any CPU. 我是否需要SetWindowsHookEx从针对Any CPU.

我已经编写了 HookLogger_32.exe 加载 HookFunctions_32.dll(均为 x86)和 HookLogger_64.exe 加载 HookFunctions_64.dll(均为 x64)设置WH_CBTWH_MOUSE全局(不是特定线程)。

HookLogger_32.exe、HookLogger_64.exe、HookFunctions_32.dll 和 HookFunctions_64.dll 是用 C++ 编写的。

当我单击基于 .NET 构建的应用程序时Any CPU,这些 DLL 会被注入(通过SetWindowHookEx)。Windows 操作系统挂起,我必须强制重启我的机器。

当针对 x86 或 x64 构建相同的 .NET 应用程序时,当我在 HookLoggers(32 位和 64 位)启动后单击该应用程序时,一切正常。

这种未定义行为的任​​何原因。

我工作的平台是 64 位机器。

4

4 回答 4

3

您需要从具有相应位元的 DLL 注入 - 即“任何 CPU”在运行时变为 32 位或 64 位......并且您的 DLL 必须与运行时位匹配!

在您的情况下有用的东西被称为“并行程序集”(同一程序集的两个版本,一个 32 位和另一个 64 位)......我认为您会发现这些很有帮助:

在这里您可以找到一个很好的演练,其中包含许多有用的信息片段 - 它描述了.NET DLL 包装 C++/CLI DLL 引用本机 DLL

更新:

要使钩子变得非常简单和健壮,请查看这个经过良好测试的免费库- 除其他外,它可以与 AnyCPU 一起使用!

于 2012-02-04T20:10:37.787 回答
0

我想您的主要问题是您试图将 .NET 程序集注入本机进程,这肯定行不通。我什至不确定 SetWindowsHookEx 是否支持在 CLR 进程中注入 .NET 程序集。您的问题的解决方案是:

  1. 使用原生编译器(例如 C++/Delphi/VB 等)为 x86 和 x64 平台重写/重新编译您的 dll。
  2. 确保您的 dll 仅依赖于系统库。例如,它不应该依赖于任何不随 windows 一起提供的 dll,因为您可能会使目标进程崩溃。您可以使用“Dependency Walker”工具来识别依赖关系。
  3. 正如 MSDN 中提到的,您应该为您希望支持的每个 cpu 提供一个可执行注入器。在这种情况下,x86 和 x64。

或者您可以使用更好的注入/挂钩库,例如 madCodeHook 或 Detours。通过这种方式,您将克服问题 #3,更不用说他们提供的数十位专业人士了。

于 2012-02-04T22:57:25.260 回答
0

仅根据您对问题的描述,我的猜测是......您的任何 CPU 编译程序正在加载一个 x86 存根,该存根正在触发您的 32 位钩子,然后 x86 存根检查并查看环境是否支持 64 位并启动 64 位 CLR 版本。

在这种情况下,您的 32 位钩子 dll 正在获取 WH_SHELL 消息并试图注入已经结束的进程(x86 存根)或将 32 位钩子注入 64 位 CLR 进程。因此,您的“非常模棱两可,需要详细说明”系统崩溃。

如果您想详细说明您的代码实际在做什么,那么将提供更多帮助(以及更少的概括和“仅使用程序 A”)。您实际上是在将代码注入进程还是使用进程的 dwThreadId 调用 SetWindowsHookEx。

于 2012-02-07T13:04:26.830 回答
0

在一台 32 位计算机上,任何 CPU 应用程序所采用的位数应该是非常明显的。

一台 64 位计算机有两个单独的 .NET Framework 安装:每个位一个。使用 Any CPU 作为目标编译的 .NET 应用程序通常在 64 位安装上运行,但如果被另一个直接针对 x86 的应用程序引用,它也可以在 32 位安装上运行。因此,只有知道应用程序的运行方式:作为独立进程或通过引用,您才能确定所获得的结果。

我不会做任何假设。不要假设该进程在 64 位计算机上是 64 位的:它可能是 32 位的。正确检查它以查看它正在运行的模式。然后,相应地从 32 位或 64 位注入。

您必须使用与目标进程相同的位数的原因是,出于我不会了解的技术原因,此类挂钩无法跨越所谓的 SysWOW 障碍。SysWOW 允许 32 位应用程序在 64 位计算机上运行,​​16 位应用程序在 32 位计算机上运行等。当您在运行在 SysWOW 不同方面的应用程序之间进行通信时,您正在“跨越障碍” --也就是说,一个在SysWOW(32位)中运行,另一个不在(64位)。简单地说,一个进程必须完全进出SysWOW。因此,您不能将 32 位代码添加到 64 位进程,反之亦然。

于 2012-02-08T07:12:16.253 回答