导语:BYOL提供了一种强大的新技术,可以让红队在交战中不被发现,并且可以轻松地与Cobalt Strike的“execute-assembly”命令一起使用。
一、简介
顶级攻击行动最近最重要的进展之一是攻击者使用LotL(Living off the Land)技术。这些技术利用系统中已有的合法工具(例如PowerShell脚本语言)执行攻击。作为一种攻击性工具,PowerShell的普及最终导致了围绕它开发整个红队框架,如Empire和PowerSploit。此外,PowerShell可以通过使用诸如Invoke-Obfuscation之类的工具来混淆。作为回应,防御者已经开发出了恶意使用合法应用程序的检测技术。这些检测包括可疑的父/子进程关系,可疑的进程命令行参数,甚至通过使用脚本块记录来反混淆恶意PowerShell脚本。
在本文中,我将讨论当前LotL技术的替代方案。在Cobalt Strike的最新版本(版本3.11)中,使用execute-assembly命令可以在内存中执行.NET程序。通过开发定制的C#程序,攻击者不再需要依赖目标系统上的已有工具;他们可以改写和提供自己的工具,这是一种我称之为BYOL(Bring Your Own Land)的技术。我将通过使用重现PowerSploit项目的部分函数的自定义.NET程序演示此技术。我还将讨论如何针对BYOL开发检测技术。
二、背景
在去年的DerbyCon上,我很高兴见到了Cobalt Strike RAT(远程访问工具)的开发者Raphael Mudge。在讨论中,我提到将.NET程序加载到Cobalt Strike中是很有用的,类似于使用powershell-import命令导入PowerShell脚本的方式。在之前我参加的一次红队过程中,目标环境中主机上的终端检测和响应(EDR)agent阻止了PowerShell的使用。这是一个严重的问题,因为当时我们红队的攻击方法都是基于各种PowerShell脚本。例如,PowerView脚本的Get-NetUser cmdlet允许在Active Directory环境中枚举域用户。尽管没有使用PowerShell,但我发现目标环境中的主机上并没有应用程序的白名单。因此,我开始将PowerShell功能转换为C#代码,将程序本地编译为可执行文件(PE)文件,然后将PE文件上传到目标机器并执行它们。这种策略是成功的,我能够使用这些自定义程序来提升权限至目标环境中的域管理员。
Raphael同意Cobalt Strike信标内添加在内存中加载这些程序的功能会很有用,大约8个月后,此功能通过execute-assembly命令被整合到Cobalt Strike 3.11版本中。
三、execute-assembly示例
在本演示中,使用了一个名为“get-users”的自定义C#.NET程序。该组件重现了PowerView“Get-NetUser”cmdlet的一些功能;它查询指定域的域控制器以获取当前所有域帐户的列表。获得的信息包括每个帐户的SAMAccountName,UserGivenName和UserSurname属性。域名是通过传递其FQDN作为参数来指定的,然后将结果发送到stdout。在Cobalt Strike信标内程序执行结果如图1所示。
图1:在Cobalt Strike信标中使用“execute-assembly”命令
很简单吧,现在我们来看看此技术的工作原理。
四、execute-assembly工作原理
为了更多地了解execute-assembly命令是如何工作的,在运行ProcMon的主机上重复执行图1中的过程。ProcMon执行后的进程树结果如图2所示。
图2:执行“execute-assembly”命令后ProcMon的进程树
在图2中,powershell.exe(2792)进程包含信标,而rundll32.exe(2708)进程用于加载和执行get-users程序。请注意,本例中powershell.exe显示为rundll32.exe的父进程,因为Cobalt Strike信标是通过使用PowerShell单线程启动的;然而,通过利用各种进程迁移技术,几乎任何进程都可以用于托管信标。根据这些信息,我们可以确定execute-assembly命令与其他 Cobalt Strike post-exploitation jobs类似。在Cobalt Strike中,为了确保信标的稳定性,一些功能被载到新的进程中。rundll32.exe默认情况下使用,但可以更改此设置。为了将必要的代码迁移到新进程中,使用了CreateRemoteThread 函数。可以通过在使用Sysmon监视主机的同时执行execute-assembly命令来确认是否可以使用此功能。使用CreateRemoteThread函数生成的事件如图3所示。
图3:执行“execute-assembly”命令后创建的CreateRemoteThread Sysmon事件
有关此事件的更多信息如图4所示。
图4:图3所示的Sysmon CreateRemoteThread事件的详细信息
为了执行提供的程序,必须将CLR(公共语言运行时库)加载到新创建的进程中。从ProcMon日志中,我们可以确定在此步骤中加载的确切DLL。部分DLL如图5所示。
图5:加载到rundll32中用于托管CLR的DLL示例
另外,加载到rundll32进程中的DLL包括get-users程序所需的那些DLL,例如用于LDAP通信和Kerberos身份验证的DLL。部分DLL如图6所示。
图6:加载到rundll32以进行Kerberos身份验证的DLL示例
ProcMon日志确认所提供的程序永远不会写入磁盘,从而使execute-assembly命令成为纯内存中的攻击。
五、检测和阻止execute-assembly
有几种方法可以阻止execute-assembly命令。如前所述,由于该技术是基于Cobalt Strike框架的,因此它使用了EDR解决方案通常检测到的CreateRemoteThread函数。但是,BYOL技术的其他实现可能不需要使用CreateRemoteThread函数。
execute-assembly技术利用本地LoadImage函数来加载提供的程序。CLRGuard挂钩该函数,并阻止它的执行。CLRGuard阻止执行execute-assembly命令的示例如图7所示。
图7:CLRGuard阻止执行“execute-assembly”技术
由此产生的错误显示在图8中的Cobalt Strike teamserver上。
图8:当CLRGuard阻止“execute-assembly”时Cobalt Strike显示错误
虽然CLRGuard可有效阻止execute-assembly命令以及其他BYOL技术,但在系统上禁止使用LoadImage函数会对其他正常应用程序产生负面影响,因此不建议在实际环境中使用。
与几乎所有的安全问题一样,特征和相关性是检测这种技术的最有效手段。可关联的可疑事件包括通常不使用它的进程使用LoadImage函数,并将异常的DLL加载到进程中。
六、BYOL的优点
由于先进的攻击者普遍使用PowerShell脚本,恶意PowerShell活动的检测已成为当前检测方法的主要焦点。特别是,版本5的PowerShell允许使用脚本块记录,它能够准确记录系统执行的PowerShell脚本,而不管混淆技术如何。另外,可以使用CL(约束语言)模式来限制PowerShell功能。虽然绕过这些保护措施(如PowerShell降级攻击),但攻击者的每个绕过企图都会触发防御者的另一事件。BYOL允许执行由PowerShell脚本执行的攻击,同时完全避免所有可能的基于PowerShell的警报。
PowerShell不是唯一一个恶意使用被防御方跟踪的本地二进制文件。其他可以生成警报的常见二进制文件包括WMIC,schtasks / at和reg。由于C#代码的灵活性,所有这些工具的功能都可以在自定义.NET程序中重现。在不使用这些工具的情况下执行相同的功能,基于恶意使用的警报将无效。
最后,由于使用了反射加载,BYOL技术可以完全在内存中执行,而无需写入磁盘。
七、总结
BYOL提供了一种强大的新技术,可以让红队在交战中不被发现,并且可以轻松地与Cobalt Strike的execute-assembly命令一起使用。另外,使用C#程序可以为攻击者提供比类似的PowerShell脚本更大的灵活性。基于CLR技术的检测,例如挂钩反射性加载程序的函数,应该纳入防御之中,因为这些攻击可能随着LotL技术的检测成熟而变得更加普遍。