4

这里有一些背景信息。AppInit_DLLs我正在通过注册表项替换已在 dll 注入技术中使用的 dll 。它的目的是存在于每个进程中,并在 GDI32.dll 中设置挂钩以收集有关打印的信息。这是一种获得我们想要的东西的时髦方式。.dll 本身已有 10 多年的历史(用 Visual Studio 97 编写),我们想用比注入的 dll 侵入性更小的东西来替换它。

这似乎SetWindowsHookEx()是我们正在寻找的东西。我一直遇到一些麻烦,但我也与同事讨论过这棵树是否值得吠叫。以下是一些我们无法确定的问题:

  1. 当我们从 dll 中挂钩例程时,例如StartDoc()从 GDI32.dll 中,是否真的每次其他进程使用该 dll 中的该例程时都会收到通知? 这是我们通过注入的 .dll 获得的功能,我们需要相同的功能。

  2. 当钩子被触发时,钩子处理过程是在发起实际调用的进程的进程空间中运行,还是在设置钩子的进程的进程空间中运行? 我的观点是它必须在调用例程的进程的进程空间中运行。例如,如果一个程序调用StartDoc()从 GDI32.dll 中,它将钩子处理程序代码“注入”到其空间并执行。否则,必须在调用进程和设置挂钩的进程之间自动建立一些进程间通信,我只是不认为是这种情况。此外,这个钩子处理例程在调用进程的进程空间中运行是必要的,因为它需要知道的一件事是该调用进程的名称,我不确定如何获取该信息,如果它实际上并没有在该过程中运行。

  3. 如果挂钩处理例程是使用 .NET 托管环境编写的,那么当挂钩到不使用 .NET 托管环境的进程时会中断吗?我们真的很想在这里摆脱 C++ 并使用 C#,但是如果我们的钩子从不受管理的进程中调用会发生什么?如前所述,我认为我们的钩子处理过程将在最初调用被钩子例程的进程中运行。但如果这是真的,那么我认为如果这个进程没有使用 .NET 运行时环境,但传入的钩子处理代码是,我们会遇到麻烦。

4

1 回答 1

3
  1. 是的。

  2. 通常,它是前者:它在它正在挂钩的事件的进程的上下文中执行。

    调用成功后SetWindowsHookEx,操作系统会自动将钩子DLL(包含回调函数的DLL)注入到所有满足指定钩子类型要求的目标进程的地址空间中。(当然,挂钩代码不一定是立即注入的。)

    此一般规则的例外是低级键盘和鼠标挂钩(WH_LL_KEYBOARDWH_LL_MOUSE)。由于这些钩子类型没有注入到客户端进程中,因此回调在最初调用的同一线程中调用SetWindowsHookEx

  3. 最后一点很重要,要记住回答你的第三个问题。因为低级键盘和鼠标挂钩是仅有的两个不需要 DLL 注入的全局挂钩,所以它们也是仅有的两种可以用托管 .NET 代码编写的挂钩。

    对于其他钩子类型,您在问题中表达的担忧是完全正确的。您需要用 C 或 C++ 编写这些钩子 DLL。当然,您的应用程序的其余部分仍然可以用托管语言编写。唯一重要的是挂钩 DLL。

您可以考虑查看Microsoft DetoursEasyHook

于 2012-01-27T04:31:09.043 回答