4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / capture_and_plot.sh SH
#!/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 "$@"