NVISO Labs - Cobalt Strike解密系列

【收集翻译】NVISO Labs

Cobalt Strike: Using Known Private Keys To Decrypt Traffic – Part 1

我们为 Cobalt Strike 软件找到了 6 个私钥,可用于 C2 网络流量解密。
Cobalt Strike Beacon(客户端)和 Cobalt Strike 团队服务器 (C2) 之间的通信使用 AES 加密(即使它通过 HTTPS 进行)。AES 密钥由Beacon生成,并使用加密的元数据 blob(默认为 cookie)与 C2 通信。
RSA 加密用于加密此元数据:Beacon拥有 C2 的公钥,而 C2 拥有私钥。
image.png
图 1:C2 流量
公钥和私钥存储在文件 .cobaltstrike.beacon_keys 中。这些密钥是在第一次使用 Cobalt Strike 团队服务器软件时生成的。
在我们对面向互联网的 Cobalt Strike 服务器进行指纹识别期间,我们发现了许多不同服务器使用的公钥。这意味着他们使用相同的私钥,因此他们的 .cobaltstrike.beacon_keys 文件是共享的。
我们验证了一种可能的解释:恶意行为者使用的 Cobalt Strike 是否存在包含 .cobaltstrike.beacon_keys 的破解版本?这个文件不是合法的 Cobalt Strike 包的一部分,因为它是在第一次使用时生成的。
通过 VirusTotal 搜索,我们发现了 10 个破解的 Cobalt Strike 软件包:ZIP 文件,其中包含一个名为 .cobaltstrike.beacon_keys 的文件。在这 10 个包中,我们提取了 6 个唯一的 RSA 密钥对。
其中 2 个密钥对在 Internet 上很流行:我们指纹识别的 Cobalt Strike 服务器中有 25%(1500 多个)使用这 2 个密钥对之一。
此关键信息现在包含在🛠工具1768.py🛠中,该工具由 Didier Stevens 开发,用于提取 Cobalt Strike Beacon的配置。
每当使用已知私钥提取公钥时,该工具都会突出显示:
image.png
图 2:1768.py 从Beacon中提取配置
至少,此信息进一步确认样本来自流氓 Cobalt Strike 服务器(而不是红队服务器)。
使用选项详细,还会显示私钥。
image.png
图 3:使用选项详细显示私钥
然后可以使用它来解密元数据和 C2 流量(稍后会详细介绍)。
image.png
图 4:解密元数据
在接下来的博客文章中,我们将详细展示如何使用这些私钥来解密元数据和解密 C2 流量。

Cobalt Strike: Using Known Private Keys To Decrypt Traffic – Part 2

在这篇博文中,我们将通过查看感染期间捕获的完整数据包来分析 Cobalt Strike 感染。此分析包括解密 C2 流量。
如果您还没有阅读,我们邀请您先阅读第 1 部分:Cobalt Strike:使用已知私钥解密流量 – 第 1 部分
对于此分析,我们使用捕获文件2021-02-02-Hancitor-with-Ficker-Stealer-and-Cobalt-Strike-and-NetSupport-RAT.pcap.zip,这是众多恶意软件流量捕获文件之一Brad Duncan 在他的网站Malware-Traffic-Analysis.net 上分享
我们从最少的知识开始:捕获文件包含 Cobalt Strike Beacon与其团队服务器通信的加密 HTTP 流量。
如果您想了解更多关于 Cobalt Strike 及其组件的信息,我们强烈推荐以下博客文章

第一步:我们用 Wireshark 打开捕获文件,并通过 stager shellcode 查找完整Beacon的下载。
尽管Beacon可以有多种形式,但我们可以确定两大类:

  1. 一小段 shellcode(几百字节),又名 stager shellcode,用于下载完整的Beacon
  2. 完整的Beacon:一个可以反射加载的PE文件

在第一步中,我们在捕获文件中搜索 stager shellcode 的迹象:我们使用以下显示过滤器执行此操作:http.request.uri 匹配“/….$”。
image.png
图 1:Cobalt Strike 流量的数据包捕获
我们一击必中。GET 请求中用于下载完整Beacon的路径由 4 个满足条件的字符组成:字符值总和的字节值(又名校验和 8)是一个已知常量。我们可以使用🛠工具metatool.py🛠进行检查,如下所示:
image.png
图 2:使用 metatool.py
可以在此处找到有关此校验和过程的更多信息。
该工具的输出显示这是下载 32 位完整Beacon (CS x86) 的有效路径。
完整Beacon的下载也被捕获:
image.png
图 3:完整的Beacon下载
我们可以提取这个下载:
image.png
图 4:导出 HTTP 对象
image.png
图 5:选择下载 EbHm 进行保存
image.png
图 6:将选定的下载保存到磁盘
一旦完整的Beacon作为 EbHm.vir 保存到磁盘,就可以使用🛠工具 1768.py🛠对其进行分析。1768.py 是一个可以解码/解密 Cobalt Strike Beacon并提取其配置的工具。Cobalt Strike Beacon有许多配置选项:所有这些选项都存储在一个编码和嵌入的表中。
这是分析的输出:
image.png
图 7:提取Beacon配置
让我们仔细看看其中的一些选项。
首先,选项 0x0000 告诉我们这是一个 HTTP Beacon:它通过 HTTP 进行通信。
它通过连接到端口 8080(选项 0x0002)上的 192.254.79[.]71(选项 0x0008)来实现。
GET 请求使用路径 /ptj(选项 0x0008),POST 请求使用路径 /submit.php(选项 0x000a)
并且对我们的分析很重要:对于这个Beacon使用的公钥,有一个已知的私钥(Has known private key) (选项 0x0007)。
因此,有了这些信息,我们知道Beacon将向团队服务器发送 GET 请求,以获取指令。如果团队服务器有Beacon要执行的命令,它将以加密数据回复 GET 请求。当Beacon必须将其命令的输出发送回团队服务器时,它将使用带有加密数据的 POST 请求。
如果团队服务器没有针对Beacon的命令,则不会发送加密数据。这并不一定意味着对 GET 请求的回复不包含任何数据:运营商可以通过配置文件伪装通信。例如,加密数据位于 GIF 文件中。但这个Beacon并非如此。我们知道这一点,因为在这个配置文件中没有所谓的可塑性 C2 指令:选项 0x000b 等于 0x00000004 -> 这意味着在解密之前不应对数据执行任何操作(我们将在稍后详细解释这一点博文)。
让我们创建一个显示过滤器来查看这个 C2 流量:http 和 ip.addr == 192.254.79[.]71
image.png
图 8:完整的Beacon下载和带有加密 Cobalt Strike 流量的 HTTP 请求
这将显示进出团队服务器的所有 HTTP 流量。请注意,我们已经查看了此视图中的前 2 个数据包(数据包 6034 和 6703):这是Beacon本身的下载,并且通信未加密。因此,我们将使用以下显示过滤器过滤掉这些数据包:
http 和 ip.addr == 192.254.79.71 和 frame.number > 6703
这为我们提供了 GET 请求及其回复的列表。请注意,每分钟都有一个 GET 请求。这也在Beacon配置中:60.000 毫秒的睡眠(选项 0x0003),变化为 0%(又名抖动,选项 0x0005)。
image.png
图 9:带有加密 Cobalt Strike 流量的 HTTP 请求
我们现在将遵循第一个 HTTP 流:
image.png
图 10:跟随 HTTP 流
image.png
图 11:第一个 HTTP 流
这是对 /ptj 的 GET 请求,它收到一个没有数据的 STATUS 200 回复。这意味着目前没有来自团队服务器的此Beacon的命令:操作员在捕获文件中的那个点没有发出任何命令。
备注 GET 请求的 Cookie 标头。这看起来像一个BASE64字符串:

  1. KN9zfIq31DBBdLtF4JUjmrhm0lRKkC / I / zAiJ + Xxjz787h9yh35cRjEnXJAwQcWP4chXobXT / E5YrZjgreeGTrORnj // A5iZw2TClEnt ++ gLMyMHwgjsnvg9czGx6Ekpz0L1uEfkVoo4MpQ0 / kJk9myZagRrPrFWdE9U7BwCzlE =

该值是Beacon作为 BASE64 字符串发送到团队服务器的加密元数据。此元数据使用Beacon配置中的公钥(选项 0x0007)进行 RSA 加密,并且团队服务器可以解密此元数据,因为它具有私钥。请记住,一些私钥已经“泄露”,我们在本系列的第一篇博文中讨论了这一点
我们的Beacon分析表明,该Beacon使用具有已知私钥的公钥。这意味着我们可以使用🛠工具cs-decrypt-metadata.py🛠来解密元数据(cookie),如下所示:
image.png
图 12:解密Beacon元数据
我们可以在这里看到解密的元数据。对我们来说非常重要的是原始密钥:caeab4f452fe41182d504aa24966fbd0。
我们将使用此密钥来解密流量(AES 和 HMAC 密钥源自此原始密钥)。
我们可以在这里找到的更多元数据是:计算机名、用户名……
我们现在将跟踪带有数据包 9379 和 9383 的 HTTP 流:这是操作员(团队服务器)发送到Beacon的第一个命令:
image.png
图 13:带有加密命令的 HTTP 流
在这里我们可以看到回复包含48个字节的数据(Content-length)。该数据已加密:
image.png
图 14:带有加密命令的 HTTP 流的十六进制视图
像这样加密的数据,可以用🛠工具cs-parse-http-traffic.py🛠解密。由于数据是加密的,我们需要提供原始密钥(选项 -r caeab4f452fe41182d504aa24966fbd0)并且由于数据包捕获包含除纯 Cobalt Strike C2 流量之外的其他流量,因此最好提供一个显示过滤器(选项 -Y http 和 ip. addr == 192.254.79.71 and frame.number > 6703) 以便该工具可以忽略所有非 C2 流量的 HTTP 流量。
这会产生以下输出:
image.png
图 15:解密的命令和结果
现在我们可以看到数据包9383中的加密数据是一条sleep命令,sleeptime为100ms,抖动系数为90%。这意味着操作员指示Beacon与Beacon交互。
解密的数据包9707包含一个未知命令(id 53),但是当我们查看数据包9723时,我们看到一个目录列表输出:这是发送回团队服务器的未知命令53的输出结果(注意POST url /提交.php)。因此可以安全地假设命令 53 是一个目录列表命令。
这个抓包文件中有很多命令和结果,工具cs-parse-http-traffic.py可以解密,这里就不一一展示了。但我们邀请您重现此博文中的命令,并查看该工具的输出。
捕获文件中的最后一个命令是进程列表命令:
image.png
图 16:解密的进程列表命令和结果

结论

虽然我们在这里解密的抓包文件是 Brad Duncan 在半年前通过在沙箱中运行恶意 Cobalt Strike Beacon生成的,但我们今天可以解密它,因为运营商使用了一个包含私钥的流氓 Cobalt Strike 包,即我们从 VirusTotal 中恢复。
如果没有这个私钥,我们将无法解密流量。
私钥不是解密流量的唯一方法:如果可以从进程内存中提取 AES 密钥,我们也可以解密流量。我们将在即将发布的博客文章中介绍这一点。