采用分而治之的方法来绕过EDRs
作者:Sec-Labs | 发布时间:
项目地址
https://github.com/Kudaes/Split
描述
分而治之是一种常用于编程的算法,通过将复杂问题分解为许多更简单的子问题来解决该问题。我们可以将这种方法应用于具有不同目标的攻击性安全:使用 EDR,使它们无法跟踪我们的活动,从而防止它们发出任何警报。这与最近在几乎所有野外网络钓鱼活动中都能看到的情况类似:长感染链,逐步运行多个文件(例如 .url -> .one -> .js -> .bat -> .dll)而不是直接运行最终的有效载荷。执行的每个文件都执行一项简单的任务(下载另一个文件、在注册表中进行任何更改、在目录之间移动文件或更改其名称/扩展名等),这些任务本身很难被标记为恶意,为攻击准备环境最后的执行。
我决定测试这个简单的想法,但应用于不同的东西,在本例中,是远程进程注入。这个存储库中的代码并不新鲜,相反,它可能是在远程进程中注入 shellcode 的最常见和最直接的方法之一:使用 NtOpenProcess、NtAllocateVirtualMemory、NtWriteVirtualMemory、NtProtectVirtualMemory 和 NtCreateThreadEx。唯一的区别是我在每次调用后使用 NtCreateUserProcess 分叉进程。由于分叉进程继续从 RIP + 1 执行并且内存完全从父进程复制,我们可以执行远程进程注入但使用 5 个不同的进程,我们只需要确保后续 API 调用所需的任何句柄被正确继承。
这样,我们将 shellcode 注入过程分解为更简单的任务,并在单独的上下文(进程)上运行它们中的每一个。
我已经针对当今最常见的三种 EDR 测试了此 PoC:MDE、CrowdStrike 和 SentinelOne。结果不言而喻:在没有分叉的情况下运行 PoC 时,三分之二的 EDR 发出了远程进程注入警报;相反,当我引入分叉机制后,他们都没有提出任何警告。
当然,即使使用 fork 机制,我们也可以在原始遥测中看到与进程创建、线程创建以及所有跨进程行为对应的事件,但 EDR 似乎不足以将活动标记为恶意活动,证明这个PoC的重点。通过将恶意行为拆分为更简单的任务并从不同的进程运行每个任务,我们可以混淆并防止 EDR 发出任何警报。
同样的结果可以用不同的方式实现,我只是使用 fork 机制来简化我的代码并减少跨进程活动。
如果您想自己对此进行测试,请在调用和不调用函数 fork() 的情况下编译代码,然后在具有所需 EDR 的环境中运行两个有效负载。
汇编
由于我们使用LITCRYPT插件来混淆字符串文字(仅针对 Dinvoke_rs 代码),因此需要在编译代码之前设置环境变量 LITCRYPT_ENCRYPT_KEY:
C:\Users\User\Desktop\Split> set LITCRYPT_ENCRYPT_KEY="yoursupersecretkey"
之后,只需编译代码并运行该工具:
C:\Users\User\Desktop\Split> cargo build --release
C:\Users\User\Desktop\Split\target\release> split.exe -h
限制
这种技术本身并不足以绕过 EDR;如果您的代码根本没有 opsec,那么您很可能无论如何都会被抓到。这不是金弹,只是您可以添加到工具中的另一层规避。尽管如此,由于以下原因,此存储库中提供的代码根本不是 opsec:
- 纯文本 shellcode。此外,shellcode 在执行后会生成一个 cmd。
- 不使用系统调用。
- 没有脱钩。
- Etw 未打包。
- 其他的。
另一方面,我刚刚针对提到的 EDR 测试了这种方法,我不知道其他 EDR 是否也会被绕过。你可以测试它,让我知道它是如何进行的;)
学分
- Deep Instinct的Dirty-Vanity工具和研究以及 shellcode 模板。