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通信,调用顺序如下:
InternetOpenA- 初始化通信环境,传入agent标识InternetConnectA- 建立连接,传入C2服务器的IP和端口HttpOpenRequestA- 准备HTTP请求,指定请求类型和URIHttpSendRequestA- 发送请求,此时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 流程图
Beacon端:
1. 收集信息 -> 加密数据 -> 构造HTTP请求 -> 发送
TeamServer端:
1. 接收请求 -> 解析数据 -> 解密 -> 验证标志位
2. 处理元数据 -> 注册密钥 -> 返回响应
0x04 关键点总结
- Beacon使用标准Windows API进行HTTP通信
- 上线前已完成信息收集和加密
- C2Profile通过index机制获取配置项
- TeamServer使用NanoHTTPD处理请求
- 上线数据包含128位加密信息和特定标志位
- 前16字节用于生成AES和HMAC密钥
- 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);