Olaf Hartong - Cobalt Strike Remote Threads detection

我正在使用我的一位同事创建的一个很酷的新 C# 工具NoPowerShell。这允许攻击者从 Cobalt Strike 执行某些 PowerShell 命令,而无需使用 PowerShell 本身。
作为一名蓝队队员,我显然希望能够检测到这一点,所以我开始在实验室工作并开始寻找 Sysmon 可以帮助我的地方。由于 NoPowerShell 依靠 Process Injection 来开展业务,我开始查看“创建远程线程”事件,很快我就注意到了一些有趣的事情。
每个注入 bij Cobalt Strike 的进程都被注入到一个内存地址中,该地址从每个线程上相同的最后 4 个字节开始:
1.png
image.png
每个注入的线程都以 0B80 结尾
我已经在几台主机上进行了尝试,并更改了可延展配置文件以使用不同的目标进程,但这种行为似乎是一致的。

检测

创建用例就像上面的例子一样简单。您想搜索您的 Sysmon 数据:

  • 事件代码 / event_id 8
  • StartAddress / target_process_address 以 0B80 结尾

在此屏幕截图中,我一直在使用 PowerShell 信标,这可以是任何东西,因此将其用作指标是毫无意义的,就像目标进程一样。
我已将它整合到我的 ThreatHunting 应用程序中,该应用程序将于下周 12 月 5 日在 BlackHat EU 发布。事件的检测将如下所示:image.png
深入研究该事件将显示:

  • injection的视觉表示
  • powershell.exe 产生的所有子进程
  • 发起进程,启动信标
  • 信标traffic
  • 和远程线程事件

image.png
我将继续努力使 Cobalt Strike 不会导致此问题,并深入挖掘进程的内存部分以便能够检测到它们。

逃避

似乎有一种方法可以通过在可延展配置文件中使用以下代码来更改此默认行为:

  1. {
  2. stage
  3. transform-x86
  4. {
  5. # transform the x86 rDLL stage
  6. prepend "\x90\x90\x90\x90\x90\x90\x90\x90\x90"; # prepend 9 nops
  7. }
  8. transform-x64
  9. {
  10. # transform the x64 rDLL stage
  11. prepend "\x90\x90\x90\x90\x90\x90\x90\x90\x90"; # prepend 9 nops
  12. }
  13. }

显然这里有可能的变化。关键是你,作为一名红队队员,想要隐身。通过添加 9 个 nops,只有注入线程的 Start Address / target_process_address 的最后一个字符会改变。添加太多空字节可能会导致不稳定。
image.png

检测策略

这样做会绕过对上述规则的检测,这显然可以改变或扩大。这可能会引入更多的误报。我相信选择“0B80”仍然是一个有效的检测,大多数红队/对手不会知道这一点,因此不会改变默认值。
除了您的环境中的这种基线注入行为之外,无论如何,这并不常见,您会被数据淹没。在异常进程接收来自不常见来源的注入时创建警报。在对具有类似行为的多个主机进行折扣之前,还要注意或横向移动。
使用 Cobalt Strike Malleable 配置文件将是一个全局设置,因此注入线程的起始地址 / target_process_address 在此方法所针对的所有系统中都是相同的。
感谢 c_apt_ure、Scouby 和 mika 在他们的环境中验证检测。感谢@_vivami提供了一个可延展的配置文件来规避这一点。