如何用我自己的实现(名称和参数设置相同)替换MS VC ++项目中的WinAPI函数调用?

时间:2020-03-05 18:52:44  来源:igfitidea点击:

我需要替换所有的WinAPI调用

  • CreateFile,
  • ReadFile,
  • SetFilePointer,
  • 关闭手柄

用我自己的实现(通过蓝牙使用低级文件读取)。
该代码将替换功能,即视频文件播放器,它已经可以与常规硬盘文件一起使用了。
同样需要的是,如果VideoPlayer输入中的文件是常规的HDD文件,则Video Player仍可以播放HDD中的文件。

这项任务的最佳实践是什么?

解决方案

回答

我认为这不是最佳做法,但是如果将其放在包含文件的位置,该文​​件包含在要更改的函数的每个位置,该文​​件应该会起作用:

#define CreateFile MyCreateFile

HRESULT MyCreateFile(whatever the params are);

MyCreateFile的实现如下所示:

#undef CreateFile
HRESULT MyCreateFile(NobodyCanRememberParamListsLikeThat params)
{
    if (InputIsNormalFile())
        CreateFile(params);
    else
        // do your thing
}

我们基本上可以使每个CreateFile调用成为MyCreateFile调用,我们可以在其中决定是否需要使用自己的实现或者原始实现。

免责声明:我认为这样做很丑,我不会这样做。我宁愿搜索并替换所有出现的事件或者其他内容。

回答

如果我们试图拦截来自另一个应用程序的对这些API的调用,请考虑使用Detours。

回答

如果我们可以编辑代码,则只需重新编写代码即可使用符合我们需要的自定义API。如果失败,请使用Maximilian的技术,但要警告它是维护恐怖。

如果我们无法编辑代码,则可以修补导入表以将调用重定向到我们自己的代码。可以在本文搜索标题为"通过更改导入地址表进行间谍活动"的部分中找到此技术的说明。

这很危险,但是如果我们小心一点,就可以使它起作用。还请检查Microsoft Detours,它可以执行相同的操作,但不需要我们弄乱实际的补丁。

回答

我建议我们按照以下步骤操作:

  • 编写一组包装函数,例如MyCreateFile,MyReadFile等,它们最初只是调用相应的API并传递相同的参数,且未修改。
  • 使用文本编辑器搜索对原始API的所有调用,然后将其替换为对新包装函数的调用。
  • 测试该应用程序仍然可以正常运行。
  • 修改包装函数以适合我们自己的目的。

请注意,CreateFile是一个宏,它会根据是否定义UNICODE扩展为CreateFileW或者CreateFileA。考虑使用LPCTSTR和TCHAR函数,以便可以将应用程序构建为ANSI或者Unicode。

请不要使用#define(如此处其他答复中所建议的那样),因为这只会导致维护问题,并且正如Maximilian正确指出的那样,这不是最佳实践。

回答

我们可以只在自定义名称空间中编写新函数。例如

namespace Bluetooth
{
  void CreateFile(/*params*/);
  void etc...
}

然后在代码中,我们唯一需要更改的就是:

if (::CreateFile(...))
{
}

if (Bluetooth::CreateFile(...))
{
}

简单! :)

回答

如果我们确实要劫持该API,请查看printer.dll(L-GPL)。