AdaptixC2通信机制与流量解密分析(listener_beacon_http)
字数 3340 2025-09-23 19:27:46
AdaptixC2 listener_beacon_http 通信机制与流量解密技术详解
一、 分析环境与工具准备
在进行逆向与流量分析前,需搭建以下环境:
- AdaptixC2 源码:需自备
AdaptixC2_main_v0.8源码,这是分析的基础。关键代码位于Extenders/和AdaptixServer/目录。 - 分析工具:
- mitmproxy:用作中间人(MITM)代理,拦截并解密 HTTPS 流量(降级为 HTTP 明文)。使用命令:
mitmproxy --listen-port 8080 --ssl-insecure --set ssl_version_client=TLSv1_2 -w output.mitm - Wireshark:进行原始流量抓包。需配置
sslkeys.log环境变量以解密 TLS 流量。
- mitmproxy:用作中间人(MITM)代理,拦截并解密 HTTPS 流量(降级为 HTTP 明文)。使用命令:
- 编程环境:使用 IDE(如 VS Code 或 GoLand) 阅读和跟踪 Go 语言源码。同时需准备 Python 环境来编写解密脚本。
二、 核心通信机制与加解密流程
AdaptixC2 的通信采用多层加密,理解其密钥体系是解密的关键。
1. 初始心跳(注册)与静态 RC4 密钥
- 触发:Agent(
agent.x64.exe)首次上线时,向 C2 Server 发送一个 HTTP GET 请求作为心跳包。 - 密钥生成与存储:
- 当在 C2 Server 端创建
listener_beacon_http监听器时,会随机生成一个 16 字节的加密密钥。 - 该密钥存储在
HTTPConfig.EncryptKey中。 - 此密钥会持久化保存在服务端的数据库
adaptixserver.db中。 - 在提供的例子中,该密钥的 Base64 编码为:
kJiY+eNoaq/j8VvSHUOl0Q==。
- 当在 C2 Server 端创建
- 数据携带:Agent 将心跳数据(称为
beat)通过 HTTP 头x-nws-log-uuid发送(该示例中)或类似的自定义头。 - 第一层解密(心跳包):
- C2 Server 从 HTTP 头中读取
Beat数据(Base64 编码)。 - 使用监听器的静态
EncryptKey进行 RC4 解密。 - 解密后的明文
beat数据结构如下:- 前 8 字节:
Agent Type(4 字节) +Agent ID(4 字节) - 后续部分:包含
Flags字段和多个可变长度字符串(如Hostname,Username,Executable路径等)。
- 前 8 字节:
- 在此
beat数据的偏移量 36 字节后,存储着用于后续通信的 SessionKey。
- C2 Server 从 HTTP 头中读取
2. 会话密钥 (SessionKey) 与动态加密
- SessionKey 的提取:服务端的
CreateAgent函数(位于pl_agent.go)在解析初始心跳包时,会从解密后的beat数据中提取出SessionKey。这是 Agent 与 C2 后续所有通信的对称会话密钥。 - 双重加密模型:后续的任务下发和结果回传都采用两层加密:
- 第一层(外层):使用监听器的静态
EncryptKey(kJiY...)进行 RC4 加密。 - 第二层(内层):使用本次会话的动态
SessionKey进行 RC4 加密。
- 第一层(外层):使用监听器的静态
三、 流量解密实战分析
通信过程包含三个关键数据包,下图清晰地展示了其交互流程和解密层次:
sequenceDiagram
participant A as Agent
participant S as C2 Server
participant M as mitmproxy/Wireshark
Note over A, S: 1. 初始心跳 (注册)
A->>S: HTTP GET<br/>Header: x-nws-log-uuid=RC4(EncryptKey, beat_data)
Note left of A: beat_data中包含SessionKey
S-->>A: HTTP Response<br/>(无任务data字段为空)
Note over A, S: 2. 任务下发 (C2 -> Agent)
S->>A: HTTP Response<br/>Body: { data: RC4(EncryptKey, RC4(SessionKey, Task)) }
Note right of S: 任务示例: whoami
M->>M: 解密外层(RC4_EncryptKey)<br/>得到: RC4(SessionKey, Task) 密文
Note over A, S: 3. 任务执行与结果回传 (Agent -> C2)
A->>S: HTTP POST<br/>Body: RC4(EncryptKey, RC4(SessionKey, Result))
Note left of A: 执行命令,回传结果
M->>M: 解密外层(RC4_EncryptKey)<br/>得到: RC4(SessionKey, Result) 密文
接下来,我们对每个阶段进行详细剖析。
阶段一:解密初始心跳包
目标:验证静态密钥并提取 Agent 信息。
- 源码定位:
AdaptixC2_main_v0.8/Extenders/listener_beacon_http/pl_http.go - 解密脚本 (
Beacon_Http_Rc4_Decode.py):
#!/usr/bin/env python3
import base64
from Crypto.Cipher import ARC4
import argparse
def main():
parser = argparse.ArgumentParser(description='Decode AdaptixC2 Beacon HTTP Traffic')
parser.add_argument('--key', required=True, help='Base64 encoded RC4 key')
parser.add_argument('--header', required=True, help='Base64 encoded data from header')
args = parser.parse_args()
# Decode the key and data
rc4_key = base64.b64decode(args.key)
encrypted_data = base64.b64decode(args.header)
# Decrypt with RC4
cipher = ARC4.new(rc4_key)
decrypted_data = cipher.decrypt(encrypted_data)
print(f"Decrypted Hex: {decrypted_data.hex()}")
print(f"Decrypted Raw: {decrypted_data}")
if __name__ == '__main__':
main()
- 操作命令与结果:
python .\Beacon_Http_Rc4_Decode.py --key kJiY+eNoaq/j8VvSHUOl0Q== --header QCcNx3EyLCgMPAr+TnGdPy5RQIdfmYiADUkr3b11iT4laCf11qgYliN/2zwR8T1rFBOnksPrZ/Q6prmuCbfsHRtYHggVmMaoQ1mFkZftDQx6nZd0pkguBWgO4fAFuy93jJoWi7FXSEPzoTAWUjmG0C7fzW70qHxD4Q== - 输出分析:解密后的数据应包含可读的字符串(主机名、用户名、进程路径等),与 C2 控制台界面显示的信息一致。SessionKey 也包含在这段解密后的数据中,为后续通信所用。
阶段二:解密任务下发包 (C2 -> Agent)
目标:解密 C2 服务器下发给 Agent 的指令。
-
流量特征:在 Wireshark 或 mitmproxy 中,此包是 Server 对 Agent 心跳的 HTTP 响应包。其 HTTP Body 是一个 JSON,其中包含一个
data字段,值为长长的 Base64 字符串。 -
解密步骤:
- Base64 解码
data字段的值,得到密文C1。 - 使用监听器的静态
EncryptKey对C1进行 RC4 解密,得到中间密文C2。C2实际上是使用SessionKey加密后的任务数据。 - 使用从阶段一获取的
SessionKey对C2进行 第二次 RC4 解密,得到最终的明文任务数据。
- Base64 解码
-
明文任务格式:解密后通常为二进制格式,可能包含指令类型(如
0x0001代表shell)、任务 ID 以及具体的命令(如C:\Windows\System32\cmd.exe /c whoami)。明文数据周围常包含填充字符(如0x00)以规避简单的流量特征检测。
阶段三:解密结果回传包 (Agent -> C2)
目标:解密 Agent 执行命令后返回给 C2 的结果数据。
- 流量特征:通常是 Agent 发出的 HTTP POST 请求,请求体内包含加密的二进制数据。
- 解密步骤:
- 提取 HTTP 请求体(Raw Body)。
- 使用监听器的静态
EncryptKey进行 第一层 RC4 解密。 - 使用
SessionKey对上述结果进行 第二层 RC4 解密,得到命令执行输出的明文(如desktop-123\user)。
四、 核心代码逻辑追溯
理解代码调用链对深入分析至关重要:
-
服务端任务打包:
- 入口:
AdaptixC2_main_v0.8/AdaptixServer/core/server/ts_agent.go中的TsAgentGetHostedAll函数。它从数据库获取任务队列。 - 调用:调用
ts.Extender.ExAgentPackData(位于AdaptixServer/core/extender/ex_agent.go)。 - 路由:
ExAgentPackData根据 Agent 类型,找到对应的 Agent 插件(如agent_beacon)。 - 最终加密:插件中的
AgentPackData方法(位于Extenders/agent_beacon/pl_main.go)将任务数据序列化后,用SessionKey加密,再交由监听器用EncryptKey加密。
- 入口:
-
客户端加解密函数:
- 在
Extenders/agent_beacon/pl_agent.go中定义了AgentEncryptData和AgentDecryptData函数,其内部就是标准的 RC4 算法操作,用于处理SessionKey层的加解密。
- 在
五、 总结与完整解密思路
AdaptixC2 (listener_beacon_http) 的通信保密性通过两层加密实现:
- 第一层(固定层):使用监听器初始化时生成的
EncryptKey。用于加密初始心跳包和所有后续通信的外层。 - 第二层(会话层):每个 Agent 上线时在心跳包中携带的
SessionKey。用于加密内层的实际任务和结果数据。
因此,完整的解密前提是:
- 获取到 C2 Server 配置中或数据库中的静态
EncryptKey。 - 成功解密第一个心跳包,并从明文中提取出
SessionKey。
一旦同时拥有这两个密钥,即可完全解密该监听器下所有 Agent 的整个通信过程。这种分析手法对于深度威胁狩猎、C2 流量监控和恶意软件逆向工程具有重要价值。