Cheat sheet — Network Forensics¶
Companion to Module 09 — Network Forensics · CC BY 4.0 — print it, pin it, share it.
Last reviewed: 2026-07
Zeek — PCAP → structured logs (breadth first)¶
zeek -r capture.pcap # process a PCAP; writes conn.log, dns.log, http.log, …
zeek -r capture.pcap LogAscii::use_json=T # JSON logs instead of TSV
zeek-cut -h < conn.log # print the column header names
- Zeek collapses a 50 GB capture into greppable rows: one per connection, DNS query, HTTP transaction, file. This is the first pass that narrows where you point tshark.
The Zeek logs you actually read¶
conn.log every connection: id.orig_h/id.resp_h, proto, duration, orig_bytes, resp_bytes
dns.log every query: query, qtype_name, answers, rcode_name (NXDOMAIN = can't-find-C2)
http.log every transaction: host, uri, method, status_code, resp_mime_types
files.log every transferred file: md5, sha1, mime_type, source (check hash on VirusTotal)
ssl.log TLS metadata: server_name (SNI), subject, issuer — visible even without decryption
zeek-cut — slice columns from the logs¶
zeek-cut id.orig_h id.resp_h duration orig_bytes < conn.log | sort -k3 -nr | head # longest flows
zeek-cut query rcode_name < dns.log | grep NXDOMAIN | sort | uniq -c | sort -nr # NXDOMAIN storm
zeek-cut host uri method < http.log | grep -i '\.exe' # exe downloads
zeek-cut md5 mime_type source < files.log # file hashes
tshark — packet-level depth (pivot on the flagged flow)¶
tshark -r capture.pcap -Y "ip.addr==198.51.100.42" # display filter on the suspect IP
tshark -r capture.pcap -Y "dns" -T fields -e dns.qry.name # every DNS query name
tshark -r capture.pcap -Y "http.request" -T fields \
-e http.host -e http.request.uri # HTTP request lines
tshark -r capture.pcap --export-objects http,out/ # carve transferred HTTP objects
tshark -r capture.pcap -z conv,tcp -q # TCP conversation statistics
tshark -r capture.pcap -Y "tls.handshake.extensions_server_name" \
-T fields -e tls.handshake.extensions_server_name # SNI from TLS ClientHello
Wireshark / tshark display filters (the ones you re-type)¶
ip.addr == 10.0.0.5 host either direction (ip.src / ip.dst to pin)
tcp.port == 443 port either direction
http.request.method == "POST"
dns.qry.name contains "xyz" DGA-looking subdomains
tcp.flags.syn==1 && tcp.flags.ack==0 SYN-only (scans)
frame.time >= "2026-07-10 14:00:00" time window
- Right-click a packet → Follow → TCP/HTTP Stream to reassemble a full session interactively.
Gotchas worth remembering¶
- Zeek for breadth, tshark for depth. Scrolling a 50 GB PCAP in Wireshark is a prayer, not a strategy. Grep the Zeek logs to find the handful of suspect flows, then pivot to packet-level.
- Encryption doesn't end the investigation. You usually can't decrypt TLS — but SNI, cert subject/issuer, connection timing, and beacon interval are all still readable. A fresh IP contacted at a regular cadence is detectable by pattern alone.
files.loggives you the hash without the file. Check the md5/sha1 on VirusTotal to identify a dropper you never held. For unencrypted HTTP,--export-objectspulls the actual bytes.- A capture is attacker-unmodifiable ground truth (from the victim's side) — they can wipe the host but can't un-send the packets. If you didn't capture it, though, it's gone: capture first.
- Trace every AI/"looks suspicious" hunch to a specific log row and document the field values, then confirm the packets in Wireshark before it's a finding.
Comments
Sign in with GitHub to comment. Choose the type: Feedback (errors or suggestions on this page) · Hints (help for fellow learners — no spoilers) · General (anything else).