在进程启动时编辑 IAT(重定向到另一个 DLL)

Editing the IAT (redirecting to another DLL) at process startup

我有一个应用程序 X,它使用 DLL 文件 A 中的函数并在其 IAT 中引用它。我想以编程方式(不是手动修补)强制 X 加载具有模拟功能的替换 DLL B,换句话说,更改 IAT,以便加载我的文件 B.dll。举例说明:

X's IAT: A.TestFunction

在流程开始之前,我想将其更改为

B.TestFunction

我想在进程启动时执行此操作:启动器修改 X.exe 的 IAT(同样,不修补 HDD 文件;我的意思是一次性更改),然后真正启动进程,所以我需要以编程方式执行此操作,只是修补 IAT 不是一个选项。

在这种情况下,IAT 挂钩并不是我想要的,因为我不想覆盖 Windows 加载程序加载的过程,而是希望它在启动时加载我的 DLL .当然,可以创建一个虚拟 A.dll 并将函数转发到 B.dll,但我希望文件尽可能少,所以我正在寻找更好的解决方案。

该应用程序不是我的,我无权访问源代码,因此修改它是不可能的。

问题:我应该使用什么 API 来创建上面提到的加载程序,能够在启动之前修补 .exe 的 IAT?

您的应用在启动 运行 之前无法更改其自身的导入 table。您将必须:

  1. 创建一个单独的启动器应用程序,在启动主应用程序之前修补主应用程序的导入 table。

  2. 使用编译器的 delay-load feature(如果有的话)。延迟加载使用不同的 PE table,它在运行时由编译器的 RTL 处理,而不是在启动时由 OS 处理。延迟加载的 DLL 函数在您的代码首次调用时会在运行时按需加载。因此,您可以使用延迟加载挂钩来拦截 A 的加载,这样您就可以加载 return B 的句柄。

  3. 不要静态 link 到您的 DLL 函数开始。在代码中根据需要显式使用 LoadLibrary()GetProcAddress()(延迟加载在内部使用这些函数)。

如果您想用自己的 DLL 替换其中一个加载的 DLL,实际上非常简单。

您可以使用 LordPE(PE 编辑器 -> 目录 -> 导入 Table(不是 IAT!))获得导入列表,特别是您将获得每个导入的 "Name RVA"已导入 DLL。

这是该 DLL 名称在您的二进制文件中的存储地址。 例如,在我的屏幕截图中,如果您查看 RVA 0x1A46C,您将看到字符串 "SHELL32.dll"。使用您最喜欢的十六进制编辑器就地编辑字符串,或者在其他地方添加一个新字符串,然后将 LordPE 中的 "Name RVA" 更改为指向您的新字符串。

现在,如果您想以编程方式做同样的事情,方法是完全相同的,但您必须完成 LordPE 的工作。即解析PE头。 如果您想了解有关如何解析它的更多信息,可以查看此问题:PE File Parsing c/c++

我意识到我所需要的只是在我的启动器应用程序中使用 CREATE_SUSPENDED 标志 (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684863%28v=vs.85%29.aspx) 调用 CreateProcess。然后我可以自由地处理 IAT 并在完成后恢复该过程。