$npx -y skills add killvxk/cybersecurity-skills-zh --skill analyzing-command-and-control-communication分析恶意软件命令与控制(C2)通信协议,以了解 beacon 模式、命令结构、数据编码和基础设施。 涵盖 HTTP、HTTPS、DNS 和自定义协议 C2 分析,用于检测规则开发和威胁情报。 适用于 C2 分析、beacon 检测、C2 协议逆向工程或命令与控制基础设施绘图相关请求。
| 1 | # 分析命令与控制通信 |
| 2 | |
| 3 | ## 适用场景 |
| 4 | |
| 5 | - 对恶意软件样本的逆向工程揭示了需要协议分析的网络通信 |
| 6 | - 为特定 C2 框架(Cobalt Strike、Metasploit、Sliver)构建网络级检测签名 |
| 7 | - 绘制 C2 基础设施图,包括主服务器、备用域名和投弃站 |
| 8 | - 分析加密或编码的 C2 流量以了解命令集和数据格式 |
| 9 | - 基于 C2 基础设施模式和工具对恶意软件进行威胁行为者溯源归因 |
| 10 | |
| 11 | **不适用于**一般网络异常检测;本技能专门用于从恶意软件分析中了解已知或疑似 C2 协议。 |
| 12 | |
| 13 | ## 前置条件 |
| 14 | |
| 15 | - 恶意软件网络流量的 PCAP 捕获(来自沙箱、网络分流或全包捕获) |
| 16 | - Wireshark/tshark 用于数据包级分析 |
| 17 | - 逆向工程工具(Ghidra、dnSpy)用于了解恶意软件二进制文件中的 C2 代码 |
| 18 | - Python 3.8+,安装 `scapy`、`dpkt` 和 `requests` 用于协议分析和重放 |
| 19 | - 威胁情报数据库用于 C2 基础设施关联(VirusTotal、Shodan、Censys) |
| 20 | - JA3/JA3S 指纹数据库用于基于 TLS 的 C2 识别 |
| 21 | |
| 22 | ## 工作流程 |
| 23 | |
| 24 | ### 步骤 1:识别 C2 通道 |
| 25 | |
| 26 | 确定用于 C2 通信的协议和传输方式: |
| 27 | |
| 28 | ``` |
| 29 | C2 通信通道: |
| 30 | ━━━━━━━━━━━━━━━━━━━━━━━━━ |
| 31 | HTTP/HTTPS: 最常见;使用标准 Web 流量进行混入 |
| 32 | 指标:定期 POST/GET 请求、特定 URI 模式、自定义请求头 |
| 33 | |
| 34 | DNS: 通过 DNS 查询和响应进行数据隧道传输 |
| 35 | 指标:大量 TXT 查询、长子域名、高熵值 |
| 36 | |
| 37 | 自定义 TCP/UDP:使用非标准端口的私有二进制协议 |
| 38 | 指标:高端口上的非 HTTP 流量、未知协议 |
| 39 | |
| 40 | ICMP: 编码在 ICMP 回显/回复载荷中的数据 |
| 41 | 指标:具有大型或非标准载荷的 ICMP 数据包 |
| 42 | |
| 43 | WebSocket: 用于实时 C2 的持久双向连接 |
| 44 | 指标:WebSocket 升级后跟随二进制帧 |
| 45 | |
| 46 | 云服务: 使用合法 API(Telegram、Discord、Slack、GitHub) |
| 47 | 指标:非预期进程向云服务进行 API 调用 |
| 48 | |
| 49 | 电子邮件: 使用 SMTP/IMAP 进行 C2 命令和数据外泄 |
| 50 | 指标:非电子邮件进程的自动化邮件操作 |
| 51 | ``` |
| 52 | |
| 53 | ### 步骤 2:分析 Beacon 模式 |
| 54 | |
| 55 | 对周期性通信模式进行特征分析: |
| 56 | |
| 57 | ```python |
| 58 | from scapy.all import rdpcap, IP, TCP |
| 59 | from collections import defaultdict |
| 60 | import statistics |
| 61 | import json |
| 62 | |
| 63 | packets = rdpcap("c2_traffic.pcap") |
| 64 | |
| 65 | # 按目标分组 TCP SYN 数据包 |
| 66 | connections = defaultdict(list) |
| 67 | for pkt in packets: |
| 68 | if IP in pkt and TCP in pkt and (pkt[TCP].flags & 0x02): |
| 69 | key = f"{pkt[IP].dst}:{pkt[TCP].dport}" |
| 70 | connections[key].append(float(pkt.time)) |
| 71 | |
| 72 | # 分析每个目标的 beacon 行为 |
| 73 | for dst, times in sorted(connections.items()): |
| 74 | if len(times) < 3: |
| 75 | continue |
| 76 | |
| 77 | intervals = [times[i+1] - times[i] for i in range(len(times)-1)] |
| 78 | avg_interval = statistics.mean(intervals) |
| 79 | stdev = statistics.stdev(intervals) if len(intervals) > 1 else 0 |
| 80 | jitter_pct = (stdev / avg_interval * 100) if avg_interval > 0 else 0 |
| 81 | duration = times[-1] - times[0] |
| 82 | |
| 83 | beacon_data = { |
| 84 | "destination": dst, |
| 85 | "connections": len(times), |
| 86 | "duration_seconds": round(duration, 1), |
| 87 | "avg_interval_seconds": round(avg_interval, 1), |
| 88 | "stdev_seconds": round(stdev, 1), |
| 89 | "jitter_percent": round(jitter_pct, 1), |
| 90 | "is_beacon": 5 < avg_interval < 7200 and jitter_pct < 25, |
| 91 | } |
| 92 | |
| 93 | if beacon_data["is_beacon"]: |
| 94 | print(f"[!] 检测到 BEACON:{dst}") |
| 95 | print(f" 间隔:{avg_interval:.0f}s +/- {stdev:.0f}s({jitter_pct:.0f}% 抖动)") |
| 96 | print(f" 会话:{len(times)} 次,持续 {duration:.0f}s") |
| 97 | ``` |
| 98 | |
| 99 | ### 步骤 3:解码 C2 协议结构 |
| 100 | |
| 101 | 从捕获的流量中逆向工程消息格式: |
| 102 | |
| 103 | ```python |
| 104 | # 基于 HTTP 的 C2 协议分析 |
| 105 | import dpkt |
| 106 | import base64 |
| 107 | |
| 108 | with open("c2_traffic.pcap", "rb") as f: |
| 109 | pcap = dpkt.pcap.Reader(f) |
| 110 | |
| 111 | for ts, buf in pcap: |
| 112 | eth = dpkt.ethernet.Ethernet(buf) |
| 113 | if not isinstance(eth.data, dpkt.ip.IP): |
| 114 | continue |
| 115 | ip = eth.data |
| 116 | if not isinstance(ip.data, dpkt.tcp.TCP): |
| 117 | continue |
| 118 | tcp = ip.data |
| 119 | |
| 120 | if tcp.dport == 80 or tcp.dport == 443: |
| 121 | if len(tcp.data) > 0: |
| 122 | try: |
| 123 | http = dpkt.http.Request(tcp.data) |
| 124 | print(f"\n--- C2 请求 ---") |
| 125 | print(f"方法:{http.method}") |
| 126 | print(f"URI:{http.uri}") |
| 127 | print(f"请求头:{dict(http.headers)}") |
| 128 | if http.body: |
| 129 | print(f"正文({len(http.body)} 字节):") |
| 130 | # 尝试 Base64 解码 |
| 131 | try: |
| 132 | decoded = base64.b64decode(http.body) |
| 133 | print(f" 解码后:{decoded[:200]}") |
| 134 | except: |
| 135 | print(f" 原始:{http.body[:200]}") |
| 136 | except: |
| 137 | pass |
| 138 | ``` |
| 139 | |
| 140 | ### 步骤 4:识别 C2 框架 |
| 141 | |
| 142 | 将观察到的模式与已知 C2 框架进行匹配: |
| 143 | |
| 144 | ``` |
| 145 | 已知 C2 框架签名: |
| 146 | ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ |
| 147 | Cobalt Strike: |
| 148 | - 默认 URI:/pixel、/submit.php、/___utm.gif、/ca、/dpixel |
| 149 | - Malleable C2 配置文件可自定义所有流量特征 |
| 150 | - JA3:随配置文件变化 |
| 151 | - Beacon 配置中的水印(每个许可证唯一) |
| 152 | - 配置提取:使用 CobaltStrikeParser 或 1768.py |
| 153 | |
| 154 | Metasploit/Meterpreter: |
| 155 | - 默认分段 URI 模式:随机 4 字符校验和 |
| 156 | - 反向 HTTP(S) 处理器模式 |
| 157 | - Meterpreter TLV(类型-长度-值)协议结构 |
| 158 | |
| 159 | Sliver: |
| 160 | - mTLS、HTTP、DNS、WireGuard 传输选项 |
| 161 | - Protobuf 编码消息 |
| 162 | - 通信中的唯一植入物 ID |
| 163 | |
| 164 | Covenant: |
| 165 | - 基于 .NET 的 C2 框架 |
| 166 | - HTTP 加可自定义配置文件 |
| 167 | - 基于任务的命令执行 |
| 168 | |
| 169 | PoshC2: |
| 170 | - 基于 PowerShell/C# |
| 171 | - HTTP 加加密载荷 |
| 172 | - 基于 Cookie 的会话管理 |
| 173 | ``` |
| 174 | |
| 175 | ```bash |
| 176 | # 从 PCAP 或样本中提取 Cobalt Strike beacon 配置 |
| 177 | python3 << 'PYEOF' |
| 178 | # 使用 CobaltStrikeParser(pip install cobalt-strike-parser) |
| 179 | from cobalt_strike_parser import BeaconConfig |
| 180 | |
| 181 | try: |
| 182 | config = BeaconConfig.from_file("suspect.exe") |
| 183 | print("Cobalt Strike Beacon 配置:") |
| 184 | for key, value in config.items(): |
| 185 | print(f" {key}: {value}") |
| 186 | except Exception as e: |
| 187 | print(f"不是 Cobalt St |