CHAPTER 05 40 MIN READ INTERMEDIATE

Packet Analysis with Wireshark

The last four chapters gave you the theory: how frames are built, how TCP negotiates and tears down a session, how DNS resolves a name, how TLS wraps a conversation in ciphertext. That theory is what makes a capture readable instead of a wall of hex. This chapter is where it becomes a hands-on skill. You will open an unfamiliar PCAP, apply the right filters, follow a conversation end to end, and actually pull answers out of it rather than just staring at packets scrolling past. By the end, you should be able to sit down with a capture you have never seen and know exactly where to start looking.

Wireshark display filters PCAP triage

The Wireshark Interface

Wireshark's main window is built around three panes, and understanding how they relate to each other is the first real skill in packet analysis.

The Three Panes

  • Packet list (top). One row per captured frame: number, timestamp, source, destination, protocol, length, and a summary column that Wireshark generates from the highest-layer protocol it recognizes. This is where you scan for patterns, sort by column, and click into anything that looks interesting.
  • Packet detail (middle). Shows the selected packet broken into its protocol layers as a collapsible tree: Frame, Ethernet, IP, TCP or UDP, and then whatever application protocol sits on top. Expanding each layer reveals field values, flags, and options that never appear in the packet list at all, like TCP window size or a specific HTTP header.
  • Packet bytes (bottom). Shows the raw hex and ASCII for the packet, synchronized with whatever you have selected in the detail pane above it. Useful for confirming exactly how a value is encoded on the wire, and for spotting cleartext strings that Wireshark's dissectors did not surface as a named field, such as a credential embedded in a custom application protocol.

Capture Filter vs Display Filter

The distinction that trips up almost every beginner is capture filter versus display filter. The confusion is understandable, since both narrow down packets and both use a text box near the top of the window.

A capture filter is applied before any packet is captured, using Berkeley Packet Filter (BPF) syntax, the same syntax tcpdump uses: host 10.0.0.5, port 443, tcp and port 80. Anything that does not match a capture filter is discarded at the network interface and never written to the capture file at all, which means you cannot get it back later no matter what display filter you write.

A display filter, by contrast, is applied after capture, to packets already sitting in memory or in a saved PCAP file. It uses Wireshark's own filter language, which looks similar to BPF but is not the same syntax and is far more expressive, since it can reference any field that any dissector has parsed, not just the handful of fields BPF understands.

In practice, when you are handed a PCAP someone else already captured, you are always working with display filters, because the capture already happened and there is nothing left to discard. Beginners who type BPF syntax like port 443 into the display filter bar are often surprised when Wireshark rejects it or interprets it unexpectedly, since the display filter equivalent is tcp.port == 443.

Note: If you are capturing live traffic yourself, using a capture filter to discard obviously irrelevant traffic (a busy backup job, unrelated broadcast noise) keeps the capture file small and the analysis machine responsive. But when in doubt, capture broadly and filter on display instead. A capture filter mistake is unrecoverable; a display filter mistake just needs to be rewritten.

Display Filters That Matter

A small set of display filters covers the overwhelming majority of real analyst work, and learning them fluently is worth more than memorizing the full filter grammar.

Host and Port Filters

The most basic is an address filter: ip.addr == 10.0.0.5 shows every packet where that address appears as either source or destination, which is almost always what you want when following one host's activity. Narrow it further with a port filter, tcp.port == 443, to isolate one conversation type, or combine both to pin down a specific host-to-service relationship.

Application-Layer Filters

These let you skip straight to protocol events instead of scrolling through every packet in a stream. http.request shows only HTTP request lines, far more useful than wading through TCP ACKs to find the handful of packets that actually carry a GET or POST.

dns.qry.name contains "evil" searches DNS query names for a substring, useful for spotting a suspicious domain fragment across an entire capture without knowing the exact FQDN in advance. tls.handshake.type == 1 isolates Client Hello messages, where you would look for SNI values before the rest of the session is encrypted.

Flag-Based Filters

These find specific TCP behaviors rather than specific hosts or ports. tcp.flags.syn==1 and tcp.flags.ack==0 isolates SYN packets with no ACK set, meaning connection attempts rather than responses, exactly what a port scan looks like: one source sending SYNs to many ports or many hosts with few or no completed handshakes.

tcp.flags.reset==1 finds resets, useful when you suspect a firewall or an overwhelmed service is tearing down connections abnormally often.

Combining Filters and Discovering New Ones

Filters chain with and, or, and parentheses the same way you would expect from boolean logic in any language. Getting comfortable combining them is what turns Wireshark from a packet viewer into an investigation tool.

ip.addr==10.0.0.5 and tcp.port==443 narrows to one host's HTTPS traffic. (ip.src==10.0.0.5 or ip.src==10.0.0.6) and tcp.flags.syn==1 isolates connection attempts from either of two suspect hosts. Negation uses ! or not, so !(arp or icmp) hides the broadcast chatter that clutters most captures and is rarely relevant to an investigation.

Wireshark's filter bar also autocompletes and color-codes as you type: green means valid syntax, red means it will not parse. Right-clicking any field in the packet detail pane and choosing "Apply as Filter" or "Prepare as Filter" is often faster than typing from memory, and it is a good way to learn the underlying field names for protocols you do not use every day.

FilterWhat It Finds
ip.addr==x.x.x.xAll traffic to or from a specific host
tcp.port==xTraffic on a specific TCP port, either direction
http.requestHTTP request lines only, skips responses and ACKs
dns.qry.name contains "x"DNS queries containing a substring in the name
tls.handshake.type==1Client Hello messages, where SNI values live
tcp.flags.syn==1 and tcp.flags.ack==0Connection attempts, a signature of port scanning
tcp.flags.reset==1Resets, a sign of abnormal connection teardown
tcp.analysis.retransmissionPackets Wireshark identified as retransmissions
!(arp or icmp)Hides broadcast/control-plane chatter

Following a TCP Stream

Right-clicking any TCP packet and choosing Follow > TCP Stream is one of the highest-value moves in Wireshark, and it is easy to overlook when you are focused on filtering the packet list. Instead of showing individual segments, it reassembles the entire conversation, both directions, in the order the application layer actually sent and received the data, stripping away the TCP mechanics of sequence numbers, ACKs, and segmentation that obscure what was actually said.

What It Shows

The result is presented as a single scrollable transcript, conventionally colored red for one direction and blue for the other, so you can read a request and its matching response as continuous text rather than reconstructing it yourself from a dozen scattered packets. For an HTTP exchange, this means the full request line, headers, and body, followed immediately by the full response, headers, and body, exactly as an application would have assembled it.

Wireshark automatically applies a display filter for that specific stream when you close the window, so the packet list narrows to just the packets in that conversation.

Why It's Fast

This is often the fastest way to understand what actually happened in an exchange, faster than reading packet by packet, because most analysis questions are really questions about content, not about individual segments. Follow TCP Stream answers questions like these in seconds, where manually clicking through twenty packets and reassembling payload bytes in your head would take much longer and invite mistakes:

  • Did the client send credentials in the clear?
  • What exact URL was requested?
  • What did the server actually return: an error page, a redirect, a file?

Where It Works, and Where It Breaks

The technique works on any cleartext TCP protocol, not just HTTP. FTP control channels, Telnet sessions, unencrypted SMTP, and plenty of legacy or misconfigured application protocols all read cleanly as a follow stream transcript.

For UDP-based protocols there is an equivalent Follow > UDP Stream, and Wireshark also offers Follow > TLS Stream, which will show decrypted content only if you have supplied the session keys or a private key, since TLS is specifically designed to prevent a passive observer from reading the stream without them.

One caveat worth internalizing early: stream reassembly depends on Wireshark seeing the full conversation. A capture that starts mid-session, drops packets due to capture loss, or only captured one direction of an asymmetric routing path will produce a partial or garbled follow stream. When the reconstructed text looks broken or out of order, check Statistics > Conversations for that stream to confirm you actually have both directions and no obvious gaps before concluding the application behaved strangely.

Spotting Anomalies in a Conversation

Recognizing normal traffic by sight is what makes abnormal traffic jump out, and that pattern recognition is built through repetition. There are still specific signals worth training yourself to notice deliberately.

Five Signals Worth Training Yourself to Notice

  • Excessive retransmissions. Wireshark marks them automatically in black with red text, and its tcp.analysis.retransmission filter will surface every one in a capture. A handful on a long-haul or wireless link is normal network behavior, but a dense cluster concentrated on one host or one service usually points to packet loss, an overloaded server, or a middlebox interfering with the connection.
  • Unexpected resets. A TCP RST is a normal way to end a connection when there is no listener on a port or when an application decides to abort abruptly. But a pattern of many RSTs immediately after SYN-ACK, especially spread across many destination ports from one source, is a classic signature of a host being scanned. RSTs appearing mid-conversation on connections that were previously healthy can indicate a firewall or IPS intervening, or an application crashing under load.
  • Traffic on unusual ports. A service that should only ever speak on its well-known port suddenly showing up on a high, ephemeral-looking port, or a host making outbound connections to port 4444, 8080, or another commonly abused port with no legitimate business reason, warrants a closer look at the actual payload rather than trusting the port number. Attackers deliberately choose ports to blend in, and Wireshark's protocol dissectors will still correctly identify many protocols regardless of the port they run on, which is a useful cross-check.
  • Cleartext credentials in the wrong protocol. A plaintext username and password on an FTP or Telnet stream is unsurprising, since those protocols were never designed with confidentiality. Seeing the same thing inside a protocol that is supposed to be encrypted, such as HTTP Basic Auth over plain port 80 where HTTPS should have been enforced, or credentials inside an HTTP POST body without TLS, is a real finding worth escalating immediately, not just a curiosity.
  • Unusually large or frequent DNS queries. This signal is easy to miss because DNS traffic is so voluminous it becomes background noise. A single host issuing hundreds of DNS queries per minute, queries for long or high-entropy subdomain labels, or DNS responses far larger than a typical A or AAAA record can indicate DNS tunneling, a DGA-based malware family cycling through candidate domains, or data exfiltration encoded into query names. Statistics > DNS or a targeted dns filter combined with sorting by query name length is usually enough to surface this pattern quickly.
Warning: None of these signals is conclusive on its own. Retransmissions can mean bad Wi-Fi, not an attack. Unusual ports can mean a misconfigured but legitimate service. Treat each anomaly as a lead that earns further investigation, not as a verdict, and corroborate with other evidence, such as endpoint logs or threat intel, before drawing a conclusion.

A Repeatable PCAP Triage Workflow

Opening an unfamiliar capture and scrolling through the packet list from the top is the least efficient way to start, and it is exactly what beginners tend to do. A repeatable triage workflow gets you from an unknown file to a working hypothesis in a fraction of the time, and it starts at the statistics menu rather than the packet list.

  1. Check Statistics > Protocol Hierarchy first. It breaks down every protocol present in the capture as a percentage of total packets and bytes, nested by layer, so you immediately see the shape of the traffic: is this mostly HTTP, mostly TLS, a lot of DNS relative to its size, any protocols present that seem out of place for the environment the capture came from. A capture that is supposedly internal LAN traffic but shows a meaningful percentage of an unfamiliar or unexpected protocol is worth investigating before anything else.
  2. Check Statistics > Conversations and Endpoints next. Conversations gives you a sortable table of every unique communication pairing, by IP, TCP, or UDP, with packet counts, byte counts, and duration for each. Sorting by bytes or packets descending surfaces your top talkers immediately: the handful of conversations that dominate the capture. Endpoints gives the same idea from a single-host perspective rather than a pairwise one, useful for quickly answering "which hosts are even present in this capture" before you start filtering on any of them specifically.
  3. Drill into anomalies with targeted display filters. With top talkers and an overall protocol shape in hand, drill into anything that looked anomalous in either view. If Protocol Hierarchy showed unexpected DNS volume, filter on dns and sort by query name. If Conversations showed one host dominating byte count, filter to that host with ip.addr== and check what protocol is carrying that volume. If a top talker pairing looks like a suspicious scan pattern, apply the SYN-without-ACK filter scoped to that host and count how many distinct destination ports it touched.

This sequence, overview first, then top talkers, then targeted drill-down, works because it moves from the broadest possible signal to the narrowest as fast as possible, instead of guessing where to look first. It also produces a natural audit trail: you can document exactly which statistics view surfaced the anomaly and which filter confirmed it, which matters when the triage needs to be written up or handed off.

Tip: Save the display filters that led you to a finding as filter buttons (the plus icon at the right of the filter bar) before you move on. Re-running the same triage sequence on the next capture becomes much faster once your most useful filters are one click away instead of retyped from memory.

Wireshark vs tshark vs tcpdump vs Zeek

All four tools touch packet data, but each earns its place at a different stage of an investigation, from live triage to unattended automation to long-term visibility.

Wireshark, tshark, and tcpdump

Wireshark's GUI is the right tool when you need to explore, when you do not yet know what you are looking for and need to pivot between statistics views, filters, and stream reconstruction interactively. That exploratory strength is also its limitation: it does not scale to automation, to processing hundreds of captures unattended, or to running the same check across a fleet of collected PCAPs without a human clicking through each one.

tshark is Wireshark's command-line sibling, built on the exact same dissection engine, which means any display filter you have already learned in the GUI works identically in tshark. It is the tool to reach for once you know what you are looking for and need to script it: extracting every DNS query name from a directory of captures, running the same anomaly filter against files pulled from an automated collection pipeline, or feeding filtered fields into another tool as CSV or JSON. What tshark trades away is interactive exploration; you are typically writing the filter and field extraction up front rather than discovering it by clicking around.

tcpdump sits a level below both. It is a capture tool first, a display tool second, using the same BPF capture filter syntax discussed earlier in this chapter, and it is available by default on nearly every Linux and Unix system without installing anything extra. Its own output formatting is far less rich than Wireshark's, and in practice a common pattern is capturing with tcpdump on a remote or resource-constrained host and then transferring the resulting PCAP file to a workstation for full analysis in Wireshark.

From Packets to Logs: The Zeek Preview

Wireshark, tshark, and tcpdump share one fundamental characteristic: they work with full packet captures, meaning every byte of every packet, which gives maximum fidelity but also means storage and processing cost scale directly with traffic volume.

Chapter 7 introduces Zeek, which takes a genuinely different approach: instead of storing raw packets, it observes traffic in real time and generates structured, protocol-aware log files, a connection log, an HTTP log, a DNS log, and more, each just the fields that matter for that protocol. That shift, from packets to logs, is what makes Zeek practical at a scale where retaining full PCAP for everything is not feasible. The two approaches are complementary rather than competing: Zeek logs tell you where to look, and a packet capture of that specific window is what you would open in Wireshark to confirm it.

ToolBest ForTrade-off
Wireshark (GUI)Interactive exploration when you don't yet know what you're looking forDoes not scale to unattended automation
tsharkScripting a known filter across many capturesNo interactive discovery, filters written up front
tcpdumpFast, lightweight capture on any Linux/Unix boxMinimal display formatting, usually paired with Wireshark for analysis
ZeekStructured, protocol-aware logs at scale (Chapter 7)Not full packet fidelity; a lead, not a replacement for PCAP

Key Takeaways

  • Wireshark's three panes, packet list, packet detail, and packet bytes, work together: scan the list, confirm in the detail tree, verify raw encoding in the bytes pane.
  • Capture filters (BPF syntax) discard packets before they are ever written to disk and cannot be undone. Display filters (Wireshark's own syntax) narrow an already-captured file and can always be rewritten.
  • A small core of display filters, address, port, protocol event, and TCP flag filters, chained with and/or, covers most real analyst work.
  • Follow TCP Stream reconstructs a full two-way conversation as readable text and is often the fastest way to understand what actually happened in an exchange.
  • Retransmissions, unexpected resets, traffic on unusual ports, cleartext credentials in the wrong protocol, and abnormal DNS query volume are the anomaly signals worth training yourself to spot.
  • A repeatable triage workflow, Protocol Hierarchy for overview, Conversations and Endpoints for top talkers, then targeted filters to drill in, beats scrolling the packet list from the top.

Knowledge Check

Click an answer to reveal the explanation.

You want to capture only traffic to or from 10.0.0.5 on a live interface, and you type ip.addr == 10.0.0.5 into the capture filter field before starting the capture. Wireshark rejects it. Why?

Capture filters use Berkeley Packet Filter (BPF) syntax, the same syntax as tcpdump, where the equivalent expression is host 10.0.0.5. The field==value style with double equals and dotted field names is display filter syntax, applied after capture, and is not valid in the capture filter field. This mismatch is one of the most common beginner mistakes.

You are handed a PCAP and, using Statistics > Conversations, notice one internal host sent SYN packets with no ACK to over 400 distinct destination ports on the same external IP within a few seconds. What does this most likely indicate, and what filter would confirm it?

Many SYNs with no completed handshake against a large number of distinct ports on one destination in a short window is the textbook signature of a port scan. Filtering on tcp.flags.syn==1 and tcp.flags.ack==0 scoped to that host pairing isolates exactly these connection attempts and lets you count the distinct ports touched to confirm the pattern.

You need to check DNS query patterns across 300 PCAP files collected overnight from multiple sensors, looking for any host issuing an abnormal volume of queries. What is the most practical approach?

tshark shares Wireshark's dissection engine and display filter syntax, so a DNS query filter already validated in the GUI can be scripted against 300 files without a human opening each one. Opening each file manually does not scale. tcpdump cannot re-capture traffic that already happened. Zeek is a legitimate long-term visibility strategy but does not help with PCAP files you already have in hand right now.