C2通信协议解析(一):HTTP(s)、mTLS、WebSocket、DNS
字数 6083 2025-10-01 14:05:44

C2通信协议解析教学文档

概述

本文档详细解析了四种常用于C2(Command and Control,命令与控制)框架的通信协议:HTTP(s)、mTLS、WebSocket和DNS。内容涵盖各协议的工作原理、在C2中的实现思路、关键代码示例及流量分析,旨在深入理解C2通信的隐匿与对抗技术。


一、HTTP/HTTPS

1.1 思路构建

HTTP(S)因其高带宽、普遍性及加密特性(HTTPS)成为主流C2通信协议。

  • 任务获取:C2服务器(Server)启动HTTP(S)监听器,注册自定义URI的路由。Beacon(受控端)通过GET请求该URI获取任务。任务数据经加密后嵌入HTML模板的占位符中返回。
  • 任务执行:Beacon通过正则匹配提取HTML中的加密任务数据,解密后执行命令(示例中为cmd命令)。
  • 结果回传:Beacon将任务执行结果加密后,通过POST请求同一URI回传给Server。
  • 数据序列化:示例中使用JSON序列化任务和结果数据,简化开发但扩展性不足。
  • 流量伪装:通过自定义多项参数使通信流量更像正常Web流量,包括:
    • 协议类型(HTTP/HTTPS)
    • 主机地址(HOST)
    • 端口(PORT)
    • 请求URI
    • SSL证书(若为HTTPS)
    • 返回的HTML页面内容
    • 自定义HTTP响应头(如X-Session-Id
  • 简化设计:示例中未实现任务队列,采用硬编码命令;未实现Beacon注册机制。

1.2 代码实现 (核心摘要)

Server端 (Go - Gin框架)

  • 可控参数:定义HOST, PORT, URI, IS_HTTPS, 证书路径, HTML模板路径, 自定义Header, 加密密钥, 占位符, 硬编码任务等。
  • ListenerStart函数:根据IS_HTTPS配置,启动HTTP或HTTPS服务器,在指定URI上注册processRequest(GET)和processResponse(POST)处理函数。
  • processRequest函数 (处理GET - 任务下发)
    1. 调用parseBeat解析Beacon心跳包(Metadata)。
    2. 读取HTML模板文件。
    3. 将加密(示例为RC4)后的任务数据替换模板中的占位符。
    4. 设置自定义响应头。
    5. 返回包含任务数据的HTML页面。
  • processResponse函数 (处理POST - 结果回传)
    1. 调用parseBeat解析心跳包。
    2. 读取请求Body,解密后得到任务执行结果。
    3. 将结果输出到Server控制台。
  • parseBeat函数:从自定义HTTP头(如X-Session-Id)中提取值,进行Base64解码和RC4解密,得到原始Metadata(心跳包)。

Beacon端 (Go)

  • HttpGet函数 (拉取任务)
    1. 将Metadata加密(RC4)并Base64编码。
    2. 将编码后的数据放入预定义的HTTP请求头(如X-Session-Id)。
    3. 向Server的指定URI发起GET请求。
    4. 接收响应(HTML),使用正则匹配提取加密的任务数据。
  • HttpPost函数 (回传结果)
    1. 将Metadata和任务结果分别加密、Base64编码。
    2. 将编码后的Metadata放入HTTP请求头。
    3. 将编码后的结果数据作为POST请求的Body。
    4. 向Server的指定URI发起POST请求。
  • Main函数:循环执行HttpGet -> 提取任务 -> 执行命令 -> HttpPost回传结果。

1.3 流量分析

  • Beacon → Server (GET):请求自定义URI,心跳包在自定义Header中。
  • Server → Beacon (Response):返回200 OK,数据为包含加密任务数据的HTML。
  • Beacon → Server (POST):请求同一URI,心跳包在Header,加密结果在Body。
  • Server → Beacon (Response):返回200 OK。
  • 所有关键数据(心跳、任务、结果)均经加密,但协议本身特征明显。

1.4 域前置 (Domain Fronting)

  • 目的:隐藏C2服务器的真实IP地址。
  • 原理:利用CDN服务。Beacon配置中设置回调地址为CDN提供的CNAME域名。Beacon实际与CDN边缘节点通信,CDN根据配置将流量转发(回源)至真实的C2 Server。
  • 流量特征:DNS查询解析到CDN节点IP而非真实Server IP。后续HTTP(S)通信目的IP也是CDN节点。通信内容仍加密。
  • 实施
    1. 注册域名。
    2. 在云厂商配置CDN,添加源站(真实Server IP)和CNAME记录。
    3. 在域名DNS设置中,添加一条NS记录,将特定子域(如c2.example.com)的解析权委托给第2步中CDN提供的CNAME域名(或另一个A记录指向CDN)。
    4. Beacon的回调地址设置为该子域。

二、mTLS (Mutual TLS)

2.1 思路构建

mTLS在标准TLS基础上要求客户端与服务器相互验证证书,实现双向认证。

  • 证书体系:需搭建私有PKI,生成自签名CA证书,并用其签发Server和Beacon(客户端)证书。
  • 连接管理:Server为每个Beacon连接创建独立goroutine处理,实现长连接交互式会话。
  • 流量分帧:为避免TCP粘包,自定义应用层协议:先发送4字节(大端序)表示数据长度,再发送实际数据。接收方先读长度,再读取指定长度的数据。
  • 通信模式:示例为实时交互式。也可改造为Beacon模式(短连接+任务队列)。

2.2 代码实现

2.2.1 生成证书
使用Go代码或openssl命令生成:

  1. CA:自签名根证书及私钥 (ca.crt, ca.key)。
  2. Server:由CA签发证书 (server.crt) 和私钥 (server.key)。证书中需设置Subject Alternative Name (SAN)为Server的IP或域名。
  3. Beacon:由CA签发客户端证书 (client.crt) 和私钥 (client.key)。

2.2.2 Server端

  • ListenerStart函数
    1. 加载Server证书、私钥及CA证书(用于验证Beacon证书)。
    2. 配置tls.Config,设置ClientAuth: tls.RequireAndVerifyClientCert(关键,开启mTLS)。
    3. 调用tls.Listen启动TLS监听。
  • handleConnection函数
    1. 接受连接后,进行TLS握手(包含双向证书验证)。
    2. 循环:读取Beacon发来的数据帧 -> 处理(示例中直接输出)-> 从标准输入读取命令 -> 将命令写入数据帧发送给Beacon。

2.2.3 Beacon端

  • 加载Beacon(客户端)证书、私钥及CA证书(用于验证Server证书)。
  • 配置tls.Config,设置ServerName为Server的SAN中指定的域名或IP。
  • 使用tls.Dial连接Server。
  • 成功连接后,发送初始元数据。
  • 循环:读取Server发来的数据帧(命令)-> 执行命令 -> 将结果写入数据帧发送回Server。

2.3 流量分析

  • 初始为TCP三次握手。
  • 后续为TLS握手过程,包含Certificate Request、Client Certificate等mTLS特有报文。
  • 应用层数据全部由TLS记录协议加密。
  • 可使用域名连接,Beacon需先解析域名得到Server IP。

三、WebSocket

3.1 思路构建

WebSocket提供全双工通信,通过HTTP(S)升级建立,使用80/443端口,易于伪装。

  • 协议升级:Beacon发送包含Upgrade: websocket头的HTTP请求,Server响应101状态码完成升级。
  • 内置分帧:WebSocket协议自身有帧格式(操作码+长度+载荷),无需自行解决粘包问题。
  • 通信模式:示例实现类交互式会话。长连接,实时性强。

3.2 代码实现

3.2.1 Server端 (使用gorilla/websocket)

  • ListenerStart函数:启动HTTP(S)服务器,在指定路径(如/ws)上挂接处理函数。
  • 处理函数
    1. 使用Upgrader将HTTP连接升级为WebSocket连接。
    2. 在新goroutine中handleConnection
  • handleConnection函数
    1. 读取Beacon发来的消息(如心跳)。
    2. 循环:从标准输入读命令 -> conn.WriteMessage(websocket.TextMessage, []byte(cmd))发送 -> conn.ReadMessage()读取Beacon回显。

3.2.2 Beacon端

  • 使用websocket.Dialer连接Server的WebSocket端点(WS或WSS)。
  • 成功连接后,可发送初始消息。
  • 循环:conn.ReadMessage()接收命令 -> 执行 -> conn.WriteMessage(websocket.TextMessage, []byte(result))发送结果。

3.3 流量分析

  • HTTP Upgrade请求:可见Connection: UpgradeUpgrade: websocket头。
  • HTTP 101响应:协议切换成功。
  • 后续通信:为WebSocket二进制帧,载荷内容加密后不可读。
  • 改进方向
    • 使用WSS(WebSocket Secure)。
    • 伪装Upgrade路径和HTTP头。
    • 部署在正常Web服务下。
    • 结合域前置。

四、DNS

4.1 前置知识

  • DNS隧道:将数据封装在DNS查询和响应中进行传输。利用UDP 53端口通常开放且检查宽松的特点。
  • 记录类型
    • A (IPv4地址):4字节载荷。常用于控制信号或小数据。
    • TXT (文本记录):≤255字节/记录。常用于传输任务数据。
    • AAAA (IPv6地址):16字节载荷。
  • 限制:域名标签长度≤63字符,总域名长度≤253字符。需编码(如Hex、Base32无填充)以适应域名格式。
  • 实现模式:反向连接。Beacon主动向Server(权威DNS服务器)发起查询。

4.2 Cobalt Strike DNS Beacon使用 (参考)

  1. 域名配置
    • 注册域名(如example.com)。
    • 添加一条A记录:将子域(如ns1.example.com)指向C2 Server IP。
    • 添加一条NS记录:将子域(如c2.example.com)委托给ns1.example.com解析。
  2. CS配置:DNS监听器的DNS Hosts设置为NS记录的子域(c2.example.com)。
  3. 通信流程
    • 心跳/拉取任务:Beacon查询[agentId].[c2.example.com]的A记录。Server返回的IPv4地址的最后一个字节作为控制信号(如0无任务,非0则需TXT查询取任务)。
    • 获取任务:Beacon查询[agentId].[c2.example.com]的TXT记录。Server在TXT响应中返回任务数据。
    • 回传数据:Beacon将数据分片编码后,放入查询子域的名称中(如[data].[agentId].[c2.example.com]),发起A查询。Server记录查询名即可提取数据。需实现分片、重组、序号机制。

4.3 思路构建

  • 反向连接:Beacon作为DNS客户端,向Server(权威DNS服务器)发起查询。
  • 任务获取:Beacon通过TXT查询获取任务。
  • 结果回传:Beacon通过A查询,将编码后的数据嵌入查询域名中回传。
  • 数据分片:因域名长度限制,大数据需分片传输。Server需重组。
  • 编码:使用Hex或Base32无填充将二进制数据编码为域名合法字符。
  • 多Beacon:通过查询域名中的agentId区分不同Beacon。

4.4 代码实现 (简化概念)

(一)发送心跳包/回传数据 (Beacon - A查询)

  • DNSPut函数
    1. 将待发送数据(如Metadata、结果)进行Hex编码。
    2. 根据数据长度,按预定义档位(如104B, 84B, 56B, ... 4B)分片。
    3. 对于每一片数据,构造查询域名:[档位标识][分片数据][序号][Nonce][agentId].[委托域]
    4. 发起A记录查询。Server端记录查询域名即可提取数据。
    5. 实现重传机制。
  • 心跳包:上线时发送一次。

(二)解析回传数据 (Server - 处理A查询)

  1. 检查查询域名前缀(如www, post)。
  2. 提取agentIdNonce序号分片数据
  3. 如果是首包(序号0),提取总长度信息。
  4. 根据Nonce和序号将数据分片存入缓存。
  5. 收齐所有分片后,Hex解码重组原始数据。

(三)获取任务 (Beacon)

  1. 获取控制信号:向api.[agentId].[domain]发起A查询。Server返回IP,最后一字节为信号。
  2. 获取任务数据:向api.[agentId].[domain]发起TXT查询。Server返回TXT记录,其中包含任务数据(可分片)。Beacon拼接TXT记录得到完整任务。

(四)Server响应

  • 对A查询:根据场景返回预设IP(如控制信号)。
  • 对TXT查询:返回包含(分片)任务数据的TXT记录。

4.4 实验注意事项

  • Server需监听UDP 53端口,并拥有公网IP。
  • 确保VPS安全组/防火墙放行UDP 53端口。
  • 关闭可能占用53端口的本地服务(如systemd-resolved)。
  • 客户端DNS服务器需设置为可解析互联网DNS的地址(如8.8.8.8)。

五、下一步计划

作者表示后续可能研究方向:

  1. 免杀技术(二进制相关)。
  2. 深入分析公开的Cobalt Strike Beacon源码。
  3. 继续完善C2协议研究(本篇为第一篇)。

参考资料

  • Sliver C2 框架源码 (mtls, dns)
  • Gorilla WebSocket 库文档
  • DNS 协议规范 (RFC 1035)
  • 域前置技术文章(先知社区、长亭)
  • Cobalt Strike DNS Beacon 技术分析文章(FreeBuf、博客园等)
  • Cobalt Strike 官方文档

C2通信协议解析教学文档 概述 本文档详细解析了四种常用于C2(Command and Control,命令与控制)框架的通信协议:HTTP(s)、mTLS、WebSocket和DNS。内容涵盖各协议的工作原理、在C2中的实现思路、关键代码示例及流量分析,旨在深入理解C2通信的隐匿与对抗技术。 一、HTTP/HTTPS 1.1 思路构建 HTTP(S)因其高带宽、普遍性及加密特性(HTTPS)成为主流C2通信协议。 任务获取 :C2服务器(Server)启动HTTP(S)监听器,注册自定义URI的路由。Beacon(受控端)通过GET请求该URI获取任务。任务数据经加密后嵌入HTML模板的占位符中返回。 任务执行 :Beacon通过正则匹配提取HTML中的加密任务数据,解密后执行命令(示例中为 cmd 命令)。 结果回传 :Beacon将任务执行结果加密后,通过POST请求同一URI回传给Server。 数据序列化 :示例中使用JSON序列化任务和结果数据,简化开发但扩展性不足。 流量伪装 :通过自定义多项参数使通信流量更像正常Web流量,包括: 协议类型(HTTP/HTTPS) 主机地址(HOST) 端口(PORT) 请求URI SSL证书(若为HTTPS) 返回的HTML页面内容 自定义HTTP响应头(如 X-Session-Id ) 简化设计 :示例中未实现任务队列,采用硬编码命令;未实现Beacon注册机制。 1.2 代码实现 (核心摘要) Server端 (Go - Gin框架) 可控参数 :定义HOST, PORT, URI, IS_ HTTPS, 证书路径, HTML模板路径, 自定义Header, 加密密钥, 占位符, 硬编码任务等。 ListenerStart函数 :根据 IS_HTTPS 配置,启动HTTP或HTTPS服务器,在指定URI上注册 processRequest (GET)和 processResponse (POST)处理函数。 processRequest函数 (处理GET - 任务下发) : 调用 parseBeat 解析Beacon心跳包(Metadata)。 读取HTML模板文件。 将加密(示例为RC4)后的任务数据替换模板中的占位符。 设置自定义响应头。 返回包含任务数据的HTML页面。 processResponse函数 (处理POST - 结果回传) : 调用 parseBeat 解析心跳包。 读取请求Body,解密后得到任务执行结果。 将结果输出到Server控制台。 parseBeat函数 :从自定义HTTP头(如 X-Session-Id )中提取值,进行Base64解码和RC4解密,得到原始Metadata(心跳包)。 Beacon端 (Go) HttpGet函数 (拉取任务) : 将Metadata加密(RC4)并Base64编码。 将编码后的数据放入预定义的HTTP请求头(如 X-Session-Id )。 向Server的指定URI发起GET请求。 接收响应(HTML),使用正则匹配提取加密的任务数据。 HttpPost函数 (回传结果) : 将Metadata和任务结果分别加密、Base64编码。 将编码后的Metadata放入HTTP请求头。 将编码后的结果数据作为POST请求的Body。 向Server的指定URI发起POST请求。 Main函数 :循环执行 HttpGet -> 提取任务 -> 执行命令 -> HttpPost 回传结果。 1.3 流量分析 Beacon → Server (GET) :请求自定义URI,心跳包在自定义Header中。 Server → Beacon (Response) :返回200 OK,数据为包含加密任务数据的HTML。 Beacon → Server (POST) :请求同一URI,心跳包在Header,加密结果在Body。 Server → Beacon (Response) :返回200 OK。 所有关键数据(心跳、任务、结果)均经加密,但协议本身特征明显。 1.4 域前置 (Domain Fronting) 目的 :隐藏C2服务器的真实IP地址。 原理 :利用CDN服务。Beacon配置中设置回调地址为CDN提供的CNAME域名。Beacon实际与CDN边缘节点通信,CDN根据配置将流量转发(回源)至真实的C2 Server。 流量特征 :DNS查询解析到CDN节点IP而非真实Server IP。后续HTTP(S)通信目的IP也是CDN节点。通信内容仍加密。 实施 : 注册域名。 在云厂商配置CDN,添加源站(真实Server IP)和CNAME记录。 在域名DNS设置中,添加一条NS记录,将特定子域(如 c2.example.com )的解析权委托给第2步中CDN提供的CNAME域名(或另一个A记录指向CDN)。 Beacon的回调地址设置为该子域。 二、mTLS (Mutual TLS) 2.1 思路构建 mTLS在标准TLS基础上要求客户端与服务器相互验证证书,实现双向认证。 证书体系 :需搭建私有PKI,生成自签名CA证书,并用其签发Server和Beacon(客户端)证书。 连接管理 :Server为每个Beacon连接创建独立goroutine处理,实现长连接交互式会话。 流量分帧 :为避免TCP粘包,自定义应用层协议:先发送4字节(大端序)表示数据长度,再发送实际数据。接收方先读长度,再读取指定长度的数据。 通信模式 :示例为实时交互式。也可改造为Beacon模式(短连接+任务队列)。 2.2 代码实现 2.2.1 生成证书 使用Go代码或 openssl 命令生成: CA :自签名根证书及私钥 ( ca.crt , ca.key )。 Server :由CA签发证书 ( server.crt ) 和私钥 ( server.key )。证书中需设置 Subject Alternative Name (SAN) 为Server的IP或域名。 Beacon :由CA签发客户端证书 ( client.crt ) 和私钥 ( client.key )。 2.2.2 Server端 ListenerStart函数 : 加载Server证书、私钥及CA证书(用于验证Beacon证书)。 配置 tls.Config ,设置 ClientAuth: tls.RequireAndVerifyClientCert (关键,开启mTLS)。 调用 tls.Listen 启动TLS监听。 handleConnection函数 : 接受连接后,进行TLS握手(包含双向证书验证)。 循环:读取Beacon发来的数据帧 -> 处理(示例中直接输出)-> 从标准输入读取命令 -> 将命令写入数据帧发送给Beacon。 2.2.3 Beacon端 加载Beacon(客户端)证书、私钥及CA证书(用于验证Server证书)。 配置 tls.Config ,设置 ServerName 为Server的SAN中指定的域名或IP。 使用 tls.Dial 连接Server。 成功连接后,发送初始元数据。 循环:读取Server发来的数据帧(命令)-> 执行命令 -> 将结果写入数据帧发送回Server。 2.3 流量分析 初始为TCP三次握手。 后续为TLS握手过程,包含Certificate Request、Client Certificate等mTLS特有报文。 应用层数据全部由TLS记录协议加密。 可使用域名连接,Beacon需先解析域名得到Server IP。 三、WebSocket 3.1 思路构建 WebSocket提供全双工通信,通过HTTP(S)升级建立,使用80/443端口,易于伪装。 协议升级 :Beacon发送包含 Upgrade: websocket 头的HTTP请求,Server响应101状态码完成升级。 内置分帧 :WebSocket协议自身有帧格式(操作码+长度+载荷),无需自行解决粘包问题。 通信模式 :示例实现类交互式会话。长连接,实时性强。 3.2 代码实现 3.2.1 Server端 (使用 gorilla/websocket ) ListenerStart函数 :启动HTTP(S)服务器,在指定路径(如 /ws )上挂接处理函数。 处理函数 : 使用 Upgrader 将HTTP连接升级为WebSocket连接。 在新goroutine中 handleConnection 。 handleConnection函数 : 读取Beacon发来的消息(如心跳)。 循环:从标准输入读命令 -> conn.WriteMessage(websocket.TextMessage, []byte(cmd)) 发送 -> conn.ReadMessage() 读取Beacon回显。 3.2.2 Beacon端 使用 websocket.Dialer 连接Server的WebSocket端点(WS或WSS)。 成功连接后,可发送初始消息。 循环: conn.ReadMessage() 接收命令 -> 执行 -> conn.WriteMessage(websocket.TextMessage, []byte(result)) 发送结果。 3.3 流量分析 HTTP Upgrade请求 :可见 Connection: Upgrade 和 Upgrade: websocket 头。 HTTP 101响应 :协议切换成功。 后续通信 :为WebSocket二进制帧,载荷内容加密后不可读。 改进方向 : 使用WSS(WebSocket Secure)。 伪装Upgrade路径和HTTP头。 部署在正常Web服务下。 结合域前置。 四、DNS 4.1 前置知识 DNS隧道 :将数据封装在DNS查询和响应中进行传输。利用UDP 53端口通常开放且检查宽松的特点。 记录类型 : A (IPv4地址) :4字节载荷。常用于控制信号或小数据。 TXT (文本记录) :≤255字节/记录。常用于传输任务数据。 AAAA (IPv6地址) :16字节载荷。 限制 :域名标签长度≤63字符,总域名长度≤253字符。需编码(如Hex、Base32无填充)以适应域名格式。 实现模式 :反向连接。Beacon主动向Server(权威DNS服务器)发起查询。 4.2 Cobalt Strike DNS Beacon使用 (参考) 域名配置 : 注册域名(如 example.com )。 添加一条 A记录 :将子域(如 ns1.example.com )指向C2 Server IP。 添加一条 NS记录 :将子域(如 c2.example.com )委托给 ns1.example.com 解析。 CS配置 :DNS监听器的 DNS Hosts 设置为NS记录的子域( c2.example.com )。 通信流程 : 心跳/拉取任务 :Beacon查询 [agentId].[c2.example.com] 的A记录。Server返回的IPv4地址的最后一个字节作为控制信号(如0无任务,非0则需TXT查询取任务)。 获取任务 :Beacon查询 [agentId].[c2.example.com] 的TXT记录。Server在TXT响应中返回任务数据。 回传数据 :Beacon将数据分片编码后,放入查询子域的名称中(如 [data].[agentId].[c2.example.com] ),发起A查询。Server记录查询名即可提取数据。需实现分片、重组、序号机制。 4.3 思路构建 反向连接 :Beacon作为DNS客户端,向Server(权威DNS服务器)发起查询。 任务获取 :Beacon通过TXT查询获取任务。 结果回传 :Beacon通过A查询,将编码后的数据嵌入查询域名中回传。 数据分片 :因域名长度限制,大数据需分片传输。Server需重组。 编码 :使用Hex或Base32无填充将二进制数据编码为域名合法字符。 多Beacon :通过查询域名中的 agentId 区分不同Beacon。 4.4 代码实现 (简化概念) (一)发送心跳包/回传数据 (Beacon - A查询) DNSPut函数 : 将待发送数据(如Metadata、结果)进行Hex编码。 根据数据长度,按预定义档位(如104B, 84B, 56B, ... 4B)分片。 对于每一片数据,构造查询域名: [档位标识][分片数据][序号][Nonce][agentId].[委托域] 。 发起A记录查询。Server端记录查询域名即可提取数据。 实现重传机制。 心跳包 :上线时发送一次。 (二)解析回传数据 (Server - 处理A查询) 检查查询域名前缀(如 www , post )。 提取 agentId 、 Nonce 、 序号 、 分片数据 。 如果是首包(序号0),提取总长度信息。 根据Nonce和序号将数据分片存入缓存。 收齐所有分片后,Hex解码重组原始数据。 (三)获取任务 (Beacon) 获取控制信号 :向 api.[agentId].[domain] 发起A查询。Server返回IP,最后一字节为信号。 获取任务数据 :向 api.[agentId].[domain] 发起TXT查询。Server返回TXT记录,其中包含任务数据(可分片)。Beacon拼接TXT记录得到完整任务。 (四)Server响应 对A查询:根据场景返回预设IP(如控制信号)。 对TXT查询:返回包含(分片)任务数据的TXT记录。 4.4 实验注意事项 Server需监听UDP 53端口,并拥有公网IP。 确保VPS安全组/防火墙放行UDP 53端口。 关闭可能占用53端口的本地服务(如 systemd-resolved )。 客户端DNS服务器需设置为可解析互联网DNS的地址(如 8.8.8.8 )。 五、下一步计划 作者表示后续可能研究方向: 免杀技术(二进制相关)。 深入分析公开的Cobalt Strike Beacon源码。 继续完善C2协议研究(本篇为第一篇)。 参考资料 Sliver C2 框架源码 (mtls, dns) Gorilla WebSocket 库文档 DNS 协议规范 (RFC 1035) 域前置技术文章(先知社区、长亭) Cobalt Strike DNS Beacon 技术分析文章(FreeBuf、博客园等) Cobalt Strike 官方文档