Chapter 34: Network Forensics and Traffic Analysis

"Every packet tells a story. The art of network forensics is learning to read the narrative hidden in the noise." --- Richard Bejtlich, The Practice of Network Security Monitoring

The Packet That Cracked the Case

In 2014, a financial services company noticed something odd in their monthly bandwidth reports. Outbound traffic to a small hosting provider in Eastern Europe had been steadily increasing for six months --- from barely measurable to 2 GB per day. Nobody could explain it.

It turned out to be a data exfiltration channel. An attacker had compromised a database administrator's workstation months earlier and was slowly siphoning customer records --- encrypted and chunked into what looked like normal HTTPS traffic. The only reason anyone noticed was a curious network engineer who happened to look at traffic patterns, not content. That is network forensics: finding the story the packets are telling, even when the content is encrypted.

You might wonder: if the traffic was encrypted, how do you analyze it? You would be surprised how much you can learn without reading content. Timing, volume, patterns, destinations, protocol behavior --- metadata tells a remarkable story.


The Forensic Investigation Workflow

Before diving into tools and techniques, understand the structured workflow that guides every network forensic investigation. Jumping straight into Wireshark without a plan is how you waste hours and miss critical evidence.

flowchart TD
    A["1. TRIGGER<br/>Alert, anomaly report,<br/>or intelligence tip"] --> B["2. SCOPE DEFINITION<br/>What timeframe?<br/>What systems?<br/>What are we looking for?"]
    B --> C["3. EVIDENCE ACQUISITION<br/>Capture packets (tcpdump)<br/>Collect flow data (NetFlow)<br/>Preserve existing captures<br/>Hash everything immediately"]
    C --> D["4. INITIAL TRIAGE<br/>Protocol hierarchy<br/>Top conversations by volume<br/>DNS anomalies<br/>Known-bad IOC matching"]
    D --> E["5. DEEP ANALYSIS<br/>Follow suspicious streams<br/>Decode protocols<br/>Extract artifacts<br/>Build timeline"]
    E --> F["6. TIMELINE RECONSTRUCTION<br/>Map events chronologically<br/>Correlate with host logs<br/>Identify initial compromise<br/>Track lateral movement"]
    F --> G["7. REPORTING<br/>Document findings<br/>Preserve chain of custody<br/>Prepare evidence for legal"]

    style A fill:#3498db,color:#fff
    style C fill:#e74c3c,color:#fff
    style E fill:#e67e22,color:#fff
    style F fill:#8e44ad,color:#fff

Packet Capture for Forensics

Capture Strategy: Full vs. Header vs. Flow

Not every investigation requires full packet capture. Understanding the trade-offs helps you choose the right level of detail for the storage budget and analytical need.

StrategyWhat It CapturesStorage (1 Gbps link)Forensic ValueBest For
Full packet captureEntire packet including payload~10 TB/dayMaximum: reconstruct files, read contentIncident response, targeted capture
Header-only (snaplen)Packet headers, truncated payload~1 TB/dayConnection tracking, protocol analysisBroad monitoring, compliance
Flow data (NetFlow/IPFIX)Connection metadata only~10 GB/dayTraffic patterns, anomaly detectionLong-term trending, baseline building

Why not just capture everything all the time? Math. A 10 Gbps network link generates roughly 100 TB of pcap data per day. Even with cheap storage, that is expensive and impractical. Most organizations use a tiered approach: flow data for everything with long retention, header captures for key network segments with medium retention, and full packet capture triggered by alerts or on critical segments with short retention. The goal is to have enough data to answer forensic questions without bankrupting the storage budget.

Practical tcpdump Commands for Forensic Capture

tcpdump is the Swiss Army knife of packet capture. Every security practitioner needs to know these commands cold --- during an incident at 3 AM, you will not have time to read the man page.

# ================================================
# BASIC CAPTURES
# ================================================

# Capture on interface eth0, write to file
$ sudo tcpdump -i eth0 -w /evidence/capture_$(date +%Y%m%d_%H%M%S).pcap

# Capture with rotation: new file every 100MB, keep 50 files max
# -G 3600 creates a new file every hour
$ sudo tcpdump -i eth0 -w /captures/cap_%Y%m%d_%H%M%S.pcap \
    -C 100 -W 50 -G 3600 -Z root

# ================================================
# TARGETED FORENSIC CAPTURES
# ================================================

# Capture all traffic to/from a suspect host
$ sudo tcpdump -i eth0 host 10.0.1.105 -w /evidence/suspect_host.pcap

# Capture traffic between two specific hosts (suspect and C2)
$ sudo tcpdump -i eth0 \
    'host 10.0.1.105 and host 185.234.72.19' \
    -w /evidence/c2_traffic.pcap

# Capture DNS traffic only (for DNS tunneling investigation)
$ sudo tcpdump -i eth0 port 53 -w /evidence/dns_traffic.pcap

# Capture SYN packets only (connection attempts = port scanning)
$ sudo tcpdump -i eth0 \
    'tcp[tcpflags] & (tcp-syn) != 0 and tcp[tcpflags] & (tcp-ack) == 0' \
    -w /evidence/syn_scan.pcap

# Capture traffic on non-standard ports (potential C2)
$ sudo tcpdump -i eth0 \
    'not port 80 and not port 443 and not port 53 and not port 22' \
    -w /evidence/unusual_ports.pcap

# ================================================
# LIVE ANALYSIS (quick triage without saving)
# ================================================

# Watch DNS queries in real-time
$ sudo tcpdump -i eth0 -n port 53 -l | \
    awk '/A\?/ {print $NF}'

# Watch HTTP GET requests and Host headers
$ sudo tcpdump -i eth0 -A -s 0 'tcp port 80' | \
    grep -E "^(GET|POST|Host:)"

# Watch for SMB traffic (lateral movement indicator)
$ sudo tcpdump -i eth0 -n 'tcp port 445 or tcp port 139'

# ================================================
# HEADER-ONLY CAPTURE (save space)
# ================================================

# Capture only first 96 bytes of each packet (headers)
$ sudo tcpdump -i eth0 -s 96 -w /evidence/headers_only.pcap
Packet captures may contain sensitive data --- credentials transmitted over unencrypted protocols, personal data, financial information, health records. Handle pcap files with the same sensitivity as the data they contain:
- Store captures in encrypted storage with restricted access
- Limit access to authorized investigators only
- Delete captures when the investigation is complete (unless legal hold requires retention)
- Document chain of custody for captures that may become legal evidence
- Be aware of legal requirements: in some jurisdictions, intercepting network traffic requires consent, court order, or specific authorization (Wiretap Act, GDPR, country-specific laws)
- Never capture on networks you do not own or have explicit authorization to monitor

Wireshark: Deep Packet Analysis

Wireshark is the standard tool for interactive packet analysis. While tcpdump captures, Wireshark helps you understand what was captured.

Essential Display Filters for Forensic Analysis

Mastering display filters is the difference between efficient analysis and hours of scrolling through millions of packets:

# ================================================
# PROTOCOL FILTERS
# ================================================
dns                         # DNS traffic only
http                        # HTTP traffic only
tls                         # TLS/SSL traffic only
smb || smb2                 # SMB traffic (lateral movement)
kerberos                    # Kerberos (credential attacks)
ldap                        # LDAP (AD enumeration)

# ================================================
# ADDRESS AND PORT FILTERS
# ================================================
ip.addr == 10.0.1.105                    # Traffic to/from this IP
ip.src == 10.0.1.105 && ip.dst != 10.0.0.0/8  # Outbound from suspect
tcp.port == 443                          # HTTPS traffic
tcp.dstport == 4444                      # Common Metasploit port
tcp.port in {80,443,8080,8443}           # Web ports

# ================================================
# TCP ANALYSIS FILTERS (detecting issues)
# ================================================
tcp.analysis.retransmission              # Retransmissions (network issues)
tcp.analysis.zero_window                 # Zero window (congestion)
tcp.analysis.duplicate_ack               # Duplicate ACKs
tcp.flags.rst == 1                       # RST packets (connection refused)
tcp.flags.syn==1 && tcp.flags.ack==0     # SYN only (port scan indicator)

# ================================================
# HTTP FORENSIC FILTERS
# ================================================
http.request.method == "POST"            # POST requests (data submission)
http.response.code >= 400                # Error responses
http.request.uri contains "/admin"       # Admin page access
http.user_agent contains "PowerShell"    # PowerShell downloading
http.content_type contains "application" # Binary downloads

# ================================================
# DNS FORENSIC FILTERS
# ================================================
dns.qry.name contains "evil"            # Queries for suspicious domains
dns.flags.rcode == 3                    # NXDOMAIN (DGA indicator)
dns.qry.type == 16                      # TXT records (tunneling)
dns.resp.len > 512                      # Large DNS responses (tunneling)

# ================================================
# TLS FORENSIC FILTERS
# ================================================
tls.handshake.type == 1                  # Client Hello (SNI visible)
tls.handshake.extensions_server_name     # Server Name Indication
tls.handshake.type == 1 && !tls.handshake.extensions_server_name
                                         # TLS without SNI (suspicious)

# ================================================
# COMBINATION FILTERS
# ================================================
ip.src==10.0.1.105 && !(dns || arp || icmp)  # Non-trivial traffic from suspect
!(arp || dns || icmp || ssdp || mdns)         # Filter out noise

Analysis Workflow

Here is a structured approach for every pcap analysis.

Step 1: Get the big picture. Open Statistics > Protocol Hierarchy. This shows the distribution of protocols. Unexpected protocols are immediately suspicious --- why is there IRC traffic on your corporate network? Why is a workstation speaking raw TCP on port 4444?

Step 2: Identify conversations. Open Statistics > Conversations > TCP tab. Sort by Bytes descending. The largest conversations by volume are often the most interesting for exfiltration detection. Note any conversations with external IPs you do not recognize.

Step 3: Check DNS. Filter for dns and look for:

  • Queries to domains you do not recognize
  • Unusually long subdomain strings (DNS tunneling)
  • High volume of NXDOMAIN responses from a single host (DGA malware)
  • Queries bypassing your internal resolver (going directly to 8.8.8.8)

Step 4: Follow TCP streams. Right-click a packet in a conversation of interest, select "Follow > TCP Stream." Wireshark reassembles the full conversation, showing the data as exchanged. For HTTP traffic, this reveals complete requests and responses.

Step 5: Export objects. File > Export Objects > HTTP extracts all files transferred over HTTP. This is how you recover malware samples, exfiltrated documents, or dropped payloads from a capture.

TLS Analysis: When You Cannot See Content

With most traffic encrypted via TLS, content inspection is often impossible. But TLS metadata reveals a surprising amount:

# Extract Server Name Indication (SNI) from TLS Client Hello
# SNI tells you what hostname the client requested
$ tshark -r capture.pcap -Y "tls.handshake.type == 1" \
    -T fields -e ip.src -e ip.dst -e tls.handshake.extensions_server_name \
    | sort | uniq -c | sort -rn | head -20

# TLS connections WITHOUT SNI are suspicious (may indicate C2)
$ tshark -r capture.pcap \
    -Y "tls.handshake.type == 1 && !tls.handshake.extensions_server_name" \
    -T fields -e ip.src -e ip.dst -e tcp.dstport

# Extract JA3 fingerprints (client TLS behavior fingerprint)
$ tshark -r capture.pcap -Y "tls.handshake.type == 1" \
    -T fields -e ip.src -e ip.dst -e tls.handshake.ja3 \
    | sort | uniq -c | sort -rn
# Compare JA3 hashes against ja3er.com or threat intel feeds
JA3 fingerprinting, developed by Salesforce engineers John Althouse, Jeff Atkinson, and Josh Atkins, creates an MD5 hash of the TLS Client Hello parameters: TLS version, accepted cipher suites, extensions list, elliptic curves, and elliptic curve point formats. Different applications produce different JA3 hashes because they support different TLS configurations.

This means you can identify Cobalt Strike, Metasploit, specific malware families, or even specific versions of web browsers by their TLS fingerprint --- even though you cannot see the encrypted content. JA3S does the same for the server response. The combination of JA3 (client) and JA3S (server) is highly specific.

Known JA3 hashes for malware:
- Cobalt Strike default: `72a589da586844d7f0818ce684948eea`
- Metasploit Meterpreter: `5d79b0ab9d7c9d9dfef20a4a3b9b3f9d`
- Trickbot: `6734f37431670b3ab4292b8f60f29984`

Threat intelligence feeds now routinely include JA3 hashes alongside IP addresses and domain names as indicators of compromise.

NetFlow/IPFIX for Traffic Pattern Analysis

Full packet capture is expensive and impractical for long-term storage. NetFlow and IPFIX provide connection metadata without packet payloads --- think of it as phone call records versus recordings. You know who called whom, when, for how long, and how much data was exchanged, but not what was said.

What NetFlow Records Contain

Source IP:          10.0.1.105
Destination IP:     185.234.72.19
Source Port:        49832
Destination Port:   443
Protocol:           TCP (6)
Start Time:         2026-03-12 14:23:07.123
End Time:           2026-03-12 14:23:52.456
Duration:           45.333 seconds
Packets:            127
Bytes:              234,567
TCP Flags:          SYN, ACK, PSH, FIN
Input Interface:    GigabitEthernet0/1
Output Interface:   GigabitEthernet0/0

Analyzing NetFlow Data

# Using nfdump to analyze NetFlow data

# Top 10 talkers by bytes in the last hour
$ nfdump -r /data/netflow/nfcapd.202603121400 \
    -s srcip/bytes -n 10

# All connections to a suspicious IP
$ nfdump -r /data/netflow/nfcapd.202603121400 \
    'dst ip 185.234.72.19'

# Large outbound transfers (possible exfiltration)
# Find transfers >100MB to external IPs
$ nfdump -r /data/netflow/nfcapd.202603121400 \
    'bytes > 100000000 and dst net not 10.0.0.0/8 and dst net not 172.16.0.0/12' \
    -s dstip/bytes -n 20

# Detect port scanning: single source, many SYN packets, few responses
$ nfdump -r /data/netflow/nfcapd.202603121400 \
    -s srcip/flows -n 10 \
    'flags S and not flags A and packets < 4'

# Time-series: bytes per 5-minute interval to suspicious destination
$ nfdump -R /data/netflow/ \
    'dst ip 185.234.72.19' \
    -t 2026/03/12.00:00-2026/03/12.23:59 \
    -o "fmt:%ts %td %byt" -a

Identifying Command-and-Control (C2) Communication

C2 traffic is the communication channel between malware on a compromised system and the attacker's infrastructure. Detecting C2 is one of the most valuable capabilities in network forensics because it reveals active compromise.

C2 Communication Patterns

graph TD
    subgraph "C2 Detection Methods"
        B["BEACONING<br/>Regular interval connections<br/>Consistent packet sizes<br/>Small jitter (+/- 10%)<br/><br/>Detection: Statistical analysis<br/>of connection intervals<br/>Jitter/mean ratio < 0.1"]

        D["DNS TUNNELING<br/>Data encoded in subdomains<br/>Long domain names (>30 chars)<br/>High volume to single domain<br/>TXT/NULL record queries<br/><br/>Detection: Entropy analysis<br/>Query length distribution"]

        H["HTTP/S C2<br/>Mimics normal browsing<br/>Uses cloud services<br/>Data in headers/cookies/body<br/>Uncommon User-Agents<br/><br/>Detection: JA3 fingerprinting<br/>Timing analysis"]

        DF["DOMAIN FRONTING<br/>CDN hides true destination<br/>SNI: legitimate.com<br/>Host header: c2-server.com<br/><br/>Detection: SNI vs Host<br/>header mismatch"]
    end

    style B fill:#3498db,color:#fff
    style D fill:#e67e22,color:#fff
    style H fill:#e74c3c,color:#fff
    style DF fill:#8e44ad,color:#fff

Detecting Beaconing

Beaconing is the telltale heartbeat of most C2 implants. The malware needs to check in periodically to receive commands. Even with jitter, the regularity is detectable because human browsing is bursty and irregular, while C2 is metronomic.

# Extract timing of connections from suspect host to external IP
$ sudo tcpdump -r capture.pcap -n 'host 185.234.72.19' -tt 2>/dev/null | \
    awk '{print $1}' | \
    awk 'NR>1 {printf "%.1f\n", $1-prev} {prev=$1}'
# Output showing intervals between packets:
# 59.8
# 60.1
# 60.3
# 59.9
# 60.0
# Consistent ~60 second intervals = beaconing

# Using Wireshark: filter for suspect traffic, then
# Statistics > I/O Graph with 1-second interval
# Look for regular spikes at consistent intervals

# Python script for beacon detection from pcap timestamps:
$ tshark -r capture.pcap \
    -Y "ip.src == 10.0.1.105 && ip.dst == 185.234.72.19" \
    -T fields -e frame.time_epoch | \
    python3 -c "
import sys, statistics
times = [float(line) for line in sys.stdin]
intervals = [times[i+1]-times[i] for i in range(len(times)-1)]
if intervals:
    mean = statistics.mean(intervals)
    stdev = statistics.stdev(intervals) if len(intervals) > 1 else 0
    jitter_ratio = stdev/mean if mean > 0 else 999
    print(f'Connections: {len(times)}')
    print(f'Mean interval: {mean:.1f}s')
    print(f'Std deviation: {stdev:.1f}s')
    print(f'Jitter ratio: {jitter_ratio:.3f}')
    print(f'BEACON DETECTED' if jitter_ratio < 0.1 else 'Unlikely beacon')
"
During an incident response, a team captured 48 hours of full packet data from a compromised subnet. The attacker was using Cobalt Strike with a malleable C2 profile that made traffic look like legitimate jQuery CDN requests. The GET requests returned what appeared to be jQuery JavaScript code, complete with valid function definitions and comments.

But when the timing of requests from the compromised host was analyzed --- one request every 5 minutes, with sub-second consistency --- the beaconing pattern was unmistakable. Legitimate web browsing is bursty: rapid page loads with minutes or hours of silence. C2 beaconing is metronomic: request, wait, request, wait, with machine-like precision.

The timing analysis identified three additional compromised hosts that had not been known about. They were all beaconing to the same C2 domain with slightly different intervals (300s, 600s, 900s) but the same consistency. The attacker had configured different sleep intervals for different hosts, but the regularity betrayed them all.

Detecting DNS Tunneling

DNS tunneling encodes data in DNS queries and responses. An attacker exfiltrates data by encoding it in subdomain labels:

Normal DNS query:    www.google.com           (15 chars)
Tunneled query:      aGVsbG8gd29ybGQ.x2.evil.com   (30+ chars)
                     ^^^^^^^^^^^^^^^^^
                     Base64-encoded data
# Analyze DNS query lengths from a pcap file
$ tshark -r capture.pcap -Y "dns.qry.name" \
    -T fields -e dns.qry.name | \
    awk -F. '{total=0; for(i=1;i<=NF;i++) total+=length($i);
    print total, $0}' | sort -rn | head -20

# Output:
# 87 aGVsbG8gd29ybGQgdGhpcyBpcyBhIHRlc3Q.x2.data.evil.com
# 82 c2VjcmV0IGRhdGEgZXhmaWx0cmF0aW9u.x3.data.evil.com
# 45 long-but-normal-subdomain.cdn.cloudflare.com
# 12 www.google.com

# Count unique subdomains per base domain
# A domain with thousands of unique subdomains from one host = tunneling
$ tshark -r capture.pcap -Y "dns.qry.name" \
    -T fields -e ip.src -e dns.qry.name | \
    awk '{split($2,a,"."); base=a[length(a)-1]"."a[length(a)]; print $1, base}' | \
    sort | uniq -c | sort -rn | head -10

# Measure entropy of subdomain labels (high entropy = encoded data)
$ tshark -r capture.pcap -Y "dns.qry.name" \
    -T fields -e dns.qry.name | \
    python3 -c "
import sys, math, collections
for line in sys.stdin:
    domain = line.strip()
    subdomain = domain.split('.')[0]
    if len(subdomain) > 10:
        freq = collections.Counter(subdomain)
        entropy = -sum(c/len(subdomain) * math.log2(c/len(subdomain))
                      for c in freq.values())
        if entropy > 3.5 and len(subdomain) > 20:
            print(f'HIGH ENTROPY ({entropy:.2f}): {domain}')
"

Detecting Domain Generation Algorithms (DGAs)

DGA malware generates pseudo-random domain names to contact C2 servers. The attacker registers a few; the malware queries many. Most queries return NXDOMAIN.

# Find hosts with abnormally high NXDOMAIN rates
$ tshark -r capture.pcap -Y "dns.flags.rcode == 3" \
    -T fields -e ip.src | sort | uniq -c | sort -rn | head -10

# Output:
# 3847  10.0.1.105    <-- 3847 queries for non-existent domains!
#   12  10.0.1.22
#    3  10.0.1.15

# Examine the domains queried by the suspicious host
$ tshark -r capture.pcap \
    -Y "dns.flags.rcode == 3 && ip.src == 10.0.1.105" \
    -T fields -e dns.qry.name | head -20

# Output (DGA-generated domains):
# a8f72kd9.com
# p3x91mnz.net
# k7hb2qrt.com
# m4nz8fwx.org
# ...all random-looking, none resolve

Reconstructing an Attack Timeline from Pcap

One of the most valuable skills in network forensics is building a timeline of an attack from packet captures. This is the evidence that tells the complete story of what happened, when, and how.

Step-by-Step Timeline Reconstruction

# Step 1: Establish the timeframe
$ capinfos capture.pcap | grep -E "First|Last|Number"
Number of packets:   2,847,291
First packet time:   2026-03-10 08:14:23.456789
Last packet time:    2026-03-12 16:42:11.234567

# Step 2: Find first connection to C2 (initial compromise indicator)
$ tshark -r capture.pcap \
    -Y "ip.addr == 185.234.72.19" \
    -T fields -e frame.time -e ip.src -e ip.dst -e tcp.dstport \
    | head -5
# 2026-03-10 09:23:45  10.0.1.105  185.234.72.19  443
# This was the first C2 callback

# Step 3: What happened just before the C2 callback?
# (Find the initial infection vector)
$ tshark -r capture.pcap \
    -Y "ip.addr == 10.0.1.105 && frame.time < \"2026-03-10 09:24:00\"" \
    -T fields -e frame.time -e ip.src -e ip.dst -e tcp.dstport -e http.host \
    | tail -20
# 2026-03-10 09:22:31  10.0.1.105  93.184.216.34  80  phishing-site.evil
# User visited phishing page at 09:22, malware called home at 09:23

# Step 4: Track lateral movement from compromised host
$ tshark -r capture.pcap \
    -Y "ip.src == 10.0.1.105 && tcp.flags.syn == 1 \
        && tcp.flags.ack == 0 && ip.dst != 185.234.72.19" \
    -T fields -e frame.time -e ip.dst -e tcp.dstport | sort
# 2026-03-10 10:45:12  10.0.1.20   445   <-- SMB to file server
# 2026-03-10 11:02:33  10.0.1.30   3389  <-- RDP to app server
# 2026-03-10 14:18:01  10.0.2.10   22    <-- SSH to database server

# Step 5: Quantify data exfiltration
$ tshark -r capture.pcap \
    -Y "ip.src == 10.0.2.10 && ip.dst == 185.234.72.19" \
    -T fields -e frame.len | \
    awk '{sum+=$1} END {printf "Exfiltrated: %.2f GB\n", sum/1073741824}'
# Exfiltrated: 2.14 GB

Reconstructed Timeline

sequenceDiagram
    participant U as User (10.0.1.105)
    participant P as Phishing Site
    participant C2 as C2 Server (185.234.72.19)
    participant FS as File Server (10.0.1.20)
    participant AS as App Server (10.0.1.30)
    participant DB as Database (10.0.2.10)

    Note over U: Mar 10, 09:22 - User clicks phishing link
    U->>P: HTTP GET /invoice.html
    P->>U: Malicious JavaScript + exploit

    Note over U: Mar 10, 09:23 - Malware installed, C2 established
    U->>C2: TLS Client Hello (initial beacon)
    C2->>U: Commands: enumerate network

    Note over U: Mar 10, 10:45 - Lateral movement begins
    U->>FS: SMB (port 445) - Credential harvesting
    Note over FS: Mimikatz extracts domain admin credentials

    Note over U: Mar 10, 11:02 - Pivot to app server
    U->>AS: RDP (port 3389) with stolen admin creds

    Note over AS: Mar 10, 14:18 - Reach database
    AS->>DB: SSH (port 22) - Cross segment boundary

    Note over DB: Mar 10, 15:00 - Mar 12, 14:00
    DB->>C2: Data exfiltration (2.14 GB over 47 hours)
    Note over DB: Slow trickle to avoid volume-based alerts

    Note over U: Mar 12, 14:23 - Anomaly detected
    Note over U: Mar 12, 14:30 - IR initiated

That timeline is incredibly precise --- down to the minute. Logs might have gaps, but if you captured the packets, you have ground truth. Packets do not lie. An attacker can delete logs from a compromised server, but they cannot retroactively delete packets that were already captured by a network tap or SPAN port they do not control. That is why network forensics is so powerful for incident response --- it provides an independent, tamper-resistant record of what actually happened on the wire.


Evidence Preservation and Chain of Custody

When network captures may be used as legal evidence --- in criminal prosecution, civil litigation, regulatory proceedings, or even internal HR investigations --- proper handling is critical.

flowchart TD
    A["1. CAPTURE<br/>Record start/end time<br/>Document capture point<br/>Document command used<br/>Record who initiated"] --> B["2. HASH IMMEDIATELY<br/>SHA-256 hash of pcap file<br/>Record hash in evidence log<br/>Proves file not modified"]
    B --> C["3. STORE SECURELY<br/>Copy to encrypted evidence storage<br/>Set file permissions read-only<br/>Create working copy for analysis<br/>Never modify the original"]
    C --> D["4. DOCUMENT ACCESS<br/>Log every access to evidence<br/>Record who, when, why<br/>Document tools and versions used<br/>Keep analysis notes with timestamps"]
    D --> E["5. TRANSFER PROTOCOL<br/>Document sender and receiver<br/>Record date, time, method<br/>Verify hash matches after transfer<br/>Both parties sign transfer log"]

    style A fill:#3498db,color:#fff
    style B fill:#e74c3c,color:#fff
    style C fill:#e67e22,color:#fff
# Immediately after capture: hash the file
$ sha256sum /evidence/capture_20260312.pcap | tee /evidence/capture_20260312.sha256
a1b2c3d4e5f6...  /evidence/capture_20260312.pcap

# Make the original read-only
$ chmod 444 /evidence/capture_20260312.pcap
$ chattr +i /evidence/capture_20260312.pcap  # immutable flag (Linux)

# Create a working copy for analysis
$ cp /evidence/capture_20260312.pcap /analysis/working_copy.pcap

# Before any analysis session, verify the original is intact
$ sha256sum -c /evidence/capture_20260312.sha256
/evidence/capture_20260312.pcap: OK
Common evidence handling mistakes that can invalidate forensic evidence:
- Analyzing the original capture file directly (always use a copy)
- Failing to hash the file immediately after capture
- Not documenting who had access to the evidence and when
- Running captures on the compromised system itself (attacker may have tampered with tcpdump)
- Overwriting evidence by continuing to capture to the same file
- Not accounting for timezone differences when correlating timestamps across systems
- Breaking the chain of custody by transferring files without documentation

Advanced: Encrypted Traffic Analysis

Even without decrypting traffic, you can extract valuable intelligence from encrypted connections:

TLS Certificate Analysis:

  • Self-signed certificates are common in malware C2 (legitimate sites use CA-issued certificates)
  • Recently issued certificates (especially from Let's Encrypt) at unusual domains
  • Certificate subject/issuer mismatches or unusual fields
  • Certificates with IP addresses instead of domain names
  • Very long or very short validity periods

Traffic Pattern Analysis:

  • Packet size distribution: C2 often has uniform sizes (beacons are templated)
  • Inter-arrival times: beaconing detection as discussed above
  • Session duration patterns: C2 sessions are often long-lived
  • Upload-to-download ratio: exfiltration = unusually high upload
  • Time-of-day patterns: C2 often active during off-hours
# Extract TLS certificates and check for self-signed
$ tshark -r capture.pcap \
    -Y "tls.handshake.type == 11" \
    -T fields -e ip.src -e ip.dst \
    -e x509ce.dNSName -e x509af.utcTime

# Look for TLS connections to IP addresses (no domain = suspicious)
$ tshark -r capture.pcap \
    -Y "tls.handshake.type == 1" \
    -T fields -e ip.dst -e tls.handshake.extensions_server_name | \
    awk '$2 == "" {print "NO SNI: " $1}'

Network Forensics Toolkit

Every incident responder should have these tools installed and tested before an incident:

CategoryToolPurpose
CapturetcpdumpCLI packet capture
CaptureWireshark/tsharkGUI/CLI packet analysis
CaptureArkime (Moloch)Full packet capture at scale
AnalysisZeek (Bro)Network security monitor, protocol analysis
AnalysisNetworkMinerNetwork forensic analyzer, file extraction
Analysisnfdump/SiLKNetFlow analysis
DNSdig, dnstop, passivednsDNS investigation tools
UtilityeditcapSplit/filter pcap files
UtilitymergecapMerge multiple pcap files
UtilitytcpreplayReplay captured traffic
UtilityngrepNetwork grep (search packet payloads)
TLSja3TLS fingerprinting
Build and test your forensics toolkit now, before you need it:

1. Install tcpdump, tshark, and ngrep on your incident response laptop
2. Capture 5 minutes of traffic on your home or lab network
3. Use tshark to extract all DNS queries from the capture
4. Use Wireshark to identify the top 10 conversations by volume
5. Follow one TCP stream and understand what application generated it
6. Hash the capture file and practice the evidence handling process
7. Download a sample pcap from malware-traffic-analysis.net and analyze it

Muscle memory matters during incidents. You do not want your first time using tshark to be during a real breach at 3 AM. Practice in calm conditions so the commands are automatic when the pressure is on.

What You've Learned

In this chapter, you explored the discipline of network forensics:

  • Forensic workflow: A structured process from trigger through evidence acquisition, triage, deep analysis, timeline reconstruction, and reporting. Jumping into tools without a plan wastes time and risks missing evidence.

  • Packet capture strategies: Full capture provides maximum forensic value but requires massive storage (~10 TB/day for 1 Gbps). NetFlow provides metadata at minimal cost (~10 GB/day). Use a tiered approach matching storage investment to network segment criticality.

  • tcpdump mastery: From basic captures to targeted forensic collection with rotation, filtering, and header-only modes. Know these commands before you need them --- they are your first response tool.

  • Wireshark analysis: Display filters, protocol hierarchy, conversation analysis, TCP stream following, and object export form the core analytical workflow. TLS metadata (SNI, JA3 fingerprints) reveals insights even when content is encrypted.

  • C2 detection: Beaconing detection through timing analysis, DNS tunneling detection through query length and entropy analysis, and DGA detection through NXDOMAIN rate analysis can reveal command-and-control channels even when traffic is encrypted.

  • Timeline reconstruction: Building attack timelines from packet captures provides millisecond-precision ground truth that correlates initial compromise, lateral movement, and data exfiltration into a complete narrative.

  • Evidence handling: Chain of custody procedures --- immediate hashing, read-only originals, working copies, access documentation, and transfer protocols --- ensure that forensic evidence is admissible and trustworthy.

  • NetFlow analysis: When full packet capture is not available (storage constraints, encryption), NetFlow/IPFIX metadata provides connection-level visibility: who talked to whom, when, how long, and how much data moved. Tools like nfdump and SiLK enable analysis at scale, and NetFlow data is often available from network infrastructure even when no dedicated capture was in place.

  • Encrypted traffic analysis: TLS 1.3 and widespread HTTPS adoption mean packet payloads are increasingly opaque. But metadata remains visible: JA3/JA3S fingerprints identify client and server TLS implementations regardless of IP or domain. Certificate details (subject, issuer, validity period, SAN entries) reveal infrastructure. Self-signed certificates, certificates from unusual CAs, and certificates with very short validity periods are common indicators of malicious infrastructure.

Network forensics intersects with several legal frameworks that analysts must understand:

- **Wiretap laws** (18 USC 2511 in the US) generally require consent or authorization to intercept communications. Organizational acceptable use policies that notify users of monitoring provide the basis for lawful capture on corporate networks.
- **Stored communications** (18 USC 2701) governs access to stored electronic communications. Packet captures stored for forensic purposes fall under this statute.
- **GDPR Article 6** requires a lawful basis for processing personal data, including network traffic that may contain personal information. Incident response and legitimate security interests can provide a lawful basis, but data minimization principles apply.
- **Chain of custody documentation** is essential if forensic evidence may be used in criminal prosecution or civil litigation. Follow your organization's evidence handling procedures from the moment of capture.

Always coordinate with legal counsel before performing network forensic analysis, especially when the investigation may involve employees, cross-border data flows, or law enforcement referral.

Metadata is the analyst's best friend. An attacker can encrypt their payload, but they cannot hide the fact that a connection exists, when it happens, how long it lasts, how much data flows, or the TLS fingerprint of their tool. Those patterns are what give them away. Every connection leaves a trace. Your job is to learn to read those traces.