CobaltStrike逆向学习系列(4):Beacon 上线协议分析
字数 1269 2025-08-07 08:22:12

CobaltStrike逆向学习系列(4): Beacon上线协议分析

0x00 概述

本文详细分析CobaltStrike中Beacon与TeamServer之间的上线协议交互过程,包括Beacon端的发送流程和TeamServer端的处理逻辑。

0x01 Beacon发送流程

1. 通信初始化

Beacon使用Windows API进行HTTP通信,调用顺序如下:

  1. InternetOpenA - 初始化通信环境,传入agent标识
  2. InternetConnectA - 建立连接,传入C2服务器的IP和端口
  3. HttpOpenRequestA - 准备HTTP请求,指定请求类型和URI
  4. HttpSendRequestA - 发送请求,此时COOKIE已被加密

2. 信息收集与加密

在进入功能性while循环之前,Beacon已完成以下操作:

  • 信息收集
  • 数据加密

3. C2Profile解析

加密前会从C2Profile中取出public key,具体流程:

  1. 通过index(7)从BeaconPayload中获取public key
  2. 调用GetPtrValue函数获取值

GetValue函数逻辑:

  • 根据index跳转到对应偏移
  • 前8字节判断类型
  • 后8字节取出实际值或地址

0x02 TeamServer处理流程

1. 请求接收

TeamServer使用NanoHTTPD库处理HTTP请求:

  • 自定义WebServer类继承NanoHTTPD
  • 实现处理函数

2. 请求处理流程

  1. 请求首先进入MalleableHook.serve()
  2. 实际调用BeaconHTTP.serve()进行解析
  3. 检查数据长度是否为128位

3. 解密过程

  1. 初始化私钥
  2. 进行解密操作
  3. 检查标志位0xBEEF(48879)
  4. 读取长度并验证(<117字节)
  5. 返回剩余字符

4. 元数据处理

  1. 保留前16字节作为关键数据
  2. 16-20字节判断字符集
  3. 获取Listener名称
  4. 初始化BeaconEntry

5. 密钥注册

调用getSymmetricCrypto().registerKey方法:

  1. 传入前16字节作为密钥
  2. 检查BeaconId是否存在(首次上线不存在)
  3. 对16字节进行SHA-256哈希:
    • 前16字节作为AESKey
    • 后16字节作为HmacSHA256Key
  4. 将密钥与BeaconId存入Map

6. 响应返回

最后调用sendResponse返回信息给Beacon

0x03 流程图

Beacon端:
1. 收集信息 -> 加密数据 -> 构造HTTP请求 -> 发送

TeamServer端:
1. 接收请求 -> 解析数据 -> 解密 -> 验证标志位
2. 处理元数据 -> 注册密钥 -> 返回响应

0x04 关键点总结

  1. Beacon使用标准Windows API进行HTTP通信
  2. 上线前已完成信息收集和加密
  3. C2Profile通过index机制获取配置项
  4. TeamServer使用NanoHTTPD处理请求
  5. 上线数据包含128位加密信息和特定标志位
  6. 前16字节用于生成AES和HMAC密钥
  7. TeamServer维护BeaconId与密钥的映射关系

0x05 参考实现

Beacon加密数据格式:

[128位加密数据]
[标志位: 0xBEEF]
[长度字段]
[剩余数据]

TeamServer密钥生成:

byte[] hash = SHA256.digest(inputKey);
byte[] aesKey = Arrays.copyOfRange(hash, 0, 16);
byte[] hmacKey = Arrays.copyOfRange(hash, 16, 32);
CobaltStrike逆向学习系列(4): Beacon上线协议分析 0x00 概述 本文详细分析CobaltStrike中Beacon与TeamServer之间的上线协议交互过程,包括Beacon端的发送流程和TeamServer端的处理逻辑。 0x01 Beacon发送流程 1. 通信初始化 Beacon使用Windows API进行HTTP通信,调用顺序如下: InternetOpenA - 初始化通信环境,传入agent标识 InternetConnectA - 建立连接,传入C2服务器的IP和端口 HttpOpenRequestA - 准备HTTP请求,指定请求类型和URI HttpSendRequestA - 发送请求,此时COOKIE已被加密 2. 信息收集与加密 在进入功能性while循环之前,Beacon已完成以下操作: 信息收集 数据加密 3. C2Profile解析 加密前会从C2Profile中取出public key,具体流程: 通过index(7)从BeaconPayload中获取public key 调用 GetPtrValue 函数获取值 GetValue 函数逻辑: 根据index跳转到对应偏移 前8字节判断类型 后8字节取出实际值或地址 0x02 TeamServer处理流程 1. 请求接收 TeamServer使用NanoHTTPD库处理HTTP请求: 自定义WebServer类继承NanoHTTPD 实现处理函数 2. 请求处理流程 请求首先进入 MalleableHook.serve() 实际调用 BeaconHTTP.serve() 进行解析 检查数据长度是否为128位 3. 解密过程 初始化私钥 进行解密操作 检查标志位0xBEEF(48879) 读取长度并验证( <117字节) 返回剩余字符 4. 元数据处理 保留前16字节作为关键数据 16-20字节判断字符集 获取Listener名称 初始化BeaconEntry 5. 密钥注册 调用 getSymmetricCrypto().registerKey 方法: 传入前16字节作为密钥 检查BeaconId是否存在(首次上线不存在) 对16字节进行SHA-256哈希: 前16字节作为AESKey 后16字节作为HmacSHA256Key 将密钥与BeaconId存入Map 6. 响应返回 最后调用 sendResponse 返回信息给Beacon 0x03 流程图 0x04 关键点总结 Beacon使用标准Windows API进行HTTP通信 上线前已完成信息收集和加密 C2Profile通过index机制获取配置项 TeamServer使用NanoHTTPD处理请求 上线数据包含128位加密信息和特定标志位 前16字节用于生成AES和HMAC密钥 TeamServer维护BeaconId与密钥的映射关系 0x05 参考实现 Beacon加密数据格式: TeamServer密钥生成: