Skip to content
Notes
Field notes · Reference

Wireshark for the SOC

A working reference for reading capture files the way an analyst does — orient, filter down, read the protocol, pivot, reconstruct.

Updated 2026-08-31Wireshark 4.xBuilt from a real capture session
From the session

This came out of a hands-on first-capture session — a few thousand packets of ordinary browsing, and not one cleartext HTTP request: all TLS and QUIC. The loop in practice: isolate a lookup with dns.qry.name == "example.com", read the query/response pair, then pivot on the answer with ip.addr == <resolved IP>. Everything below is that same loop, generalised.

01Orientation

What Wireshark is

If you've never opened it — what the tool actually does, what it's for, and where it helps or gets in the way.

Wireshark is a free, open-source network protocol analyser — a “packet sniffer.” It records the individual frames going in and out of a network interface (or reads a saved capture file) and decodes every one from raw bytes into readable fields, across roughly 3,000 protocols.

It is the de facto standard for looking at network traffic. The package is really three tools: the Wireshark GUI, the tshark command-line version, and dumpcap, the small program that actually does the capturing. It captures through Npcap on Windows and libpcap on Linux and macOS.

What you can do with it

  • Capture live traffic, or open a .pcap / .pcapng someone hands you and work it offline.
  • Inspect any layer of any packet — Ethernet, IP, TCP/UDP, TLS, HTTP, DNS, SMB, Kerberos, and thousands more.
  • Cut a capture of millions of packets down to the few that matter with the display-filter language.
  • Reassemble whole conversations (Follow Stream) and carve transferred files back out (Export Objects).
  • Summarise a file at a glance — protocol mix, top talkers, throughput over time, TCP problems.
  • Decrypt TLS or WPA/WPA2 when you legitimately hold the keys.
  • Script all of the above for automation and CI with tshark.

Typically used for: Incident response and network forensics, malware traffic analysis, chasing latency / packet loss / failed handshakes, confirming what an application actually sends on the wire, learning how a protocol really works, and CTF challenges.

Strengths

  • Free, open-source, cross-platform, and decodes more protocols than any commercial tool.
  • Unmatched depth — you see the actual bytes, not a vendor's summary of them.
  • Huge ecosystem: documentation, sample captures, courses, and a community that has already analysed almost anything you'll meet.
  • The skills transfer — the filter language and the concepts carry to tcpdump, Zeek, Suricata, and every cloud packet-capture feature.
  • Scriptable and repeatable through tshark.

Limits & cautions

  • It is not monitoring. Wireshark only sees what happens while you're watching — you have to already be capturing when the event occurs. Continuous coverage needs an IDS, Zeek, or a full-packet-capture appliance.
  • It doesn't scale to fast links. On a busy network it drops packets, and the GUI struggles with multi-gigabyte files. Capture with dumpcap or tcpdump into a ring buffer, then slice the file down before opening it.
  • It only sees traffic that reaches your capture point. For anything beyond your own machine you need a SPAN / mirror port or a network tap — it can't see other VLANs or switches.
  • Encrypted payloads stay opaque without the keys, and most of the modern web is TLS or QUIC.
  • Easy to misread — TCP “errors” in a capture are often artifacts of the capture itself, not the network.
  • Its protocol dissectors have a long history of security bugs. Keep it updated, don't run it as root/admin, and open untrusted captures on an isolated machine.
  • Capturing traffic can breach policy or law. Only capture on networks you're authorised to.
02Do this

Step by step: capture to finding

Every click from launching Wireshark to a saved, hand-off-ready finding. A–C get a capture open; D–I are the analysis. The rest of this page is the reference behind each step.

A

Capture your own traffic

Handed a .pcap file instead? Skip to C.

  1. Open Wireshark — Start menu, type Wireshark, Enter. If it can't see any interfaces, close it and reopen as Administrator.
  2. The welcome screen lists your network interfaces, each with a small live activity graph. The one that's moving is normally Wi-Fi or Ethernet.
  3. Optional — record only what you need: click the …using this filter box and type a capture filter such as host 10.0.0.42 or port 443. Leave it blank to capture everything, which is usually the safer choice in an incident.
  4. Double-click the interface. Capture starts at once — packets scroll in the top pane and the toolbar shows a red square.
  5. Reproduce the activity you're investigating, or let it run for the time window you need.
  6. Stop the capture: click the red square in the toolbar, or press Ctrl+E.
B

Save it before you touch anything

  1. File → Save As (Ctrl+Shift+S).
  2. Choose a folder, name it something you'll recognise later — case1234-web.pcapng — leave the type as pcapng, click Save.
  3. Always work on a copy. File → Save As once more to make a working duplicate, so the original stays untouched while you cut packets out of the copy.
C

Open a capture you were given

  1. File → Open (Ctrl+O) and pick the .pcap / .pcapng — or drag the file straight onto the Wireshark window.
  2. Set the clock to UTC so timestamps line up with every other log: View → Time Display Format → UTC Date and Time of Day.
  3. View → Time Display Format → Seconds Since Previous Displayed Packet is the other useful mode — it shows gaps between packets, which is how you eyeball a beacon interval.
D

Orient — read the whole file before you filter

  1. Statistics → Capture File Properties: note the time span and total packet count so you know the scale of what you're looking at.
  2. Statistics → Protocol Hierarchy: scan the protocol mix. Anything you didn't expect — IRC, TFTP, SMB heading to the internet, raw TCP on an odd port — is your first lead.
  3. Statistics → Conversations, then click the Bytes column header to sort. This is "who talked to whom, and how much." Note the largest flows and any external IP you don't recognise.
  4. Right-click the row for an interesting flow → Apply as Filter → Selected → A↔B to pull just that conversation into the main window.
  5. Statistics → Endpoints → Map plots the external IPs on a world map — quick sanity check on where traffic is going.
E

Filter down to the question

  1. Click the display-filter bar, or press Ctrl+/ to jump to it.
  2. Type an expression and press Enter. The bar turns green when the syntax is valid, red when it isn't, yellow when it's legal but probably not what you meant.
  3. Build a filter without typing it: click a value in the middle (details) pane, then right-click → Apply as Filter → Selected. Use …and Selected / …or Selected from the same menu to stack conditions.
  4. Turn a field into a permanent column: right-click it in the details pane → Apply as Column. Do this with the TLS Server Name so every HTTPS row shows its destination.
  5. Clear the filter with the X at the right of the bar. Nothing was deleted — every packet comes straight back.
F

Read a single packet

  1. Click a row in the top (packet list) pane. The other two panes follow it.
  2. Middle pane is the decode, outer layer to inner: Frame → Ethernet → IP → TCP/UDP → the application protocol. Click the > to expand one layer.
  3. Open an entire layer at once: right-click it → Expand Subtrees.
  4. Bottom pane is the raw bytes. Click any field in the middle pane and its bytes highlight below — that's how you confirm a value is genuinely in the packet and not inferred.
  5. Ctrl+. and Ctrl+, step to the next / previous packet in the same conversation.
G

Reconstruct the whole conversation

  1. Right-click any packet in the flow → Follow → TCP Stream (or HTTP / TLS / UDP Stream).
  2. The window shows the exchange in order — one colour for client→server, another for server→client. A TLS stream shows the handshake in clear, then ciphertext.
  3. Change Show data as to Hex Dump for binary protocols, or Raw to save the payload out to a file.
  4. The dropdown at the bottom-left steps through every stream of that type in the capture.
  5. Close the window — the filter tcp.stream eq <n> stays applied, so you're now looking at just that one conversation. Clear the bar to zoom back out.
H

Carve out transferred files

  1. File → Export Objects → HTTP (also SMB, IMF for email, TFTP, DICOM).
  2. The list is every file seen in that protocol, with hostname, type and size. Click a row to jump to the packets that carried it.
  3. Select one and click Save, or Save All to a folder. Treat anything you pull as hostile — scan it, don't open it.
I

Mark it up and hand off the finding

  1. Click each packet that matters and press Ctrl+M — a black bar marks it.
  2. Right-click → Packet Comment, write what the packet shows, OK. The note is saved inside the pcapng and travels with the file.
  3. File → Export Specified Packets → choose Marked packets only → save a small evidence file (case1234-evidence.pcapng).
  4. For each marked packet, write down: the frame number, the 5-tuple (src IP:port → dst IP:port, protocol), and the UTC timestamp. A finding that doesn't point at specific packets can't be reproduced.
03Method

The analysis loop

The same six moves every time, whether it's your own capture or a PCAP handed to you from an incident. Don't start filtering until you've oriented.

1

Orient before you filter

Get the shape of the whole capture first.

  • Statistics → Protocol Hierarchy — what protocols, in what proportion. Anything unexpected (IRC, TFTP, raw TCP on odd ports) stands out here.
  • Statistics → Conversations, sort by Bytes — who is talking to whom, and which flows are large.
  • Statistics → Capture File Properties — time span, dropped packets, capture comments.
  • Note the internal hosts you'll be reasoning about.
2

Filter to the question

Start broad, then narrow with fields.

  • Type a protocol name alone as a shortcut: dns, http, tls.
  • Narrow with fields: dns.qry.name == "acme-updates.com", ip.addr == 10.0.0.42.
  • Display filters never delete anything — clear the bar and every packet returns.
  • Bar colour: green = valid, red = broken syntax, yellow = legal but probably not what you meant.
3

Read the protocol

Expand the relevant layer in the details pane and read the fields that carry meaning.

  • DNS — query name, record type, reply code, answers.
  • HTTP — method, Host, URI, User-Agent, status code.
  • TLS — Client Hello → server_name (SNI); certificate CN / SAN.
  • TCP — flags, the handshake, resets, retransmissions.
4

Pivot

Every fact points at the next filter.

  • DNS gave you an IP → ip.addr == <that IP>.
  • A suspicious host → what else did it connect to?
  • A port → who else is using it?
  • A JA3 / JA4 hash → every other client with the same fingerprint.
  • Chain: domain → IP → conversation → that IP's other flows.
5

Reconstruct

Assemble whole conversations, not loose packets.

  • Right-click → Follow → TCP / HTTP / TLS Stream — the exchange in order, colour-coded by direction.
  • File → Export Objects → HTTP / SMB / IMF — carve out transferred files.
  • Statistics → HTTP → Requests — every URL that was asked for.
6

Write it down

A finding has to point at specific packets.

  • Ctrl+M to mark packets of interest.
  • Right-click → Packet Comment to annotate inside the file.
  • Record frame numbers, the 5-tuple, and timestamps — switch to UTC via View → Time Display Format.
  • File → Export Specified Packets to hand off just the relevant slice.
04Grammar

Display-filter syntax

One shape: field.name operator value. Typing a protocol name alone (dns, tls) is a shortcut for “any packet with this layer”.

Comparison

ip.addr == 10.0.0.5      # eq
tcp.port != 443          # ne
frame.len >= 1400        # ge  (gt lt le)
http.response.code > 399

Careful with ip.addr != x — it means "has an address field that isn't x", true for almost every packet. To exclude a host use !(ip.addr == x).

Combine

dns and ip.src == 10.0.0.5
http.request or tls.handshake.type == 1
not arp
(tcp.port == 80 or tcp.port == 443)
   and ip.dst == 8.8.8.8

and or not — or && || ! — same thing. Parenthesise freely.

Substring & sets

http.host contains "update"
dns.qry.name matches "[a-z0-9]{20,}"   # regex
frame contains "PASS "                 # raw bytes
tcp.port in {80 443 8080 8443}

contains is a literal byte match; matches is PCRE and case-insensitive by default.

05Reference

Filters by protocol

The handful worth memorising per protocol. Everything else you can build straight from the details pane.

FilterShows
DNS
dns.flags.response == 0Queries only — what the host wanted to resolve
dns.flags.rcode == 3NXDOMAIN — the name doesn't exist. Malware hitting dead C2, DGA misses.
dns.qry.name contains "domain"Every lookup touching a domain string
dns.qry.type == 16TXT queries — a common carrier for DNS tunnelling
dns.time > 1Slow responses (> 1 s) — resolver problems
HTTP
http.requestRequests only — one row per URL fetched
http.request.method == "POST"Uploads / form posts — watch for exfil
http.request.uri matches "\.(exe|dll|ps1|scr|zip)$"Executable / archive downloads
http.user_agent contains "curl"Non-browser clients (curl, python-requests, PowerShell)
http.response.code >= 400Errors — failed fetches, probing
TLS / SSL
tls.handshake.type == 1Client Hello — one per new HTTPS connection; carries the SNI
tls.handshake.extensions_server_name == "host"Connections to a specific hostname (pre-ECH)
tls.handshake.type == 11Certificate — read issuer, CN, SAN, validity
tls.record.version == 0x0301Legacy TLS 1.0 negotiated — worth a look
tls.alert_messageHandshake failures / aborted sessions
TCP
tcp.flags.syn == 1 && tcp.flags.ack == 0Connection attempts — the basis of scan detection
tcp.flags.reset == 1RST — refused / torn-down connections
tcp.analysis.retransmissionRetransmits — loss, or a saturated / failing path
tcp.analysis.flagsEverything Wireshark thinks is wrong with TCP here
tcp.stream == 7One TCP conversation by its stream index
UDP / ICMP / ARP
udp.length > 512Oversized UDP — DNS abuse, tunnelling, amplification
icmp.type == 8 || icmp.type == 0Ping echo request / reply — sweeps, keep-alives, tunnels
icmp && data.len > 64ICMP with a fat payload — possible ICMP tunnel
arp.duplicate-address-detectedTwo MACs claiming one IP — ARP spoofing / poisoning
arp.opcode == 1Who-has requests — a storm from one host = LAN sweep
IP / frame / generic
ip.addr == 10.0.0.0/8Anything touching a subnet (CIDR works)
ip.src == 10.0.0.5 && !(ip.dst == 10.0.0.0/8)One internal host talking out to the internet
frame contains "password"A byte string anywhere in the packet (cleartext only)
frame.time >= "2026-08-31 14:00:00"Everything after a timestamp
!(arp || dns || icmpv6 || mdns)Mute the background chatter
06Task → filter

The analyst phrasebook

You know what you want to see in words. Here's how to say it to Wireshark.

I want to see…Filter / action
Everything to and from one hostip.addr == 10.0.0.42
Only what that host sent outbound to the internetip.src == 10.0.0.42 && !(ip.dst == 10.0.0.0/8 || ip.dst == 192.168.0.0/16)
Every website a machine visited (HTTPS)tls.handshake.type == 1 — then add tls.handshake.extensions_server_name as a column
Every DNS name a machine asked fordns.flags.response == 0 && ip.src == 10.0.0.42
Lookups that failed (dead domains)dns.flags.rcode == 3
Scans / connection attemptstcp.flags.syn == 1 && tcp.flags.ack == 0
Connections that got refusedtcp.flags.reset == 1
Cleartext credentials or keywordsframe contains "password" / ftp.request.command == "PASS" / http.authorization
Files pulled over HTTPhttp.request.uri matches "\.(exe|dll|ps1|bat|zip|rar|7z|scr)$" — then File → Export Objects → HTTP
Possible upload / exfilhttp.request.method == "POST" / Statistics → Conversations, sort Bytes A→B
One conversation start to finishRight-click a packet → Follow → TCP Stream (or tcp.stream eq N)
Traffic on unexpected portsStatistics → Conversations → TCP tab, sort by Port B, scan for oddities
Whether a host is beaconingStatistics → I/O Graph, one series filtered to ip.addr == <suspect>, look for even spacing
07Recognition

Spot the pattern

What common activity looks like in the packet list — the visual signature, a starter filter, and the next thing to check.

likely hostile triage / context needed
Port scan

One source, marching through ports

10.0.0.5 → 10.0.0.9  TCP  58xxx→22   [SYN]
10.0.0.5 → 10.0.0.9  TCP  58xxx→23   [SYN]
10.0.0.5 → 10.0.0.9  TCP  58xxx→25   [SYN]
10.0.0.9 → 10.0.0.5  TCP  25→58xxx   [RST, ACK]
Filter
tcp.flags.syn == 1 && tcp.flags.ack == 0

Next: Statistics → Conversations → is one pair spread across hundreds of ports in seconds?

Host sweep

One source, one port, many targets

10.0.0.5 → 10.0.0.11  TCP  →445  [SYN]
10.0.0.5 → 10.0.0.12  TCP  →445  [SYN]
10.0.0.5 → 10.0.0.13  TCP  →445  [SYN]
10.0.0.5 → 10.0.0.14  ARP  who has 10.0.0.14?
Filter
ip.src == 10.0.0.5 && tcp.flags.syn == 1

Next: Is this host normally a client? Sweeps from a workstation are not routine.

Brute force

Repeated short sessions to one service

10.0.0.8 → SRV  TCP  →3389  [SYN]
SRV → 10.0.0.8  TLS  Application Data
10.0.0.8 → SRV  TCP  →3389  [SYN]  (new port)
SRV → 10.0.0.8  TCP  [RST, ACK]
Filter
ip.dst == SRV && tcp.port == 3389

Next: Line it up against auth logs — count attempts vs. one success.

C2 beacon

Metronome traffic to one external IP

t+0s   10.0.0.42 → 203.0.113.9  TLS  ~400 B
t+60s  10.0.0.42 → 203.0.113.9  TLS  ~400 B
t+120s 10.0.0.42 → 203.0.113.9  TLS  ~400 B
(little else to that IP)
Filter
ip.addr == 203.0.113.9

Next: How old is the domain? Any SNI? JA3/JA4 of the client? Beacon + young domain + rare fingerprint = escalate.

Data exfil

Large, sustained, outbound

10.0.0.42 → 198.51.100.7  TLS  1460 B
10.0.0.42 → 198.51.100.7  TLS  1460 B
10.0.0.42 → 198.51.100.7  TLS  1460 B
198.51.100.7 → 10.0.0.42  TCP  [ACK] len 0
Filter
Conversations, sort "Bytes A→B" descending

Next: Is the destination known? Is the volume normal for this host at this hour?

DNS tunnelling

Long random names, one domain, high volume

q  k3f9a2....x7.tun.bad.com  TXT
q  m0p1q8....z2.tun.bad.com  TXT
q  a9c4e1....r5.tun.bad.com  NULL
(hundreds/min, little other traffic)
Filter
dns && dns.qry.name contains "bad.com"

Next: Statistics → DNS — query count and rate to that domain vs. everything else.

08Menus

The Statistics menu

Where you go before filtering, and where you confirm a hunch after. Most of these can push a filter back to the main window.

Statistics →Use it to…
Protocol HierarchyEvery protocol in the file and its share of bytes. First stop for "is anything weird in here".
ConversationsEvery pair of talkers with packet/byte totals and duration. Sort by bytes; right-click → Apply as Filter.
EndpointsPer-host totals. The Map button plots external IPs geographically.
I/O GraphThroughput over time, multiple filtered series. Beacon spacing, transfer spikes, gaps where a link died.
Expert InformationWireshark's own findings — retransmissions, resets, malformed packets — grouped by severity.
DNSQuery/response counts, response codes, query types, slowest responses.
HTTP → RequestsEvery URL requested, grouped by host. Fast way to see "what did this box fetch".
Capture File PropertiesTime span, packet/drop counts, capture interface and filter, file and packet comments.
09Speed

Right-click & Follow Stream

Most of the work is done from the right-click menu on a packet or a field — not by typing filters from scratch.

On a field (details pane)

  • Apply as Filter → SelectedReplace the bar with "= this value"
  • Prepare as FilterBuild the bar but don't run it yet — chain several, then Enter
  • Apply as ColumnPromote this field to a permanent column (do this with the TLS server_name)
  • Copy → Value / as FilterGrab the value, or a ready-made filter expression

On a packet (list)

  • Follow → TCP / HTTP / TLS StreamThe whole conversation reassembled, client vs server colour-coded
  • Conversation Filter → TCPJump to just this 5-tuple
  • Colorize ConversationPaint this flow so you can track it while scrolling everything
  • Packet CommentAnnotation saved inside the pcapng
10Reality

Encrypted vs cleartext

On a modern network almost everything is TLS or QUIC. Know exactly what still leaks — it's more than people assume, and it's where the investigation starts.

You can still see

  • DNS query names and answers (unless DoH / DoT is in use)
  • TLS SNI — the destination hostname in the Client Hello, unless Encrypted Client Hello (ECH) is negotiated
  • Server certificate — CN, SAN list, issuer, validity dates (TLS 1.2; inferable in 1.3)
  • TLS version and cipher suites offered and chosen
  • JA3 / JA4 client and server fingerprints — identify the software regardless of IP or port
  • Every IP, port, packet size, direction, and timestamp — enough for beacon and volume analysis
  • Cleartext HTTP if it happens at all — rare enough now to be notable by itself

You can’t see (without keys)

  • HTTP method, path, headers, cookies, body — anything inside HTTPS
  • Request and response contents — all of it is Application Data
  • Credentials, tokens, uploaded / downloaded file contents over TLS
  • Anything inside QUIC without the keys (and QUIC hides more of the handshake than TLS 1.2 did)

To decrypt your own traffic: set SSLKEYLOGFILE before launching the browser, then Preferences → Protocols → TLS → (Pre)-Master-Secret log filename. Only works for sessions whose keys you logged — not after the fact, not someone else's.

11Before capture

Capture filters (BPF)

A different, simpler grammar — and permanent: a capture filter decides what gets written to disk. Default to capturing everything and filtering the display.

The ones worth knowing

host 10.0.0.5
net 10.0.0.0/24
port 443
tcp port 80
src host 10.0.0.5 and dst port 53
not arp and not broadcast
host 10.0.0.5 and not port 22    # drop your own SSH

Watch out

  • Syntax is not the display-filter syntax. host x, not ip.addr == x. No .field names.
  • Primitives are host, net, port, src, dst, tcp, udp — combined with and / or / not.
  • Set it on the welcome screen (bar under the interface list) or Capture → Options.
  • In an incident you usually want no capture filter — you can't filter for evidence you didn't know you'd need.
12Hands

Keyboard & navigation

Move

Ctrl + /
Jump to the display-filter bar
Ctrl + G
Go to packet number
Ctrl + .
Next packet in this conversation
Ctrl + ,
Previous packet in this conversation
Alt + → / ←
Forward / back through selection history
Ctrl + F
Find (string, hex, or filter)

Read & mark

→ / ←
Expand / collapse a layer in the details pane
*
Expand all subtrees of the selected layer
Ctrl + M
Mark / unmark this packet
Ctrl + Shift + N
Next marked packet
Ctrl + T
Set / unset time reference (times count from here)

Right-click any column header to add, remove, reorder or resize columns. A good analyst layout: No., Time (UTC), Source, Destination, Protocol, Length, Info — plus server_name when working TLS.

13Keep going

Practice & references

Cheat sheets get you moving; reps make you fast. The practice sites give you real malicious PCAPs with questions and answer keys.

Reference

Practise on real traffic

Go deeper

  • Practical Packet Analysis — Chris SandersNo Starch Press. The standard first book.
  • Applied Network Security Monitoring — Sanders & SmithThe SOC-side framing.
  • ZeekPair with Wireshark for connection logs at scale — Wireshark for the packet, Zeek for the summary.
Wireshark for the SOC — filters target Wireshark 4.x. Found an error? tell me.