pcap-triage

complete

· Security

stack
Python · scapy
links

Opening an unfamiliar capture in Wireshark means scrolling until something looks wrong. This does the first pass — the boring, mechanical questions you always ask before the interesting ones.

Output

$ pcap-triage capture.pcap
── endpoints ──────────────────────────
10.0.0.14      ⇄ 93.184.216.34    1.2 MB   443/tcp
10.0.0.14      ⇄ 8.8.8.8          4.1 KB    53/udp

── dns ────────────────────────────────
  cdn.example.com        A     93.184.216.34
  x7f2k9.dyn.example.net A     45.33.32.156   ⚠ high-entropy label

── notes ──────────────────────────────
  ⚠ 1 host contacted 47 distinct IPs in 12s

The one interesting part

Most of it is aggregation. The piece worth writing about is the high-entropy label check, which flags algorithmically generated domain names by measuring Shannon entropy over the leftmost label:

def entropy(label: str) -> float:
    counts = Counter(label)
    n = len(label)
    return -sum((c / n) * log2(c / n) for c in counts.values())

Above roughly 3.5 bits per character, a label stops looking like a word. It’s a crude heuristic with real false positives — CDN hostnames and hashed asset names trip it constantly — so it annotates rather than alerts.

Status

Finished, in the sense that it does what I wanted. Only reads TCP/UDP/DNS, ignores IPv6, and loads the whole capture into memory.