在启动时使应用程序加载 dll

逆向工程 修补
2021-07-01 06:33:27

我已经向现有的应用程序添加了一些通过 dll 注入工作的功能 - 我的 dll 加载并修补了一些东西。

我希望将它永久添加到此应用程序中,这样我就不必每次都手动注入它 - 我知道有一些解决方案,例如:

  1. Loader - 另一个运行目标应用程序然后注入 dll 的应用程序
  2. Patch EP - 目标应用程序的补丁条目,因此它在执行 rest 之前加载我的 dll
  3. AppInit_DLL - 通过这个寄存器条目使它加载到几乎每个进程,然后检查我们是否在正确的进程中,否则卸载

但这些选择是最优化的吗?第一个和第二个需要一些工作(也许有一些我不知道的现有工具并且允许它?所以我不必自己准备所有这些),第三个似乎有点过度。只是为了扩展我的知识 - 还有哪些其他选择?

4个回答

您还可以将 DLL 添加到 EXE 的导入表中。这样做的好处是不会将 DLL 加载到加载 user32.dll 的每个进程中(这是 #3 的一个问题),您可以使用IIDKing 之类的工具轻松添加导入表

IDKing

这是我前一段时间做的,当我遇到你的问题时。

  • 使用dependency walker 查找由主可执行文件导入的DLL,.exe 仅从中导入一两个函数。举例来说,让我们假设您的应用程序someprog.exe使用了一个 dll vendor.dll,它从中导入了ShowCopyright函数。
  • 使用十六进制编辑器,vendor.dll将可执行文件中的字符串更改hacker.dll.
  • 在 DLL 的启动中,使用LoadLibrary("vendor.dll")GetProcAddress("ShowCopyright")来获取指向实际ShowCopyright函数的函数指针
  • 此外,在您的 DLL 中,提供一个ShowCopyright导出,它ShowCopyright只会跳转到您刚刚检索到的地址。
  • 重命名您的 DLLhacker.dll并将其放入应用程序的搜索路径中。

请注意,这在一定程度上取决于可执行程序导入的 DLL 数量,以及您是否发现不必“模拟”几十个 API 条目、资源或任何可以链接到 dll 的 DLL。

编辑:

完成我的帖子后,我找到了Jason的答案,这似乎更专业,更容易。但是,至少,除了十六进制编辑器之外,我的解决方案不需要任何工具:-)

正如 Jason Geffner 所说,您可以将 DLL 添加到 .exe 的导入表中。除了 IIDKing 可以将您的 dll 添加到 PE 文件的导入表的其他工具称为Stud_PE,与 IIDKing 不同,如果您的 dll 在导出地址表 (EAT) 中没有任何条目,它不会崩溃:

在此处输入图片说明

奇怪的是,没有提到另外两种方法。AppInit_DLLs我所知,您提到方法不再适用。至少没有那么容易,尤其是在启用 UEFI 安全启动时。

在这两种情况下,它都取决于目标二进制文件,所以让我们来看看它。

DLL 放置攻击

我过去曾在 Windows 7 上运行过此程序,但此后规则发生了变化我使它工作的方式如下。我找到了一个由程序加载的(供应商提供的)DLL,没有完整路径(我选择了导入次数最少的那个)。然后我编写了一个存根 DLL,它会简单地将所有函数调用传递给真正的 DLL(通过完整路径加载)并为我打印出有用的信息。返回值将被简单地返回。

很容易弄清楚导出函数的函数原型,所以这对我来说是一个懒惰的选择。

ImageFileExecutionOptions

Process Explorer 使用此方法使自己成为任务管理器的替代品。下面是它的实际效果:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\taskmgr.exe]
"Debugger"="\"C:\\PATH\\TO\\PROCEXP.EXE\""

现在值名称可能已经泄露了,这以前用于完全不同的目的。

无论哪种方式,您都可以(ab)使用它来实现您想要的。您编写了一个小的存根加载器,充当“调试器”。没什么,您甚至不必实现任何调试器 API,尽管您可以。

您要做的就是使用CreateProcess或类似方法创建一个进程,其主线程在“启动”时处于挂起状态。您可以随心所欲地传递命令行参数(尽管确实如此),但CreateProcess与朋友们有一些关系

暂停的主线程是您可以绕道到您自己的代码的地方……通常是一段简单的 shell 代码,除了加载您的DLL 然后返回到原始入口点之外什么都不做等瞧,您已加载DLL到应用程序中。

第二种方法的好处在于它可以很好地扩展,因为您基本上只需要编写一次这种“调试器”(加载器)。所以它可以保持通用。

这个方法相当于做(从命令行):

loader.exe C:\path\to\hijacked\application.exe argument1 argument2 and more arguments

...除了对用户来说这将是透明的。我认为在你的加载器中你甚至可以argv[0]用来获取被劫持的可执行文件 IIRC 的路径。

现在您可能认为这是一些奇怪的安全问题,并想知道为什么它被忽视了。这不是安全问题,因为您必须首先获得特权ImageFileExecutionOptions

作为旁注:我认为甚至taskmgr.exe可以使用要劫持的可执行文件的完整路径来命名包含密钥(在上述注册表文件中)。