#!/bin/bash # # capture_and_plot.sh - Capture and visualize CVE-2023-1206 trigger traffic # # This script: # 1. Captures network traffic on the Docker bridge # 2. Extracts packet timing data # 3. Generates visualizations of the burst patterns # set -e # Auto-detect Docker bridge for triple_cve_net detect_interface() { # First try to get the bridge name from the network local bridge=$(docker network inspect triple_cve_net 2>/dev/null | grep -oP '"com.docker.network.bridge.name": "\K[^"]+' || echo "") if [ -z "$bridge" ]; then # Try to find br-* interface from network ID local net_id=$(docker network inspect triple_cve_net 2>/dev/null | grep -oP '"Id": "\K[^"]+' | head -c 12 || echo "") if [ -n "$net_id" ]; then bridge="br-$net_id" fi fi if [ -z "$bridge" ]; then # Fallback: find any br-* interface bridge=$(ip link show 2>/dev/null | grep -oP 'br-[a-f0-9]+' | head -1) fi if [ -z "$bridge" ]; then # Last resort bridge="docker0" fi echo "$bridge" } INTERFACE="${1:-$(detect_interface)}" CAPTURE_TIME="${2:-30}" OUTPUT_DIR="./captures" TIMESTAMP=$(date +%Y%m%d_%H%M%S) PCAP_FILE="${OUTPUT_DIR}/triple_cve_${TIMESTAMP}.pcap" CSV_FILE="${OUTPUT_DIR}/triple_cve_${TIMESTAMP}.csv" PLOT_FILE="${OUTPUT_DIR}/triple_cve_${TIMESTAMP}.png" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' CYAN='\033[0;36m' NC='\033[0m' log_info() { echo -e "${GREEN}[+]${NC} $1"; } log_warn() { echo -e "${YELLOW}[!]${NC} $1"; } log_error() { echo -e "${RED}[-]${NC} $1"; } mkdir -p "$OUTPUT_DIR" cat << 'BANNER' ╔══════════════════════════════════════════════════════════════╗ ║ CVE-2023-1206 Traffic Capture & Visualization ║ ║ Triple CVE Covert Channel Analysis ║ ╚══════════════════════════════════════════════════════════════╝ BANNER # Check dependencies check_deps() { local missing=() command -v tshark >/dev/null 2>&1 || missing+=("tshark (wireshark-cli)") command -v python3 >/dev/null 2>&1 || missing+=("python3") if [ ${#missing[@]} -gt 0 ]; then log_error "Missing dependencies: ${missing[*]}" echo "Install with: sudo apt install wireshark-cli python3-matplotlib python3-pandas" exit 1 fi # Check Python packages python3 -c "import matplotlib" 2>/dev/null || { log_warn "matplotlib not found, installing..." pip3 install matplotlib --break-system-packages 2>/dev/null || pip3 install matplotlib } python3 -c "import pandas" 2>/dev/null || { log_warn "pandas not found, installing..." pip3 install pandas --break-system-packages 2>/dev/null || pip3 install pandas } } # Capture traffic capture_traffic() { log_info "Capturing on interface: $INTERFACE for ${CAPTURE_TIME}s" log_info "Output: $PCAP_FILE" echo "" log_warn "Start the triple CVE demo now!" echo " Terminal 1: ./run_triple_cve.sh responder" echo " Terminal 2: sudo ./run_triple_cve.sh initiator 'SECRET MESSAGE'" echo "" # Capture UDP traffic on our ports sudo tshark -i "$INTERFACE" -a duration:"$CAPTURE_TIME" \ -f "udp port 31336 or udp port 31337" \ -w "$PCAP_FILE" 2>/dev/null & TSHARK_PID=$! # Show countdown for i in $(seq $CAPTURE_TIME -1 1); do printf "\r${CYAN}[*]${NC} Capturing... %3d seconds remaining " $i sleep 1 done echo "" wait $TSHARK_PID 2>/dev/null || true log_info "Capture complete: $PCAP_FILE" } # Extract data to CSV extract_csv() { log_info "Extracting packet data to CSV..." tshark -r "$PCAP_FILE" -T fields \ -e frame.time_relative \ -e frame.time_delta \ -e ip.src \ -e ip.dst \ -e udp.srcport \ -e udp.dstport \ -e udp.length \ -e data.data \ -E header=y -E separator=, \ > "$CSV_FILE" 2>/dev/null PACKET_COUNT=$(wc -l < "$CSV_FILE") log_info "Extracted $((PACKET_COUNT - 1)) packets to $CSV_FILE" } # Generate visualization generate_plot() { log_info "Generating visualization..." python3 << PYTHON_SCRIPT import pandas as pd import matplotlib.pyplot as plt import matplotlib.patches as mpatches import numpy as np from datetime import datetime import sys # Read CSV try: df = pd.read_csv("$CSV_FILE") if len(df) == 0: print("No packets captured!") sys.exit(1) except Exception as e: print(f"Error reading CSV: {e}") sys.exit(1) # Rename columns for easier access df.columns = ['time_rel', 'time_delta', 'src_ip', 'dst_ip', 'src_port', 'dst_port', 'length', 'data'] # Convert time to float df['time_rel'] = pd.to_numeric(df['time_rel'], errors='coerce') df['time_delta'] = pd.to_numeric(df['time_delta'], errors='coerce') # Identify packet types by magic numbers in data def classify_packet(row): data = str(row.get('data', '')) port = row.get('dst_port', 0) # CVE-2023-1206 trigger magic: 0xCAFE1206 (little endian: 0612feca) if '0612feca' in data.lower() or 'cafe1206' in data.lower(): return 'TRIGGER (CVE-2023-1206)' # Sync magic: 0xDEAD0040 (little endian: 4000adde) elif '4000adde' in data.lower() or 'dead0040' in data.lower(): return 'SYNC (Key Agreement)' elif port == 31336: return 'TRIGGER (CVE-2023-1206)' elif port == 31337: return 'SYNC (Key Agreement)' else: return 'OTHER' df['packet_type'] = df.apply(classify_packet, axis=1) # Create figure with multiple subplots fig = plt.figure(figsize=(16, 12)) fig.suptitle('Triple CVE Covert Channel - Traffic Analysis\\nCVE-2023-1206 (Trigger) + CVE-2025-40040 (KSM Key Agreement)', fontsize=14, fontweight='bold') # Color scheme colors = { 'TRIGGER (CVE-2023-1206)': '#FF4444', 'SYNC (Key Agreement)': '#4444FF', 'OTHER': '#888888' } # Subplot 1: Packet timeline (scatter plot) ax1 = fig.add_subplot(3, 2, 1) for ptype in df['packet_type'].unique(): mask = df['packet_type'] == ptype ax1.scatter(df[mask]['time_rel'], [1]*sum(mask), c=colors.get(ptype, '#888888'), label=ptype, alpha=0.6, s=20) ax1.set_xlabel('Time (seconds)') ax1.set_ylabel('Packets') ax1.set_title('Packet Timeline') ax1.legend(loc='upper right', fontsize=8) ax1.set_yticks([]) ax1.grid(True, alpha=0.3) # Subplot 2: Packets per 100ms (histogram showing bursts) ax2 = fig.add_subplot(3, 2, 2) max_time = df['time_rel'].max() bins = np.arange(0, max_time + 0.1, 0.1) # 100ms bins for ptype in ['TRIGGER (CVE-2023-1206)', 'SYNC (Key Agreement)']: mask = df['packet_type'] == ptype if sum(mask) > 0: ax2.hist(df[mask]['time_rel'], bins=bins, alpha=0.7, label=ptype, color=colors.get(ptype, '#888888')) ax2.set_xlabel('Time (seconds)') ax2.set_ylabel('Packets per 100ms') ax2.set_title('Packet Rate Over Time (100ms bins) - Shows CVE-2023-1206 Burst') ax2.legend(loc='upper right', fontsize=8) ax2.grid(True, alpha=0.3) # Subplot 3: Inter-packet timing (to show burst pattern) ax3 = fig.add_subplot(3, 2, 3) trigger_mask = df['packet_type'] == 'TRIGGER (CVE-2023-1206)' if sum(trigger_mask) > 1: trigger_times = df[trigger_mask]['time_rel'].values inter_arrival = np.diff(trigger_times) * 1000 # Convert to ms ax3.plot(range(len(inter_arrival)), inter_arrival, 'r-', alpha=0.7, linewidth=0.5) ax3.scatter(range(len(inter_arrival)), inter_arrival, c='red', s=5, alpha=0.5) ax3.set_xlabel('Packet Number') ax3.set_ylabel('Inter-arrival Time (ms)') ax3.set_title('CVE-2023-1206 Trigger - Inter-Packet Timing') ax3.set_ylim(0, max(inter_arrival.max() * 1.1, 1)) else: ax3.text(0.5, 0.5, 'No trigger packets captured', ha='center', va='center') ax3.grid(True, alpha=0.3) # Subplot 4: Sync packet timing (key agreement rounds) ax4 = fig.add_subplot(3, 2, 4) sync_mask = df['packet_type'] == 'SYNC (Key Agreement)' if sum(sync_mask) > 1: sync_df = df[sync_mask].copy() sync_times = sync_df['time_rel'].values inter_arrival = np.diff(sync_times) * 1000 ax4.plot(range(len(inter_arrival)), inter_arrival, 'b-', alpha=0.7, linewidth=0.5) ax4.scatter(range(len(inter_arrival)), inter_arrival, c='blue', s=5, alpha=0.5) ax4.set_xlabel('Packet Number') ax4.set_ylabel('Inter-arrival Time (ms)') ax4.set_title('Key Agreement Sync - Inter-Packet Timing (256 rounds)') else: ax4.text(0.5, 0.5, 'No sync packets captured', ha='center', va='center') ax4.grid(True, alpha=0.3) # Subplot 5: Packet size distribution ax5 = fig.add_subplot(3, 2, 5) for ptype in df['packet_type'].unique(): mask = df['packet_type'] == ptype if sum(mask) > 0: ax5.hist(df[mask]['length'].dropna(), bins=20, alpha=0.7, label=ptype, color=colors.get(ptype, '#888888')) ax5.set_xlabel('Packet Size (bytes)') ax5.set_ylabel('Count') ax5.set_title('Packet Size Distribution') ax5.legend(loc='upper right', fontsize=8) ax5.grid(True, alpha=0.3) # Subplot 6: Statistics text ax6 = fig.add_subplot(3, 2, 6) ax6.axis('off') stats_text = f""" CAPTURE STATISTICS ══════════════════════════════════════ Total Packets: {len(df)} Capture Duration: {df['time_rel'].max():.2f} seconds PACKET BREAKDOWN ────────────────────────────────────── """ for ptype in df['packet_type'].unique(): count = sum(df['packet_type'] == ptype) stats_text += f" {ptype}: {count} packets\\n" # Detect phases trigger_packets = df[df['packet_type'] == 'TRIGGER (CVE-2023-1206)'] sync_packets = df[df['packet_type'] == 'SYNC (Key Agreement)'] if len(trigger_packets) > 0: trigger_start = trigger_packets['time_rel'].min() trigger_end = trigger_packets['time_rel'].max() trigger_duration = trigger_end - trigger_start trigger_rate = len(trigger_packets) / max(trigger_duration, 0.001) stats_text += f""" PHASE 1: CVE-2023-1206 TRIGGER ────────────────────────────────────── Start: {trigger_start:.3f}s Duration: {trigger_duration*1000:.1f}ms Packet Rate: {trigger_rate:.0f} pkt/s Total: {len(trigger_packets)} packets """ if len(sync_packets) > 0: sync_start = sync_packets['time_rel'].min() sync_end = sync_packets['time_rel'].max() sync_duration = sync_end - sync_start stats_text += f""" PHASE 2: KEY AGREEMENT (CVE-2025-40040) ────────────────────────────────────── Start: {sync_start:.3f}s Duration: {sync_duration:.1f}s Sync Packets: {len(sync_packets)} Expected: ~512 (256 rounds × 2 parties) """ ax6.text(0.05, 0.95, stats_text, transform=ax6.transAxes, fontfamily='monospace', fontsize=9, verticalalignment='top', bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.5)) plt.tight_layout() plt.savefig("$PLOT_FILE", dpi=150, bbox_inches='tight') print(f"Plot saved to: $PLOT_FILE") # Also save a summary print("\\n" + "="*60) print("CAPTURE SUMMARY") print("="*60) print(f"Total packets: {len(df)}") for ptype in df['packet_type'].unique(): print(f" {ptype}: {sum(df['packet_type'] == ptype)}") print("="*60) PYTHON_SCRIPT log_info "Visualization saved to: $PLOT_FILE" } # Open plot open_plot() { if command -v xdg-open >/dev/null 2>&1; then xdg-open "$PLOT_FILE" 2>/dev/null & elif command -v open >/dev/null 2>&1; then open "$PLOT_FILE" 2>/dev/null & fi } # Main main() { echo "Interface: $INTERFACE" echo "Capture time: ${CAPTURE_TIME}s" echo "Output directory: $OUTPUT_DIR" echo "" check_deps capture_traffic extract_csv generate_plot open_plot echo "" log_info "Done! Files:" echo " PCAP: $PCAP_FILE" echo " CSV: $CSV_FILE" echo " Plot: $PLOT_FILE" echo "" log_info "Open in Wireshark: wireshark $PCAP_FILE" } main "$@"