PCAP evidence has the highest forensic fidelity of any network artifact — it contains the actual conversation, not just metadata. But size and complexity require a systematic workflow to extract findings efficiently.
Running Zeek on a PCAP
# Install and run Zeek offline against a PCAP
zeek -r capture.pcap local --no-checksums
# --no-checksums: skip checksum verification (common issue with captured traffic)
# Output files generated:
ls -la *.log
# conn.log dns.log http.log ssl.log
# files.log weird.log notice.log dpd.log
# x509.log ftp.log smtp.log
# Analyze conn.log for beaconing
cat conn.log | zeek-cut ts id.orig_h id.resp_h proto service duration orig_bytes resp_bytes | \
grep "185.220.101.9" | sort -k1
# Find all external ESTABLISHED connections
cat conn.log | zeek-cut ts id.orig_h id.resp_h proto duration orig_bytes resp_bytes conn_state | \
awk '$8 == "SF"' | \
grep -v "10\.\|192\.168\.\|172\.\(1[6-9]\|2[0-9]\|3[01]\)\." | \
sort -k4 -rn | head -20
# Analyze dns.log for tunneling candidates
cat dns.log | zeek-cut ts id.orig_h query qtype_name answers | \
awk '{print length($3), $3}' | sort -rn | head -20
# Check files.log for transferred malware
cat files.log | zeek-cut ts source sha256 filename mime_type | \
grep -v "^-" | sort | uniq
# Submit all SHA256 hashes to VirusTotal
File Carving Workflow
# Method 1: Zeek file extraction (most automated)
zeek -r capture.pcap local --no-checksums FileExtract::PREFIX=./extracted/
# All files transferred over HTTP/FTP/SMTP are written to ./extracted/
# MD5/SHA256 hashes in files.log
ls -la ./extracted/
# Method 2: NetworkMiner (GUI — Windows)
# 1. Open NetworkMiner
# 2. File → Open → select capture.pcap
# 3. Click Files tab
# 4. Examine all extracted files with MD5 hashes
# 5. Right-click → Submit to VirusTotal (if online)
# Method 3: Wireshark HTTP export
# File → Export Objects → HTTP
# Exports all HTTP response bodies as files
# Limited to HTTP (not HTTPS, SMB, FTP)
# Method 4: tcpflow + manual carving
# Reconstruct all TCP streams as files:
tcpflow -r capture.pcap -o ./streams/
ls ./streams/
# Files named: [src_IP].[src_port]-[dst_IP].[dst_port]
# Look for streams containing MZ (PE executable) or PK (ZIP) headers:
for f in ./streams/*; do
magic=$(xxd "$f" 2>/dev/null | head -1 | awk '{print $2$3}')
case "$magic" in
"4d5a"*) echo "PE executable: $f" ;;
"504b03"*) echo "ZIP/Office file: $f" ;;
"25504446"*) echo "PDF: $f" ;;
*) ;;
esac
done
# Hash all carved files and check against VirusTotal
for f in ./extracted/*; do
hash=$(sha256sum "$f" | awk '{print $1}')
echo "$hash $f"
done | tee extracted_hashes.txt
SMB Lateral Movement in PCAP
# Identify SMB connections (TCP 445)
tshark -r capture.pcap \
-Y "tcp.dstport == 445" \
-T fields \
-e ip.src \
-e ip.dst \
| sort | uniq -c | sort -rn
# SMB2 file operations — what files were accessed/created
tshark -r capture.pcap \
-Y "smb2.cmd == 5" \
-T fields \
-e frame.time \
-e ip.src \
-e ip.dst \
-e smb2.filename
# SMB authentication (NTLM challenge-response)
# Look for NTLM auth events (may indicate pass-the-hash)
tshark -r capture.pcap \
-Y "ntlmssp" \
-T fields \
-e frame.time \
-e ip.src \
-e ip.dst \
-e ntlmssp.identifier
# Extract files transferred via SMB
# Zeek SMB file extraction:
zeek -r capture.pcap local --no-checksums FileExtract::PREFIX=./smb_extracted/
cat files.log | grep "smb\|SMB"
Building a Network Attack Timeline
#!/bin/bash
# Generate a network timeline from PCAP for IR report
PCAP="WS-JSMITH-01_network_20240902.pcap"
ATTACKER_IP="185.220.101.9"
OUTPUT="network_timeline.txt"
echo "=== NETWORK ATTACK TIMELINE ===" > "$OUTPUT"
echo "Source PCAP: $PCAP" >> "$OUTPUT"
echo "Analysis date: $(date -u +%Y-%m-%dT%H:%M:%SZ)" >> "$OUTPUT"
echo "" >> "$OUTPUT"
echo "=== FIRST CONTACT ===" >> "$OUTPUT"
tshark -r "$PCAP" \
-Y "ip.addr == $ATTACKER_IP" \
-T fields \
-e frame.time \
| head -1 >> "$OUTPUT"
echo "" >> "$OUTPUT"
echo "=== ALL CONNECTIONS TO/FROM ATTACKER ===" >> "$OUTPUT"
tshark -r "$PCAP" \
-Y "ip.addr == $ATTACKER_IP" \
-T fields \
-e frame.time \
-e ip.src \
-e ip.dst \
-e tcp.dstport \
-e tcp.srcport \
-e tcp.len \
>> "$OUTPUT"
echo "" >> "$OUTPUT"
echo "=== HTTP REQUESTS TO ATTACKER ===" >> "$OUTPUT"
tshark -r "$PCAP" \
-Y "ip.addr == $ATTACKER_IP and http.request" \
-T fields \
-e frame.time \
-e http.request.method \
-e http.request.uri \
-e http.user_agent \
-e http.content_length \
>> "$OUTPUT"
echo "" >> "$OUTPUT"
echo "=== FILES TRANSFERRED ===" >> "$OUTPUT"
zeek -r "$PCAP" local --no-checksums 2>/dev/null
cat files.log | zeek-cut ts source sha256 filename | \
grep "$ATTACKER_IP" >> "$OUTPUT"
echo "Timeline written to $OUTPUT"