【问题标题】:Win32 Hooks DLL injection into Applications Built against "Any CPU"Win32 将 DLL 注入到针对“任何 CPU”构建的应用程序中
【发布时间】:2012-02-20 07:54:01
【问题描述】:

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

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

我的问题是,如果应用程序是针对 Any CPU 构建的,会发生什么情况。我是否需要从针对Any CPU 构建的DLL 调用SetWindowsHookEx

我已经编写了 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++ 编写的。

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

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

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

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

【问题讨论】:

  • 在为 32/64 构建时它是否正常工作或在那里崩溃?
  • @pst:它在为 32/64 构建时可以正常工作。它是一个 hello world WPF 应用程序。
  • 听起来可能是相关的:stackoverflow.com/questions/1507268/…
  • 您遗漏了“32 位和 64 位 DLL 必须具有不同的名称。”少量。如果将 DLL 构建为 Any CPU,则对于 .NET 可能无关紧要——运行时可以加载相同的二进制文件,而不管主机进程目标体系结构如何——但 Windows 中的挂钩实现可能取决于文件名的不同。因此,只需制作两份以任何 CPU 为目标的 DLL 副本,并尝试从 32 位进程加载“32 位”一份,并从 64 位进程加载“64 位”一份。
  • @cynic:我有不同名称的 DLL。并且 DLL 是针对 x86 和 x64 用 C++ 构建的(我无法针对任何使用 C++ 的 CPU 构建)

标签: hook dll-injection setwindowshookex


【解决方案1】:

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

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

在这里您可以找到一个不错的演练,其中包含许多有用的信息片段 - 它描述了 .NET DLL wrapping C++/CLI DLL referencing a native DLL

更新:

要使挂钩变得非常简单和强大,请参阅this well-tested and free library - 除其他外,它还可以与 AnyCPU 一起使用!

【讨论】:

  • 我对 EasyHook 的又一次出价。在 C/C++ 中走弯路后,EasyHook 让它变得简单。
【解决方案2】:

我猜你的主要问题是你试图将一个 .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,更不用说他们提供的数十位专业人士了。

【讨论】:

  • 我从中调用 SetWindowsHookEx 的代码和被注入的 DLL 是使用 C++(x86 和 x64)构建的。我挂接的应用程序是针对任何 CPU 构建的 .NET 应用程序。而且我用的机器是64位的。
【解决方案3】:

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

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

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

【讨论】:

  • 我不是在注入代码,而是在全局调用 SetWindowHookEx。仅当我单击针对任何 CPU 构建的 HelloWorld .NET 应用程序时,操作系统才会挂起。检查我更新的问题。
  • @sri - 感谢您的澄清。您应该让您的 HookLogger EXE 将他们收到的每条消息都记录到一个日志文件中(当然,32 位和 64 位的日志文件是分开的)。然后,当您从系统冻结中恢复时,您可以看到之前发生的事情。确保他们为收到的每条消息打开/追加/关闭日志文件。我的猜测是 Any CPU 程序集正在触发您的 x86 HookLogger 和您的 x64 HookLogger。
【解决方案4】:

在 32 位计算机上,Any 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 位进程,反之亦然。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-23
    • 2015-07-01
    • 2012-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多