在原始进程中实现DLL注入加载

admin 2024年4月27日19:18:26评论11 views字数 1964阅读6分32秒阅读模式

在原始进程中实现DLL注入加载

介绍

DLL 端加载已经使用相当长一段时间了,以实现在受信任的签名进程中执行代码。它已在其他博客中进行了广泛讨论,因此我邀请您先阅读它们,因为我不会在这里重复。最简单且最流行的方法是将代码放入 DllMain 中,以便在 DLL 加载到进程中后进行远程 shellcode 注入。

最近一段时间,针对好的 EDR 进行远程注入越来越不容易,但使用最新技术仍然是可行的,例如“Pool Party”此时是如何做到的。

在大多数情况下,通过跳转到开头来在原始进程中本地执行 shellcode 仍然是一种更稳定且更符合 OPSEC 的方法,但在进行 DLL 侧面加载时它有一个限制,即“加载器锁”。本质上,处于加载锁内部意味着在该状态下可以调用的函数受到显着限制。

在原始进程中实现DLL注入加载

图1来源:https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices

这是因为大多数 C2 shellcode(例如 Cobalt Strike 的)会在初始化期间尝试加载其他 DLL,这是在加载器锁内不允许也不建议这样做的。大多数时候,这会导致进程被阻塞并且没有 shell。

那么,我们有什么选择呢?有些人正在创建一个单独的线程并从那里成功执行,但这不是Microsoft推荐的解决方案,因为根据该线程中所做的操作,它可能会造成死锁或崩溃。我个人从不使用 DllMain 进行侧面加载,而更喜欢重新实现和导出由合法 DLL 导出并由侧面加载进程调用的第一个方法。当您不希望原始程序向当前可能登录的用户显示任何视觉指示符并且需要完全劫持程序功能时,这尤其有用。

这篇博文将介绍我用来寻找优秀候选人的方法以及如何避免编译时可能出现的问题。

寻找可侧面加载的候选者

首先,我使用常用参数启动进程监视器来查找首先在当前目录中搜索但未找到的 DLL。

在原始进程中实现DLL注入加载

然后,我开始在测试系统上执行任意签名的二进制文件,直到看到尝试从测试文件夹加载缺少的 DLL:

在原始进程中实现DLL注入加载

理想的候选者是经过签名的二进制文件,无需在同一文件夹架构中包含数十个其他文件即可启动,从而使它们更加可移植。

在此示例中,我发现 HP 相关的二进制文件在将自定义 VERSION.dll 放置在同一文件夹中时似乎容易受到侧面加载的影响。然而,就 OPSEC 而言,version.dll 是常见的检测目标,如果可能的话,应在现实生活场景中避免使用。

查找可劫持的导出函数

然后,使用API Monitor(有些人更喜欢在这里使用Frida,但在这种情况下,我发现使用这个工具更容易),可以通过过滤从目标DLL中看到原始签名进程调用了哪些函数在 GetProcAddress 和 LoadLibrary 函数调用上。这里,在目标 DLL 中查找了三个函数。

在原始进程中实现DLL注入加载

在我在本文开头描述的用例中,理想的做法是劫持第一个被调用的函数并直接跳转到 shellcode,从而无需重新实现原始 DLL 中的任何内容。

在这种情况下,通过 Microsoft 的VerQueryValueW文档,可以确认首先调用哪一个:“从指定的版本信息资源中检索指定的版本信息。要检索适当的资源,在调用 VerQueryValue 之前,必须首先调用GetFileVersionInfoSize函数,然后调用GetFileVersionInfo函数。” 这也与 API Monitor 中看到的相符。

编写有效负载

现在我知道应该给 DLL 起什么名称,以及使用哪个导出函数名称。现在是编写恶意代码并编译它的时候了。

为此,唯一重要的是模仿原始函数签名。在本例中,由于它来自系统 DLL,因此可以在 MSDN 上找到函数签名。

在原始进程中实现DLL注入加载

由于个人喜好,当前示例将使用 Nim-Lang 等效项。这是最终的代码:

在原始进程中实现DLL注入加载

在此版本中,初始化时 DllMain 中没有执行任何操作,但本地注入代码将在调用“GetFileVersionInfoSizeW”后不久执行。

编译后,最好确保 DLL 正确导出所需的函数:

在原始进程中实现DLL注入加载

欺骗编译器

有时,就像本示例中的情况一样,编译器将阻止编译,因为导出的目标函数名称已在其文件之一中定义:

在原始进程中实现DLL注入加载

规避此问题的简单方法是在编译器文件中临时注释该函数,然后重试。如果从Linux交叉编译,需要修改以下文件:/usr/share/mingw-w64/include/winver.h

在原始进程中实现DLL注入加载

生成的文件:

在原始进程中实现DLL注入加载

结论

使用这种方法,我发现在原始进程中成功实现 DLL 侧加载,同时始终避免 DllMain 及其死锁限制是微不足道的。

如果您一直在为此苦恼,或者刚刚开始使用 DLL 侧面加载,我希望这可以节省您的时间。享受你的贝壳吧!

在原始进程中实现DLL注入加载

原文翻译自:

https://www.okiok.com/achieving-dll-side-loading-in-the-original-process/

原文始发于微信公众号(Ots安全):在原始进程中实现DLL注入加载

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年4月27日19:18:26
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   在原始进程中实现DLL注入加载https://cn-sec.com/archives/2692606.html

发表评论

匿名网友 填写信息