コマンド&コントロール通信の解析 は何をしますか?
使用するタイミング
- マルウェアサンプルのリバースエンジニアリングにより、プロトコル解析が必要なネットワーク通信が発見された場合
- 特定のC2フレームワーク(Cobalt Strike、Metasploit、Sliver)に対するネットワークレベルの検知シグネチャを構築する場合
- プライマリサーバ、フォールバックドメイン、デッドドロップを含むC2インフラストラクチャをマッピングする場合
- 暗号化またはエンコードされたC2トラフィックを解析し、コマンドセットとデータ形式を理解する場合
- C2インフラストラクチャのパターンとツールに基づいて、マルウェアを脅威アクターに関連付ける場合
使用しない場合: 一般的なネットワーク異常検知には使用しないでください。これは、マルウェア解析から得られた既知または疑わしいC2プロトコルを理解するためのものです。
前提条件
- マルウェアネットワークトラフィックのPCAPキャプチャ(サンドボックス、ネットワークタップ、またはフルパケットキャプチャから)
- パケットレベル分析のためのWireshark/tshark
- マルウェアバイナリ内のC2コードを理解するためのリバースエンジニアリングツール(Ghidra、dnSpy)
- プロトコル解析とリプレイのためのPython 3.8+(
scapy、dpkt、requests) - C2インフラストラクチャの相関分析のための脅威インテリジェンスデータベース(VirusTotal、Shodan、Censys)
- TLSベースのC2識別のためのJA3/JA3Sフィンガープリントデータベース
ワークフロー
ステップ1: C2チャネルの特定
C2通信に使用されるプロトコルとトランスポートを特定します:
C2通信チャネル:
━━━━━━━━━━━━━━━━━━━━━━━━━━━
HTTP/HTTPS: 最も一般的。標準的なWebトラフィックに紛れる
兆候: 定期的なPOST/GETリクエスト、特定のURIパターン、カスタムヘッダ
DNS: DNSクエリとレスポンスを介したデータトンネリング
兆候: 高頻度のTXTクエリ、長いサブドメイン名、高エントロピー
カスタムTCP/UDP: 非標準ポート上の独自バイナリプロトコル
兆候: 高ポート上の非HTTPトラフィック、不明なプロトコル
ICMP: ICMPエコー/応答ペイロードにエンコードされたデータ
兆候: 大規模または非標準ペイロードを持つICMPパケット
WebSocket: リアルタイムC2のための持続的双方向接続
兆候: WebSocketアップグレード後のバイナリフレーム
クラウドサービス: 正規のAPI(Telegram、Discord、Slack、GitHub)の利用
兆候: 予期しないプロセスからのクラウドサービスへのAPI呼び出し
電子メール: C2コマンドとデータ窃取のためのSMTP/IMAP
兆候: 非メールプロセスからの自動化された電子メール操作
ステップ2: ビーコンパターンの解析
定期的な通信パターンを特徴付けます:
from scapy.all import rdpcap, IP, TCP
from collections import defaultdict
import statistics
import json
packets = rdpcap("c2_traffic.pcap")
# 宛先ごとにTCP SYNパケットをグループ化
connections = defaultdict(list)
for pkt in packets:
if IP in pkt and TCP in pkt and (pkt[TCP].flags & 0x02):
key = f"{pkt[IP].dst}:{pkt[TCP].dport}"
connections[key].append(float(pkt.time))
# 各宛先のビーコン動作を分析
for dst, times in sorted(connections.items()):
if len(times) < 3:
continue
intervals = [times[i+1] - times[i] for i in range(len(times)-1)]
avg_interval = statistics.mean(intervals)
stdev = statistics.stdev(intervals) if len(intervals) > 1 else 0
jitter_pct = (stdev / avg_interval * 100) if avg_interval > 0 else 0
duration = times[-1] - times[0]
beacon_data = {
"destination": dst,
"connections": len(times),
"duration_seconds": round(duration, 1),
"avg_interval_seconds": round(avg_interval, 1),
"stdev_seconds": round(stdev, 1),
"jitter_percent": round(jitter_pct, 1),
"is_beacon": 5 < avg_interval < 7200 and jitter_pct < 25,
}
if beacon_data["is_beacon"]:
print(f"[!] ビーコン検出: {dst}")
print(f" 間隔: {avg_interval:.0f}秒 +/- {stdev:.0f}秒 ({jitter_pct:.0f}% ジッター)")
print(f" セッション数: {len(times)} (期間: {duration:.0f}秒)")
ステップ3: C2プロトコル構造のデコード
キャプチャトラフィックからメッセージ形式をリバースエンジニアリング:
# HTTPベースのC2プロトコル分析
import dpkt
import base64
with open("c2_traffic.pcap", "rb") as f:
pcap = dpkt.pcap.Reader(f)
for ts, buf in pcap:
eth = dpkt.ethernet.Ethernet(buf)
if not isinstance(eth.data, dpkt.ip.IP):
continue
ip = eth.data
if not isinstance(ip.data, dpkt.tcp.TCP):
continue
tcp = ip.data
if tcp.dport == 80 or tcp.dport == 443:
if len(tcp.data) > 0:
try:
http = dpkt.http.Request(tcp.data)
print(f"\n--- C2リクエスト ---")
print(f"メソッド: {http.method}")
print(f"URI: {http.uri}")
print(f"ヘッダ: {dict(http.headers)}")
if http.body:
print(f"ボディ ({len(http.body)} バイト):")
# Base64デコードを試行
try:
decoded = base64.b64decode(http.body)
print(f" デコード後: {decoded[:200]}")
except:
print(f" 生データ: {http.body[:200]}")
except:
pass
ステップ4: C2フレームワークの特定
観測されたパターンを既知のC2フレームワークと照合:
既知のC2フレームワークシグネチャ:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Cobalt Strike:
- デフォルトURI: /pixel、/submit.php、/___utm.gif、/ca、/dpixel
- Malleable C2プロファイルが全トラフィック特性をカスタマイズ
- JA3: プロファイルにより異なる(ja3er.comでカタログ化)
- ビーコン設定に透かしあり(ライセンスごとに一意)
- 設定抽出: CobaltStrikeParserまたは1768.pyを使用
Metasploit/Meterpreter:
- デフォルトステージングURIパターン: ランダム4文字チェックサム
- リバースHTTP(S)ハンドラパターン
- Meterpreter TLV(タイプ-長さ-値)プロトコル構造
Sliver:
- mTLS、HTTP、DNS、WireGuardトランスポートオプション
- Protobufエンコードメッセージ
- 通信に一意のインプラントID
Covenant:
- .NETベースのC2フレームワーク
- カスタマイズ可能なプロファイルを持つHTTP
- タスクベースのコマンド実行
PoshC2:
- PowerShell/C#ベース
- 暗号化ペイロードを持つHTTP
- Cookieベースのセッション管理
# PCAPまたはサンプルからCobalt Strikeビーコン設定を抽出
python3 << 'PYEOF'
# CobaltStrikeParserを使用 (pip install cobalt-strike-parser)
from cobalt_strike_parser import BeaconConfig
try:
config = BeaconConfig.from_file("suspect.exe")
print("Cobalt Strike ビーコン設定:")
for key, value in config.items():
print(f" {key}: {value}")
except Exception as e:
print(f"Cobalt Strikeビーコンではないか、解析エラー: {e}")
PYEOF
ステップ5: C2インフラストラクチャのマッピング
完全なC2インフラストラクチャとフェイルオーバーメカニズムを文書化:
# インフラストラクチャマッピング
import requests
import json
c2_indicators = {
"primary_c2": "185.220.101.42",
"domains": ["update.malicious.com", "backup.evil.net"],
"ports": [443, 8443],
"failover_dns": ["ns1.malicious-dns.com"],
}
# Shodanでエンリッチ
def shodan_lookup(ip, api_key):
resp = requests.get(f"https://api.shodan.io/shodan/host/{ip}?key={api_key}")
if resp.status_code == 200:
data = resp.json()
return {
"ip": ip,
"ports": data.get("ports", []),
"os": data.get("os"),
"org": data.get("org"),
"asn": data.get("asn"),
"country": data.get("country_code"),
"hostnames": data.get("hostnames", []),
"last_update": data.get("last_update"),
}
return None
# パッシブDNSでエンリッチ
def pdns_lookup(domain):
# VirusTotalパッシブDNSを使用
resp = requests.get(
f"https://www.virustotal.com/api/v3/domains/{domain}/resolutions",
headers={"x-apikey": VT_API_KEY}
)
if resp.status_code == 200:
data = resp.json()
resolutions = []
for r in data.get("data", []):
resolutions.append({
"ip": r["attributes"]["ip_address"],
"date": r["attributes"]["date"],
})
return resolutions
return []
ステップ6: ネットワーク検知シグネチャの作成
分析したC2特性に基づいて検知ルールを構築:
# 分析したC2用のSuricataルール
cat << 'EOF' > c2_detection.rules
# HTTPビーコンパターン
alert http $HOME_NET any -> $EXTERNAL_NET any (
msg:"MALWARE MalwareX C2 HTTP ビーコン";
flow:established,to_server;
http.method; content:"POST";
http.uri; content:"/gate.php"; startswith;
http.header; content:"User-Agent: Mozilla/5.0 (compatible; MSIE 10.0)";
threshold:type threshold, track by_src, count 5, seconds 600;
sid:9000010; rev:1;
)
# JA3フィンガープリント一致
alert tls $HOME_NET any -> $EXTERNAL_NET any (
msg:"MALWARE MalwareX TLS JA3 フィンガープリント";
ja3.hash; content:"a0e9f5d64349fb13191bc781f81f42e1";
sid:9000011; rev:1;
)
# DNSビーコン検出(高エントロピーサブドメイン)
alert dns $HOME_NET any -> any any (
msg:"MALWARE 疑わしいDNS C2トンネリング";
dns.query; pcre:"/^[a-z0-9]{20,}\./";
threshold:type threshold, track by_src, count 10, seconds 60;
sid:9000012; rev:1;
)
# 証明書ベース検出
alert tls $HOME_NET any -> $EXTERNAL_NET any (
msg:"MALWARE MalwareX 自己署名C2証明書";
tls.cert_subject; content:"CN=update.malicious.com";
sid:9000013; rev:1;
)
EOF
主要概念
| 用語 | 定義 |
|---|---|
| ビーコン | マルウェアからC2サーバへの定期的なチェックイン通信。パターン検出を避けるためにジッターが追加されることが多い |
| ジッター | ビーコン間隔に適用されるランダム化(例: 60秒 +/- 15%)。タイミングパターンの予測可能性を低下させ、検出を困難にする |
| Malleable C2 | Cobalt Strikeの機能。オペレータがC2トラフィックのすべての側面(URI、ヘッダ、エンコーディング)をカスタマイズし、正規サービスを模倣できる |
| デッドドロップ | C2コマンドがマルウェアによって取得されるための中間的な場所(ペーストサイト、クラウドストレージ、ソーシャルメディア) |
| ドメインフロンティング | TLS SNIで信頼できるCDNドメインを使用しつつ、異なるバックエンドにルーティングする。C2トラフィックが正規サービス宛に見えるようにする |
| Fast Flux | C2ドメインのDNSレコードを急速に変更し、多数のIPに分散させ、テイクダウンを困難にする |
| C2フレームワーク | C2サーバ、インプラントジェネレータ、オペレータインターフェースを提供するソフトウェアツールキット(Cobalt Strike、Metasploit、Sliver、Covenant) |
ツールとシステム
- Wireshark: パケットレベルでの詳細なC2プロトコル分析のためのパケット解析ツール
- RITA (Real Intelligence Threat Analytics): Zeekログを分析してビーコン検出とDNSトンネリングを行うオープンソースツール
- CobaltStrikeParser: サンプルやメモリダンプからCobalt Strikeビーコン設定を抽出するツール
- JA3/JA3S: TLS実装の特性によりC2フレームワークを識別するためのTLSフィンガープリンティング手法
- Shodan/Censys: C2インフラストラクチャをマッピングし、関連サーバを特定するためのインターネットスキャンプラットフォーム
一般的なシナリオ
シナリオ: カスタムC2プロトコルのリバースエンジニアリング
コンテキスト: マルウェアサンプルがTCPポート8443上で未知のバイナリプロトコルを使用してC2サーバと通信している。コマンドセットを理解し検知シグネチャを構築するために、このプロトコルをデコードする必要がある。
アプローチ:
- PCAPをTCPポート8443の会話でフィルタリングし、TCPストリームを抽出する
- 最初の数回のやり取りを分析し、ハンドシェイク/認証メカニズムを特定する
- メッセージ構造(長さプレフィックス、タイプフィールド、ペイロードエンコーディング)をマッピングする
- Ghidraによるマルウェアの送受信関数の逆アセンブル結果と相互参照する
- コマンドディスパッチャを特定し、各コマンドコードの機能を文書化する
- 継続的なトラフィック分析のためのPythonプロトコルデコーダを構築する
- プロトコルハンドシェイクまたは静的ヘッダバイトに一致するSuricataルールを作成する
落とし穴:
- プロトコルが静的であると仮定すること。一部のC2フレームワークはハンドシェイク中に暗号化をネゴシエートする
- すべてのコマンドタイプを見るために十分なトラフィックをキャプチャしていないこと(一部のコマンドは稀)
- プライマリチャネルが失敗したときにアクティブになるフォールバックC2チャネル(DNS、ICMP)を見逃すこと
- 暗号化されたペイロードデータとプロトコルフレーミング構造を混同すること
出力形式
C2通信分析レポート
===================================
サンプル: malware.exe (SHA-256: e3b0c44...)
C2フレームワーク: Cobalt Strike 4.9
ビーコン設定
C2サーバ: hxxps://185.220.101[.]42/updates
ビーコンの種類: HTTPS(リバース)
スリープ: 60 秒
ジッター: 15%
ユーザーエージェント: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
URI(GET): /dpixel
URI(POST): /submit.php
透かし: 1234567890
プロトコル分析
トランスポート: HTTPS (TLS 1.2)
JA3ハッシュ: a0e9f5d64349fb13191bc781f81f42e1
証明書: CN=Microsoft Update(自己署名)
コーディング: Base64 (XOR鍵 0x69)
コマンド形式: [4B 長さ][4B コマンドID][ペイロード]
コマンドセット
0x01 - Sleep ビーコン間隔変更
0x02 - Shell cmd.exeコマンド実行
0x03 - Download ファイルをC2から転送
0x04 - Upload ファイルをC2に窃取
0x05 - Inject プロセスインジェクション
0x06 - Keylog キーロガー開始
0x07 - Screenshot 画面キャプチャ
インフラストラクチャ
プライマリ: 185.220.101[.]42 (AS12345, Hosting Co, NL)
フォールバック: 91.215.85[.]17 (AS67890, VPS Provider, RU)
DNS: update.malicious[.]com -> 185.220.101[.]42
レジストラ: NameCheap
登録日: 2025-09-01
検知シグネチャ
SID 9000010: HTTPビーコンパターン
SID 9000011: JA3 TLSフィンガープリント
SID 9000013: C2証明書一致