cobaltstrike4.5 stageless beacon 通信分析
字数 2215 2025-08-25 22:59:02

Cobalt Strike 4.5 Stageless Beacon 通信分析教学文档

1. 环境准备

1.1 调试环境搭建

  • 使用IDEA反编译Cobalt Strike并导入原jar包作为依赖进行调试跟踪
  • .cobaltstrike.beacon_keys文件中取出序列化存储的RSA公私钥

1.2 通信配置

为了便于手动解密通信数据,使用以下profile配置将所有通信数据Base64编码:

http-get {
    set uri "/ca /dpixel /__utm.gif /pixel.gif /g.pixel /dot.gif /updates.rss /fwlink /cm /cx /pixel /match /visit.js /load /push /ptj /j.ad /ga.js /en_US/all.js /activity /IE9CompatViewList.xml";
    client {
        metadata {
            base64;
            header "Cookie";
        }
    }
    server {
        header "Content-Type" "application/octet-stream";
        output {
            base64;
            print;
        }
    }
}

http-post {
    set uri "/submit.php";
    client {
        header "Content-Type" "application/octet-stream";
        id {
            parameter "id";
        }
        output {
            base64;
            print;
        }
    }
    server {
        header "Content-Type" "text/html";
        output {
            base64;
            print;
        }
    }
}

2. Beacon上线与心跳通信

2.1 上线过程

  • 第一个GET请求包含metadata信息
  • 服务端返回空响应包
  • metadata默认使用RSA公钥加密放在Cookie中

2.2 心跳通信

  • 后续心跳请求使用相同结构
  • 服务端通过心跳响应包下发命令

3. TeamServer请求处理流程

3.1 请求处理入口

  • NanoHTTPD.run方法接收请求
  • 传递给WebServer.serve
  • 最终由WebServer._serve处理

3.2 请求过滤

  1. 检查User-Agent:

    • 黑名单检测(blockedByUA
    • 白名单检测(allowedByUA
    • 默认黑名单:curl/lynx/wget*
    • 必须满足allowedByUA && !blockedByUA才会继续处理
  2. OPTIONS方法直接返回200和允许的方法

  3. 检查URI是否在profile定义的http-get.set urihttp-post.set uri

3.3 请求处理链

  • 匹配的URI由MalleableHook.serve处理
  • 最终调用BeaconHTTP._A.serve处理metadata

4. Metadata处理

4.1 处理流程

  1. BeaconHTTP._A.serve获取客户端IP
  2. 使用recover方法对metadata进行Base64解码
  3. 传入process_beacon_metadata处理

4.2 Metadata数据结构

4字节: 固定magic number 48897
4字节: 数据长度
16字节: SHA256哈希的前16字节为AES密钥,后16字节为HMAC密钥
2字节: 大端字节序编码类型(WindowsCharsets.getName)
2字节: 大端字节序编码类型
4字节: Beacon会话ID
4字节: PID
2字节: SSH端口
1字节: 系统信息标志位(按位与判断):
    +4: 64位系统
    +2: 64位程序
    +8: SYSTEM权限
    +1: 获取信息失败
2字节: Windows NT版本
2字节: Windows Build号
4字节: 未知作用
4字节: ptr_gmh
4字节: ptr_gpa
4字节: 大端字节序表示的内网IP地址
剩余部分: 计算机信息(计算机名\n用户名\n程序名)

5. 任务下发机制

5.1 任务数据结构

TeamServer使用metadata中的:

  • AES密钥加密任务数据
  • HMAC密钥作为盐计算哈希签名
  • 硬编码IV:abcdefghijklmnop

5.2 任务构造示例(shell whoami)

任务数据结构:

4字节: 命令类型(78表示shell)
4字节: 数据长度
数据部分: "%COMSPEC%\n/C whoami"

具体构造流程:

  1. BeaconConsole.actionPerformed根据命令类型进入对应方法
  2. shell方法构造任务结构:
    • 添加4字节的%COMSPEC%长度和内容
    • 添加命令编码后的长度和内容(各4字节)
    • 添加2字节的0
  3. 在数据前添加4字节命令类型和4字节数据长度

5.3 TeamServer任务队列

  1. TeamServer启动监听循环
  2. 客户端命令转换为Request对象:
    • call属性为beacon.task
    • args为加工后的参数
  3. Beacon.call方法处理任务:
    • 获取对应Beacon ID的任务队列
    • 添加任务数据到队列

5.4 Beacon获取任务

  1. BeaconHTTP._A.serve调用dump方法
  2. this.queues获取对应Beacon ID的任务
  3. 加密任务数据:
    • 添加4字节时间戳
    • 添加4字节任务数据长度
    • 使用AES加密
    • 计算HMAC签名
    • 拼接加密数据和签名(前16字节)

6. 任务结果回传

6.1 POST请求处理

  • Beacon通过POST回传结果
  • BeaconHTTP._B.serve处理POST数据
  • Session ID默认放在URL中

6.2 数据处理流程

  1. Base64解码POST数据
  2. process_beacon_data处理:
    • 前4字节为数据长度
    • 剩余部分传入process_beacon_callback
  3. 解密数据:
    • 后16字节为HMAC签名
    • 验证完整性
    • AES解密剩余数据
  4. 解析任务结果:
    • 前4字节防重放验证
    • 接着4字节为数据长度
    • 然后4字节为任务类型(30表示shell)

6.3 任务结果数据结构

4字节: 数据长度
[AES加密数据]
    4字节: 防重放int
    4字节: 数据长度
    4字节: 任务类型
    任务结果数据
    其他数据(shell类型有8字节)
16字节: HMAC哈希签名

7. 实用工具与参考

7.1 解析脚本

  • Python实现的metadata解析工具:https://github.com/l3anma/cobaltstrike4.5_http_dec

7.2 参考资源

  1. Cobalt Strike原理介绍:https://wbglil.gitbook.io/cobalt-strike/cobalt-strike-yuan-li-jie-shao/cs-mu-biao-shang-xian-guo-cheng#yuan-shu-ju
  2. Palo Alto Networks分析报告:https://unit42.paloaltonetworks.com/cobalt-strike-metadata-encryption-decryption/

8. 关键点总结

  1. 通信加密

    • 初始metadata使用RSA加密
    • 后续通信使用AES加密(密钥来自metadata)
    • HMAC用于完整性验证
  2. 任务机制

    • 心跳GET请求用于下发任务
    • POST请求用于回传结果
    • 任务队列存储在TeamServer
  3. 数据结构

    • 所有关键数据都有长度前缀
    • 使用固定magic number标识
    • 系统信息高度压缩编码
  4. 安全措施

    • User-Agent过滤
    • 防重放机制
    • 数据完整性验证
Cobalt Strike 4.5 Stageless Beacon 通信分析教学文档 1. 环境准备 1.1 调试环境搭建 使用IDEA反编译Cobalt Strike并导入原jar包作为依赖进行调试跟踪 从 .cobaltstrike.beacon_keys 文件中取出序列化存储的RSA公私钥 1.2 通信配置 为了便于手动解密通信数据,使用以下profile配置将所有通信数据Base64编码: 2. Beacon上线与心跳通信 2.1 上线过程 第一个GET请求包含metadata信息 服务端返回空响应包 metadata默认使用RSA公钥加密放在Cookie中 2.2 心跳通信 后续心跳请求使用相同结构 服务端通过心跳响应包下发命令 3. TeamServer请求处理流程 3.1 请求处理入口 NanoHTTPD.run 方法接收请求 传递给 WebServer.serve 最终由 WebServer._serve 处理 3.2 请求过滤 检查User-Agent: 黑名单检测( blockedByUA ) 白名单检测( allowedByUA ) 默认黑名单:curl/lynx/wget* 必须满足 allowedByUA && !blockedByUA 才会继续处理 OPTIONS方法直接返回200和允许的方法 检查URI是否在profile定义的 http-get.set uri 或 http-post.set uri 中 3.3 请求处理链 匹配的URI由 MalleableHook.serve 处理 最终调用 BeaconHTTP._A.serve 处理metadata 4. Metadata处理 4.1 处理流程 BeaconHTTP._A.serve 获取客户端IP 使用 recover 方法对metadata进行Base64解码 传入 process_beacon_metadata 处理 4.2 Metadata数据结构 5. 任务下发机制 5.1 任务数据结构 TeamServer使用metadata中的: AES密钥加密任务数据 HMAC密钥作为盐计算哈希签名 硬编码IV: abcdefghijklmnop 5.2 任务构造示例(shell whoami) 任务数据结构: 具体构造流程: BeaconConsole.actionPerformed 根据命令类型进入对应方法 shell 方法构造任务结构: 添加4字节的 %COMSPEC% 长度和内容 添加命令编码后的长度和内容(各4字节) 添加2字节的0 在数据前添加4字节命令类型和4字节数据长度 5.3 TeamServer任务队列 TeamServer启动监听循环 客户端命令转换为 Request 对象: call 属性为 beacon.task args 为加工后的参数 Beacon.call 方法处理任务: 获取对应Beacon ID的任务队列 添加任务数据到队列 5.4 Beacon获取任务 BeaconHTTP._A.serve 调用 dump 方法 从 this.queues 获取对应Beacon ID的任务 加密任务数据: 添加4字节时间戳 添加4字节任务数据长度 使用AES加密 计算HMAC签名 拼接加密数据和签名(前16字节) 6. 任务结果回传 6.1 POST请求处理 Beacon通过POST回传结果 BeaconHTTP._B.serve 处理POST数据 Session ID默认放在URL中 6.2 数据处理流程 Base64解码POST数据 process_beacon_data 处理: 前4字节为数据长度 剩余部分传入 process_beacon_callback 解密数据: 后16字节为HMAC签名 验证完整性 AES解密剩余数据 解析任务结果: 前4字节防重放验证 接着4字节为数据长度 然后4字节为任务类型(30表示shell) 6.3 任务结果数据结构 7. 实用工具与参考 7.1 解析脚本 Python实现的metadata解析工具:https://github.com/l3anma/cobaltstrike4.5_ http_ dec 7.2 参考资源 Cobalt Strike原理介绍:https://wbglil.gitbook.io/cobalt-strike/cobalt-strike-yuan-li-jie-shao/cs-mu-biao-shang-xian-guo-cheng#yuan-shu-ju Palo Alto Networks分析报告:https://unit42.paloaltonetworks.com/cobalt-strike-metadata-encryption-decryption/ 8. 关键点总结 通信加密 : 初始metadata使用RSA加密 后续通信使用AES加密(密钥来自metadata) HMAC用于完整性验证 任务机制 : 心跳GET请求用于下发任务 POST请求用于回传结果 任务队列存储在TeamServer 数据结构 : 所有关键数据都有长度前缀 使用固定magic number标识 系统信息高度压缩编码 安全措施 : User-Agent过滤 防重放机制 数据完整性验证