#!/usr/bin/env python3 """Wireshark/tshark packet analysis agent for network security investigations.""" import subprocess import shlex import os import sys def run_tshark(pcap_path, args): """Execute tshark with custom arguments.""" cmd = ["tshark", "-r", pcap_path] + shlex.split(args) result = subprocess.run(cmd, capture_output=True, text=True, timeout=120) return result.stdout.strip(), result.stderr.strip(), result.returncode def capture_live(interface, output_path, duration=60, capture_filter=None): """Start a live packet capture using tshark.""" cmd = ["tshark", "-i", interface, "-w", output_path, "-a", f"duration:{duration}"] if capture_filter: cmd += ["-f", capture_filter] result = subprocess.run(cmd, capture_output=True, text=True, timeout=duration + 10) return result.returncode == 0 def get_capture_summary(pcap_path): """Get overall PCAP capture statistics.""" stdout, _, _ = run_tshark(pcap_path, "-q -z io,stat,0") return stdout def get_protocol_hierarchy(pcap_path): """Get protocol hierarchy statistics.""" stdout, _, _ = run_tshark(pcap_path, "-q -z io,phs") return stdout def get_conversations(pcap_path, conv_type="ip"): """Get conversation statistics (ip, tcp, udp, ethernet).""" stdout, _, _ = run_tshark(pcap_path, f"-q -z conv,{conv_type}") return stdout def get_endpoints(pcap_path, endpoint_type="ip"): """Get endpoint statistics.""" stdout, _, _ = run_tshark(pcap_path, f"-q -z endpoints,{endpoint_type}") return stdout def extract_http_requests(pcap_path): """Extract HTTP requests with key fields.""" stdout, _, _ = run_tshark( pcap_path, '-Y "http.request" -T fields -e frame.time -e ip.src -e ip.dst ' '-e http.request.method -e http.host -e http.request.uri -e http.user_agent ' '-E separator="|"' ) requests = [] for line in stdout.splitlines(): parts = line.split("|") if len(parts) >= 6: requests.append({ "time": parts[0], "src": parts[1], "dst": parts[2], "method": parts[3], "host": parts[4], "uri": parts[5], "user_agent": parts[6] if len(parts) > 6 else "", }) return requests def extract_dns_queries(pcap_path): """Extract DNS queries and responses.""" stdout, _, _ = run_tshark( pcap_path, '-Y "dns" -T fields -e frame.time -e ip.src -e ip.dst ' '-e dns.qry.name -e dns.qry.type -e dns.flags.response ' '-E separator="|"' ) queries = [] for line in stdout.splitlines(): parts = line.split("|") if len(parts) >= 5: queries.append({ "time": parts[0], "src": parts[1], "dst": parts[2], "query": parts[3], "type": parts[4], "is_response": parts[5] if len(parts) > 5 else "0", }) return queries def extract_tls_info(pcap_path): """Extract TLS handshake information including JA3 fingerprints.""" stdout, _, _ = run_tshark( pcap_path, '-Y "tls.handshake.type==1" -T fields -e ip.src -e ip.dst ' '-e tls.handshake.extensions_server_name -e tls.handshake.ja3 ' '-E separator="|"' ) tls_sessions = [] for line in stdout.splitlines(): parts = line.split("|") if len(parts) >= 3: tls_sessions.append({ "client": parts[0], "server": parts[1], "sni": parts[2], "ja3": parts[3] if len(parts) > 3 else "", }) return tls_sessions def detect_suspicious_traffic(pcap_path): """Detect common suspicious traffic patterns.""" findings = [] # Large ICMP packets (possible data exfiltration) stdout, _, rc = run_tshark(pcap_path, '-Y "icmp && frame.len > 100" -T fields -e ip.src -e ip.dst -e frame.len') if stdout: findings.append({ "type": "Large ICMP", "description": "ICMP packets with large payloads detected", "count": len(stdout.splitlines()), }) # DNS TXT queries (possible tunneling) stdout, _, rc = run_tshark(pcap_path, '-Y "dns.qry.type==16" -T fields -e ip.src -e dns.qry.name') if stdout: findings.append({ "type": "DNS TXT Queries", "description": "DNS TXT record queries detected", "count": len(stdout.splitlines()), }) # Non-standard HTTP ports stdout, _, rc = run_tshark( pcap_path, '-Y "http && tcp.port != 80 && tcp.port != 443 && tcp.port != 8080" ' '-T fields -e ip.src -e ip.dst -e tcp.dstport' ) if stdout: findings.append({ "type": "HTTP on non-standard port", "description": "HTTP traffic on unusual ports", "count": len(stdout.splitlines()), }) return findings def export_http_objects(pcap_path, output_dir): """Export HTTP transferred objects.""" os.makedirs(output_dir, exist_ok=True) _, _, rc = run_tshark(pcap_path, f'--export-objects "http,{output_dir}"') files = [] for f in os.listdir(output_dir): fpath = os.path.join(output_dir, f) files.append({"name": f, "size": os.path.getsize(fpath)}) return files def apply_display_filter(pcap_path, display_filter, fields): """Apply a custom display filter and extract specified fields.""" field_str = " ".join(f"-e {f}" for f in fields) stdout, _, _ = run_tshark( pcap_path, f'-Y "{display_filter}" -T fields {field_str} -E separator="|"' ) results = [] for line in stdout.splitlines(): parts = line.split("|") results.append(dict(zip(fields, parts))) return results if __name__ == "__main__": print("=" * 60) print("Wireshark/tshark Network Analysis Agent") print("Packet analysis, protocol stats, artifact extraction") print("=" * 60) pcap = sys.argv[1] if len(sys.argv) > 1 else None if pcap and os.path.exists(pcap): print(f"\n[*] Analyzing: {pcap}") print("\n--- Capture Summary ---") summary = get_capture_summary(pcap) print(summary[:500] if summary else " No stats available") print("\n--- Protocol Hierarchy ---") hierarchy = get_protocol_hierarchy(pcap) print(hierarchy[:500] if hierarchy else " No hierarchy available") print("\n--- HTTP Requests ---") http = extract_http_requests(pcap) for r in http[:10]: print(f" {r['method']} {r['host']}{r['uri']}") print("\n--- DNS Queries ---") dns = extract_dns_queries(pcap) queries_only = [d for d in dns if d["is_response"] == "0"] print(f" Total DNS queries: {len(queries_only)}") print("\n--- TLS Sessions ---") tls = extract_tls_info(pcap) for t in tls[:10]: print(f" {t['client']} -> {t['sni']} (JA3={t['ja3'][:16]}...)" if t['ja3'] else f" {t['client']} -> {t['sni']}") print("\n--- Suspicious Traffic ---") suspicious = detect_suspicious_traffic(pcap) for s in suspicious: print(f" [!] {s['type']}: {s['description']} ({s['count']} occurrences)") else: print(f"\n[DEMO] Usage: python agent.py ")