LoginSignup
0
0

More than 3 years have passed since last update.

[翻译]CobaltStrike 使用Beacon Object Files(BOF)进行 Direct Syscalls

Last updated at Posted at 2020-12-31

原文链接:https://outflank.nl/blog/2020/12/26/direct-syscalls-in-beacon-object-files/
原文作者:Cornelis de Plaa

在这篇文章中,我们将探讨在Cobalt Strike使用BOF进行直接系统调用(direct system calls)。具体来说:

  1. 说明如何在Cobalt Strike BOF中使用直接系统调用来规避典型的AV和EDR检测。
  2. 发布InlineWhispers:一个脚本,使在BOF代码中使用Direct Syscalls更加容易。
  3. 提供概念验证BOF代码,该代码可用于通过修补LSASS进程内存来启用WDigest凭据缓存和规避凭据保护。

PoC的源代码可以在这里找到:https://github.com/outflanknl/WdToggle

InlineWhispers的源代码可以在这里找到:https://github.com/outflanknl/InlineWhispers

Beacon Object Files

Cobalt Strike最近引入了一个新的代码执行概念,叫做 Beacon Object Files(以下简称为BOF)。这使Cobalt Strike可以在Beacon进程中执行一小段已编译的C代码。

这有什么好处?最重要的是,我们摆脱了名为fork&run的概念。在BOF出来之前,fork&run是在Cobalt Strike中运行作业的默认机制。这意味着为了执行大多数开发后功能,将启动一个牺牲进程(使用spawnto参数指定),随后将攻击的payload作为反射DLL注入该过程。从AV、EDR的角度来看,它具有可以检测到的各种特征,例如进程产生,进程注入和内存中的反射DLL。在许多现代环境中,fork&run很容易演变成OPSEC(行动安全Operations security)的灾难。使用BOF,我们可以在Beacon当前过程的上下文中运行与位置无关的已编译代码,这更加隐蔽。

尽管BOF概念的引入对于在后渗透开发中绕过AV、EDR迈出了重大一步,但我们仍然需要面对AV、EDR产品HOOK系统API的问题。在2019年6月,我们发布了有关Direct Syscalls的博客文章,并展示了一个如何使用它绕过AV、EDR软件的示例。到目前为止,我们还没有看到Direct Syscalls在BOF的利用,因此我们决定编写自己的实现并在此博客文章中分享我们的经验。

Direct syscalls和BOF的实用性

现在很多红队都熟悉关于Direct Syscalls对绕过API HOOK的概念。在我们以前对Direct Syscalls的文章中,我们展示了如何在Visual Studio中利用Microsoft汇编程序(MASM)在C/C++项目中包含 Direct Syscalls。当我们构建一个包含汇编代码的Visual Studio项目时,它将使用汇编器和C编译器生成两个目标文件,并将所有片段链接在一起以形成一个可执行文件。

要创建BOF文件,我们使用C编译器来生成单个目标文件。如果要在BOF项目中包含汇编代码,则需要进行内联汇编以生成单个目标文件。不幸的是,Visual Studio不支持x64处理器的内联汇编,因此我们需要另一个C编译器,它支持x64处理器的内联汇编。

Mingw-w64和内联ASM

Mingw-w64 是GCC编译器的Windows版本,可用于创建32位和64位Windows应用程序。它可以在Windows,Linux或任何其他基于Unix的操作系统上运行。最重要的是,它甚至对于x64处理器也支持内联汇编。因此,现在我们需要了解如何在BOF源代码中包含汇编代码。

如果我们看一下Mingw-w64或GCC编译器的手册页,我们会注意到它支持使用-masm=dialect语法进行汇编。
image.png

使用intel语言,我们能够像在Visual Studio中使用Microsoft Assembler一样通过相同的语言编写汇编代码。要将内联汇编包含在我们的代码中,我们可以简单地使用以下汇编器模板语法:

        asm("nop \n  "
            "nop \n  "
            "nop")
  1. 起始asm关键字是asm__asm__
  2. 指令必须用换行符分隔。

有关GCC汇编程序语法的更多信息,请参见以下指南:https://www.felixcloutier.com/documents/gcc-asm.html#assembler-template

__asm__到BOF

下面的示例显示使用内联汇编(inline-assembly)的NtCurrentTeb()的自定义版本。这个例子可用于返回指向当前线程的Thread Environment Block (TEB)的指针,然后可将其用于解析为指向ProcessEnvironmentBlock(PEB)的指针:

image.png

为了使此汇编函数在我们的C代码中可用并声明其名称,返回类型和参数,我们使用EXTERN_C关键字。该预处理程序宏指定该函数在其他位置定义,具有C链接并使用C语言调用约定。这种方法还可以用于在我们的代码中包括汇编系统调用函数。只需将以汇编形式编写的系统调用转换为汇编器模板语法,使用EXTERN_C关键字添加函数定义,然后将其保存在头文件中即可,该文件可以包含在我们的项目中。

尽管在头文件中实现函数是完全有效的,但这并不是最佳实践。然而,使用-o选项编译目标文件只允许我们使用一个源文件,因此为了不使我们的主源文件带有汇编函数,我们将它们放在单独的头文件中。

要编译包含内联汇编的BOF源代码,我们使用以下编译器语法:

x86_64-w64-mingw32-gcc -o bof.o -c bof.c -masm=intel 

WdToggle

为了演示整个概念,我们编写了概念验证代码,其中包括使用内联汇编的Direct Syscalls,并且可以编译为BOF文件。

此代码显示了如何通过在Lsass进程(wdigest.dll模块)中将g_fParameter_UseLogonCredential全局参数切换为1来启用WDigest凭据缓存。此外,可以通过在lsass进程中将g_IsCredGuardEnabled变量切换为0来绕过凭据保护(如果启用)。

这两个技巧都使我们能够在LSASS中使纯文本密码再次可见,因此可以使用Mimikatz抓取它们。使用 UseLogonCredential补丁后,您只需要用户锁定和解锁其会话即可使明文密码凭据再次可用。

image.png

此PoC基于Hydra团队@_xpn_@N4kedTurtle的以下精彩博客文章。这些博客是必读且包含所有必要的详细信息:

  1. 探索Mimikatz –第1部分– WDigest
  2. 绕过凭据守卫

这两个博文都包含用于patch LSASS的PoC代码,因此从这个角度来看,我们的代码并不是什么新东西。我们的PoC以此工作为基础,并且仅演示了如何利用BOF中的Direct Syscalls来提供一种更安全的与LSASS流程进行交互并绕过Cobalt Strike的API hook的OPSEC安全方式。

补丁程序限制

此POC是内存补丁,因此重启后必须重新运行代码。此外,wdigest.dll模块中g_fParameter_UseLogonCredentialg_IsCredGuardEnabled全局变量的内存偏移量可能会在Windows版本和修订版之间发生变化。我们为代码中的不同内部版本提供了一些偏移,但是这些偏移会在将来的版本中更改。您可以添加自己的版本偏移量,可以使用Windows调试器工具找到该偏移量。(译者注:不同版本的Windows需要patch的偏移量不同)

防御

为了通过LSASS内存访问来检测凭证盗窃,我们可以使用Sysmon之类的工具来监视打开LSASS句柄的处理。我们可以监视访问LSASS进程的可疑进程,从而创建遥测来检测可能的凭证转储活动。

当然,还有更多选项可用于检测凭据盗用,例如,使用Windows Defender ATP之类的高级检测平台。但是,如果您没有使用这些新颖平台的预算,那么Sysmon是可以帮助填补空白的免费工具。

InlineWhispers

在发布直接系统调用博客文章几个月后,@Jackson_T发布了一个名为SysWhispers的出色工具。

“SysWhispers helps with evasion by generating header/ASM files implants can use to make direct system calls”.
“SysWhispers通过生成植入程序可用来进行直接系统调用的header/ASM文件来帮助规避AV”。

这是一个很棒的工具,它可以自动为任何系统调用生成标头/ ASM对,然后可以在定制的Red Teaming工具中使用它。

该工具生成的.asm输出文件可以在Microsoft Studio中使用Microsoft宏汇编器使用。 如果要在BOF项目中使用从SysWhispers输出生成的Direct Syscalls,则需要某种转换,以便它们与汇编器模板语法匹配。

我们的同事@_DaWouw 编写了一个Python脚本,可用于将SysWhispers生成的.asm输出文件转换为适合BOF项目的输出文件。

它转换输出以匹配汇编模板语法,因此可以从您的BOF代码中使用这些函数。我们可以手动输入在BOF中使用了哪些系统调用,以防止包括未使用的系统功能。该脚本可在Github页面上的InlineWhispers存储库中找到:

概要

在此博客中,我们展示了如何在Cobalt Strike BOF中使用Direct Syscalls。要使用 Direct Syscalls,我们需要使用汇编程序模板语法编写汇编程序,因此我们可以将汇编函数包括在内联汇编中。Visual Studio不支持x64处理器的内联汇编,但是幸运的是Mingw-w64支持。

为了演示在BOF中进行Direct Syscalls的用法,我们编写了概念验证代码,可用于启用WDigest凭据缓存。此外,我们编写了一个名为InlineWhispers的脚本,该脚本可用于将SysWhispers生成的.asm输出转换为适合BOF项目的内联汇编头文件。

我们希望该博文有助于理解如何在BOF项目中实施Direct Syscalls以提高OPSEC安全性。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0