Contents
前言
Cobalt Strike
作为一种后渗透工具,可以完成侦察、鱼叉式钓鱼、浏览器代理等攻击。我们知道Cobalt Strike
分为客户端和服务器两部分,服务器端被称之为Team Server。Team Server既是Beacon payload的控制器,也是Cobalt Strike提供社工功能的主机。Team Server还存储了Cobalt Strike收集的数据以及日志记录。
0x00 Beacon简介
使用过CS的师傅们都知道当我们想输入命令来和客户端进行交互时,就是通过Beacon进行实现,国内又成为信标,Beacon实际上是运行在主机系统上的一段Payload,Beacon在隐蔽信道上我们提供服务,用于长期控制受感染主机
实际渗透过程中,我们可以将其嵌入到可执行文件、添加到Word文档或者通过利用主机漏洞来传递Beacon
Beacon可以通过CS默认的HTTP、HTTPS 或 DNS实现通信,还可以通过SMB以及利用Windows 命名管道的方式实现通信,可以理解为Beacon就是整个CS框架中的有效载荷,用于APT攻击,因为在进行命令传递通信时都需要Beacon的绝对参与
借用Gcow团队的关于Beacon工作原理的图:

需要注意的是在这里我认为整个CS的框架体系可以划分为3个部分,Beacon端、TeamServer端、以及Aggressor登录端
简单来说,所谓Beacon段也就是在渗透测试过程中所控制的机器,而TeamServer段也就是控制方,或者说是Beacon端的交互对象,Aggressor端就是一个TeamServer端的登录实现,CS是一个团队后渗透工具,跨空间的登录到同一个TeamServer端就是通过Aggressor端实现的
在CS的解释文档中提到Beacon支持两种通信:
– 1.异步通信通信频率低、速度慢,Beacon会主动请求任务列表、然后进入SLEEP状态
– 2.交互式通信,交互式通信是实时发生的
Beacon的主要工作为:
使用HTTP或DNS检查是否有待执行任务
可连接到多个C2域名
能够在分段传输后自动迁移
与Cobalt Strike紧密集成,通过社工、主机漏洞和会话来传递Beacon
Stage和Unstage
很多攻击框架都是使用分段的shellcode,以防止shellcode过长,覆盖到了上一函数栈帧的数据,导致引发异常,在CS中提供了两种方式,分段shellcode则选取的是Stager,stager是一段很精短的代码,它可以连接下载真正的payload并将其注入内存。
而Unstage相反,可以理解为它是一个集合,就是一个不分阶段的Payload,也可以称之为Stageless,有关两者的详细区别和实现原理可以参考:
https://cloud.tencent.com/developer/news/335831
CS中对于这两种方式都是支持的:

0x01 Beacon实现方式
在CS 4.3中内置Listener分类可以分为:
1. HTTP and HTTPS Beacon
2. DNS Beacon
3. SMB Beacon
4. TCP Beacon
Listener是用来接收Beacon请求信息的Cobalt Strike模块
在其源码中我们也能看到:

根据Payload的选择实现了3种方式,这里我们就介绍上述所说的部分实现方式
1.1 HTTP和HTTPS Beacon
先通过一张图来说明HTTP/S Beacon实现流程:

我们知道如果Beacon端刚上线时是会想TeamServer端发送主机相关信息的,这里将其称为Beacon session的元数据(Metadata)
元数据 Metadata
元数据的格式解析在process_beacon_metadata
方法中,这里贴一下对应的实现:

至于这里为何存在AES密钥相关和RSA加解密,在后面的代码分析中我们再来提这个问题,现在先继续分析元数据相关

因此对元数据的相关解析都在BeaconEntry
方法中实现,继续跟进:

如果想知道元数据的结构和相关字段究竟是什么?不妨继续向下阅读
AES和RSA的相关说明
前文提到在解析过程中会有AES密钥相关和RSA加解密相关的操作,最终都是定位到AsymmetricCrypto
类中:

在服务端启动CS后如果细心会发现存在.cobaltstrike.beacon_keys
,并且如果我们使用类似CrossC2
等工具是必须要提供.cobaltstrike.beacon_keys
文件的,它是一段序列化后的数据,.cobaltstrike.beacon_keys
文件里存储了一个序列化对象这个对象中包含着一个密钥对里面存储着RSA公私钥
Beacon的元数据传输过程通过非对称密钥算法RSA实现,而Beacon传输的任务信息是通过AES加密的,AES密钥则是Beacon随机生成的然后通过RSA进行交换,这也符合HTTPS的通信原理和流程
RSA加密用于加密此元数据,Beacon拥有C2的RSA公钥,而C2拥有RSA私钥。
由于新版和旧版CS有一定差异,这里借用wbglil师傅的一张图:

因此我们可以通过利用解密的方式从该文件中提取出RSA的公私钥
https://github.com/WBGlIl/CS_Decrypt

因此利用得到的公私钥就能够解密得到会话密钥,即AES的密钥,通信数据都是通过AES密钥进行加密
由于本地环境是HTTPS的Beacon,解密起来比较复杂,还需要得到协商秘钥等,这里直接借用使用HTTP Beacon解密得到的元数据:

HTTP/S Beacon接收任务
这里主要以HTTP作为样例进行说明,接收任务相关代码在BeaconHTTP中:

encrypt方法主要是用于对任务数据进行加密,Beacon id
用于获取Beacon会话对应AES密钥,然后使用AES加密任务数据

获取当前系统时间/1000、data长度、data数据并将其写入var3,然后进行aes加密,密钥为BeaconEnrty中保存好的:

这样将数据发送至Beacon端接收后,其执行完任务在休眠时间结束后,在HTTP Beacon
中通过POST请求进行回传,在整个任务的交换过程中用的是AES算法
HTTP/S Beacon回传任务
对于回传的处理同样在HTTPBeacon中实现,我们来看一下其中的操作:

其中调用process_beacon_data
方法,跟进发现该函数最终会进行回调,根据Beacon ID
和加密数据进行解密,最终得到明文的返回结果:

process_beacon_callback
方法调用callback_decrypted
方法回调,最终会通过返回数据的特征值来判断输出在Beacon控制台中的值,例如var16==3
则表示进行截图操作,如果成功会在Beacon栏中输出screenshot相关语句,var16==30
表示shell命令,则直接将结果输出在Beacon控制台
1.2 DNS Beacon
相对于HTTP/S Beacon
来说,DNS Beacon在绕过防火墙方面比较具有优势,内网的主机出网在严格,也不会禁止起到DNS作用的53端口出网,因此我们可以通过将Beacon部署在DNS中,使用DNS来完成Beacon check in
的工作
当DNS返回的记录解析为需要执行的任务时,在通过HTTP来完成获取任务过程,借用Gcow团队的图:

原理
使用DNS Beacon的原理简单分为以下几点:
– 1.首先我们申请一个域名,我们需要将该域名的一个子域名设置一个A记录指向对应TeamServer的IP地址
– 2.需要添加一个NS记录,主机记录可以是dns,记录域名就是刚刚设置A记录的子域名(NS记录就是将解析任务交由一个指定的”权威”dns服务器)
– 3.当该域名的其它子域名时,进行递归查询,查询域名发现存在一个子域名负责解析,并且该子域名存在A记录,对应到TeamServer端的IP
– 4.此时便会和该IP进行通信
不过在使用DNS Beacon
进行测试时发现域名没备案没办法解析到Vps的IP上,如果要通过这种方式,最好使用备案的域名或者不需备案的域名等方式
0x02 Beacon的一些安全性考虑
在前文的代码中,我们可以知道在Cobalt Strike
中使用公私钥对的方式来保证传输的安全性,下面我们以分段传输payload为例,详细讲解一下Cobalt Strike的安全特性。
1.传输Beacon时
关于Beacon Payload的生成在BeaconPayload.java
中出现:

也就是说当下载Stager时,RSA公钥也会一起被传输到Beacon

本部分的模拟图均出自Gcow安全团队:

2.当Beacon准备check in
时,第一步就是要发送关于beacon session的元数据(Metadata)元数据中包含了用户、PID、电脑名称、IP地址等等基础信息,同时元数据中也包括了Beacon stage创建的一个随机会话密钥,即AES Key,这个密钥是通过RSA的公钥进行加密的,因此只有TeamServer才能解密和Beacon共享这个会话密钥
元数据是根据可扩展的C2配置文件的设置进行调整和发送的,在HTTP Beacon每次回连发送元数据请求任务时使用的GET方式中:

使用这种方式的好处就是允许操作者自定义流量的各种属性,例如元数据的发送位置(例如,在Header头或cookie中)以及如何对其进行编码
例如在如下的profile示例中:
Malleable C2 Config
http-get {
set uri "/foobar";
client {
metadata {
base64;
prepend "user=";
header "Cookie";
}
}
定义了将以Base64编码将元数据发送为名为user
的Cookie

有关Beacon生成相关元数据回连的分析放在之后进行,不过我们从解密得到的元数据信息中也能看到对应的密钥:

流程图如下所示:

3.TeamServer传输任务和Beacon将任务结果回传过程中都会通过会话密钥(AES Key)进行加密

其中传输任务对应的应该是GetHandler中的serve:

而后者需要分析Beacon的加载执行过程,之后我们在对其进行分析
4.对应返回任务结果的同时,TeamServer会将任务结果进行解密,和Beacon会将传输加密的任务列表进行解密然后执行对应任务

0x03. 总结
本文是对于Cobalt Strike
相关结构的初探,重点是掌握Beacon的相关原理以及传输过程中一些安全性问题的考虑,后续会逐步深入的对例如Aggressor登录端通信过程
、Beacon加载过程
等流程进行分析,后续也会进行CS的二次开发等工作
参考文章:
https://cloud.tencent.com/developer/article/1595094
https://bbs.pediy.com/thread-267208.htm#msg_header_h1_3
https://wbglil.gitbook.io/cobalt-strike/cobalt-strike-yuan-li-jie-shao/payload-sheng-cheng