【问题标题】:Can Windows API functions be over-written and called after it?Windows API 函数可以被覆盖并在它之后调用吗?
【发布时间】:2011-10-14 16:17:00
【问题描述】:

我想修改 Windows API 中可用的本机函数,例如 CreateWindowExShowWindow,以便在编译包含这些函数的应用程序时,它会调用我的函数,在那里执行任务,然后调用原来的native函数。

换句话说,我想以某种方式代理函数,同时仍然使用相同的名称(因此,如果编写的程序是使用本机 API 编译的,只需添加这些函数就会修改这些本机函数的方式处理)

HWND WINAPI CreateWindowEx(
  __in      DWORD dwExStyle,
  __in_opt  LPCTSTR lpClassName,
  __in_opt  LPCTSTR lpWindowName,
  __in      DWORD dwStyle,
  __in      int x,
  __in      int y,
  __in      int nWidth,
  __in      int nHeight,
  __in_opt  HWND hWndParent,
  __in_opt  HMENU hMenu,
  __in_opt  HINSTANCE hInstance,
  __in_opt  LPVOID lpParam
) {

    //my custom code here....

    // done with my custom code... so now I want to run the native function
    return CreateWindowEx(dwExStyle, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
}

这(出于显而易见的原因)会导致堆栈溢出,因为它会一遍又一遍地调用自己。我希望它做的是,当它被调用时,它会运行我创建的自定义函数,然后运行 ​​Windows API 中可用的本机函数。

我对 c++ 很陌生,但是例如在许多其他语言中,我可以将对本机函数的引用存储在另一个名称下,然后我可以在我的自定义函数中调用它。 c++中有没有类似的东西?

【问题讨论】:

  • 曾几何时,微软研究院有一个 Detours 项目。现在它不再是免费的(至少是在 x64 上运行的 Pro 版本)。但是请尝试在谷歌上搜索 Detours 的替代品。
  • 您这样做的原因将决定最佳解决方案是什么。你能提供更多背景信息吗?
  • @tenfour 我希望绑定这些函数以通过 Web 套接字将详细信息(窗口选项、操作等)发送到 javascript

标签: c++ winapi


【解决方案1】:

正如我在评论中所写,许多挂钩库的父级可能是 microsoft Detours

现在它不再是免费的了,有多种选择。这里有其中一些的比较(链接已删除。我不确定它是否安全。尝试使用谷歌搜索“Microsoft Detours 是用于特定拦截的库”并选择来源或更简单的 Detours Alternatives。

嗯,目前看来唯一免费的选择是 http://easyhook.codeplex.com/http://www.codeproject.com/KB/system/mini_hook_engine.aspx

有一个 SO 问题:Detours alternative for Registry interception 如果您有兴趣。

【讨论】:

  • 我没有意识到 Detours 不再免费。真可惜。
  • 这不是我想要的,但实际上可能是我需要的。需要详细阅读它到底是什么
【解决方案2】:

对您的问题的一种解释是,您有一个带有源代码的项目,并且您想更改该项目,以便它使用您自己的某些 winapi 函数版本。

这是一个您可以为每个导入的 API 函数实施的解决方案。这里的例子是ShowWindow:

#define ShowWindow Deleted_Winapi_ShowWindow // prevent windows.h from defining ShowWindow
#include <windows.h>
#undef ShowWindow

namespace HiddenWinapi
{
    extern "C"
    {
        // Do what windows.h does, but hide it inside a namespace.
        WINUSERAPI BOOL WINAPI ShowWindow( __in HWND hWnd, __in int nCmdShow);
    }
}

// make your own function to be called instead of the API, and delegate to the actual API in the namespace.
BOOL WINAPI ShowWindow(HWND hwnd, int nCmdShow)
{
    // ... do stuff ...
    // call the original API
    return HiddenWinapi::ShowWindow(hwnd, nCmdShow);
}

要将此解决方案用于CreateWindowEx,您需要存根实际导入的函数名称(例如CreateWindowExW),因为CreateWindowEx 只是一个扩展为CreateWindowExWCreateWindowExA 的宏。

这是一个用您自己的宏替换宏的解决方案,但我认为在所有情况下使用上述解决方案会更好。

#include <windows.h>

#undef CreateWindowEx

// Note that this is a unicode-only version. If your app mixes A and W versions, see 
// the solution below for non-macro APIs.
HWND WINAPI CreateWindowEx(DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
{
    // ... do stuff ...
    // call the REAL function.
    return CreateWindowExW(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
}

【讨论】:

  • 这似乎与我最初所追求的非常接近,但看看 xanatos 关于 Detours 和 EasyHook 的回答,它实际上可能是我真正需要的。但是,如果实际上所有函数都不是宏,则可能会出现问题,在这种情况下,需要一些不同的解决方案。
  • 抱歉,我对其进行了编辑,为非宏 api 调用提供了一个优雅的解决方案。
【解决方案3】:

如果您想自己执行此操作,最简单的方法是修改 PE(可移植可执行文件)标头中的导入地址表。不过,这并非微不足道。

但是,我相信有一个标准库可以满足您的需求,称为 Detours。不过,我自己从来没有使用过那个,因为当我开始这样做的时候它还不存在,所以我有一个 - 不是供公众使用的 - 库,可以在我需要时通过导入表执行它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-09
    • 1970-01-01
    • 1970-01-01
    • 2010-10-14
    • 1970-01-01
    • 2011-12-15
    • 1970-01-01
    • 2016-07-14
    相关资源
    最近更新 更多