mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-15 07:24:56 +03:00
c47eed6a64
- Fix 25 shell=True subprocess calls with list-based commands - Fix 49 verify=False in defensive skills (env-var override) - Add timeout to 231 HTTP/subprocess/socket calls - Fix 6 SQL injection patterns with whitelist validation - Replace 8 __import__() with standard imports - Remove 701 unused imports across 442 files - Add authorized-testing disclaimers to all offensive skills - Complete 11 incomplete skill directories - Expand 10 stub SKILL.md files with full content - Fix 2 YAML parse errors in frontmatter - Fix 5 pre-existing syntax errors - Convert 22 hardcoded paths/ports to environment variables - Back up 21 redundant skill pairs to .bak - Fix 2 global declaration errors - 724/724 skills with full folder anatomy (SKILL.md + agent.py + api-reference.md + LICENSE) - 0 compile errors across all 724 agent.py files
221 lines
7.3 KiB
Python
221 lines
7.3 KiB
Python
#!/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 <capture.pcap>")
|