ctf.nitaimaarek.com Tracks Leaderboard Log in Sign up

Wireshark field guide

Two skills wearing one coat: deciding where to tap the wire, and writing filters that throw away the 99% you do not care about. Everything else is menus.

Your rig

Windows desktop · Wi-Fi (MT7922) · gateway 192.168.1.1 · LAN 192.168.1.0/24. Wireshark and Npcap are already installed.

01 · Where you tap decides what you can ever see

Wireshark is not a scanner. It is a tape recorder wired to one interface, and it shows you the frames that physically arrive there. Pick the wrong tap point and the packets you want were never in the room.

Your Wi-Fi card sits on a switched network. A switch is not a megaphone — it learns which MAC lives on which port and forwards each frame only there. So capturing on your desktop shows you:

Widening the tap

Roughly in order of how much pain they cost. All of this is for a network you own.

02 · Two filter languages, and everyone mixes them up

Capture filter · BPF

Set before you start, on the welcome screen under the interface list. Decides what reaches the disk at all.

host 192.168.1.42
port 53
tcp port 443
not port 22
src net 192.168.1.0/24

Destructive. What it drops is gone forever, and it cannot be changed without restarting the capture.

Display filter · Wireshark

Set after, in the big bar at the top. Decides what you are currently looking at.

ip.addr == 192.168.1.42
dns
tcp.port == 443
!(tcp.port == 22)
ip.src == 192.168.1.0/24

Non-destructive. Change it a hundred times; the capture underneath is untouched. This is the one you will live in.

Same idea spelled two ways: host x versus ip.addr == x. BPF is terse and positional; display filters are protocol.field == value, and every field you can see in the detail pane has a name you can filter on.

The rule: capture wide, filter narrow. Start with no capture filter at all. You cannot filter your way back to a packet you refused to record.

The filter bar colours itself as you type, and it means something: green valid, red syntax error, yellow valid but probably not what you meant — which almost always means you hit the != trap in §07.

03 · Reading the window

Top pane is the packet list. Protocol is the highest layer Wireshark managed to dissect, so a DNS packet says DNS, not UDP. Info is a human summary written by that dissector and it is genuinely worth reading — most of the time it answers your question without opening anything.

Middle pane is the detail tree: the same packet peeled layer by layer, Frame → Ethernet → IP → TCP → HTTP. Bottom pane is the raw bytes. Click a field in the tree and its bytes highlight — the fastest way to learn what a header physically is.

The trick that makes filters easy

Click any field in the detail tree and look at the bottom-left of the status bar. It prints that field's filter name — dns.qry.name, tcp.window_size, http.host. You never memorise a cheat sheet; you find the thing once by clicking and Wireshark tells you what to type. Better still, right-click the field → Apply as Filter → Selected and it writes the filter for you. …and not Selected subtracts noise instead.

The four menu items that do 80% of the work

04 · Display filters worth knowing

Addresses and hosts

ip.addr == 192.168.1.42        source or destination
ip.src == 192.168.1.42         one direction only (ip.dst for the other)
ip.addr == 192.168.1.0/24      whole subnet, CIDR works anywhere an address does
!(ip.addr == 192.168.1.1)      everything except the gateway — note the shape
eth.addr == 3c:22:fb:11:22:33  by MAC; survives DHCP handing out a new IP

Ports and protocols

tcp.port == 443                either side of the connection
udp.port == 53                 DNS by port, responses included
tcp.port in {80 443 8080}      set membership, nicer than chaining or
dns                            a bare protocol name filters to it
quic                           HTTP/3 over UDP 443 — where "the missing web traffic" went
!(arp or icmp or dns or mdns)  the standard noise cut
tcp.len > 0                    only data-carrying packets, hides the ack storm

DNS — who is being looked up

dns.qry.name contains "netflix"   best first move for "what does this device talk to"
dns.flags.response == 1           answers only (== 0 for questions)
dns.flags.rcode != 0              failed lookups, NXDOMAIN and friends
dns.time > 0.2                    slow resolutions, in seconds, set on the response

HTTP — plaintext only

http.request                      one row per request, the cleanest overview
http.request.method == "POST"     form submissions and API writes
http.response.code >= 400         errors only
http.host contains "api."         by Host header
http.time > 1                     responses that took over a second

TLS — encrypted, but not silent

tls.handshake.type == 1                      Client Hello, first packet of every session
tls.handshake.extensions_server_name         the SNI: the hostname, in cleartext
tls.alert_message                            handshake failures, cert rejections

TCP mechanics and things going wrong

tcp.flags.syn == 1 && tcp.flags.ack == 0   connection attempts, one row per new connection
tcp.flags.reset == 1                       RSTs — something refused or tore down
tcp.analysis.flags                         everything Wireshark thinks is wrong
tcp.analysis.retransmission                real packet loss, somewhere
tcp.analysis.zero_window                   a receiver saying "stop, I am full"
tcp.stream eq 5                            one conversation

Layer 2, and content search

arp                            who-has/is-at; shows every live device on the segment
dhcp                           address handouts (called bootp in Wireshark 2.x)
mdns                           Bonjour — devices announcing themselves by name
frame contains "password"      raw byte search, case-sensitive
frame matches "(?i)login"      same but regex; (?i) makes it case-insensitive
frame.time_delta > 1           a gap of over a second — finds stalls fast

Combine with and / or / not (or && / || / !, identical). Ctrl+ in the filter bar walks your history; the bookmark icon saves one you will want again.

05 · Decrypting your own HTTPS

Most of what you capture is encrypted and no tap point changes that. But a browser will hand you the session keys for its own connections.

# PowerShell — sets a persistent user env var
setx SSLKEYLOGFILE "C:\Users\Admin\sslkeys.log"

Fully quit Chrome or Firefox (check the tray) and reopen. In Wireshark: Edit → Preferences → Protocols → TLS → (Pre)-Master-Secret log filename → pick that file. Existing captures decrypt retroactively as long as the keys were logged while they were recorded. It covers apps that honour the variable — Chrome and Firefox do, most native Windows apps use schannel and do not. The same keys decrypt QUIC.

06 · Recipes

What is this device even talking to?

dns.flags.response == 0 or tls.handshake.type == 1

Then right-click the SNI field → Apply as Column and the packet list becomes a readable log of every hostname contacted.

Why is this page slow?

dns.time > 0.2        slow lookups
tcp.flags.syn == 1    then check the SYN → SYN/ACK gap
tcp.analysis.flags    loss, retransmits, zero windows

Set the time column to seconds-since-previous-displayed-packet first.

Is this device even on the network?

dhcp or arp

Discover with no Offer: it cannot reach the server. Offer with no Request: the client rejected it. ARP with no reply: nothing answers to that IP.

Who is eating the bandwidth?

No filter needed. Statistics → Conversations → IPv4 → sort by Bytes, then right-click the top row → Apply as Filter. Thirty seconds, every time.

07 · Traps

ip.addr != 192.168.1.1 does not do what you think

It reads as "there exists an address field that is not the gateway" — and every packet has two address fields, so gateway traffic matches too and you filter out nothing. The bar goes yellow to warn you. Always write !(ip.addr == 192.168.1.1). Same trap for every field that appears more than once per packet.

Promiscuous mode is not a superpower

It only stops your own NIC discarding frames not addressed to it. On a switched network those frames never reach your card. The fix is the tap point, never a checkbox.

Capturing localhost needs the Npcap loopback adapter

Traffic between two programs on the same PC never touches the Wi-Fi card. Pick Adapter for loopback traffic capture in the interface list instead.

Do not leave the GUI running as Administrator

Dissectors parse hostile input off the wire and that is where the CVEs live. Npcap's installer has a "restrict to Administrators" option precisely so capture runs privileged while analysis does not. Capture with dumpcap, analyse unprivileged.

08 · Same thing without the GUI

tshark is Wireshark with the same dissectors and the same display filters.

# list interfaces (you need the number for -i)
tshark -D

# live: every hostname looked up, one per line
tshark -i 5 -Y "dns.flags.response == 0" -T fields -e dns.qry.name

# -f is a CAPTURE filter (BPF), -Y is a DISPLAY filter. Same split as the GUI.
tshark -i 5 -f "tcp port 443" -Y "tls.handshake.type == 1" \
       -T fields -e ip.dst -e tls.handshake.extensions_server_name

# chew through a saved file: top talkers
tshark -r capture.pcapng -q -z conv,tcp

# ring buffer: 10 x 60s files, then stop worrying about disk
dumpcap -i 5 -b duration:60 -b files:10 -w ring.pcapng

Live capture from the gateway

The payoff for §01, if your router lets you in. tcpdump streams raw pcap over SSH and Wireshark reads it from stdin as if it were a local interface:

ssh root@192.168.1.1 "tcpdump -i br-lan -U -s0 -w - not port 22" | wireshark -k -i -

-U flushes per packet so it is actually live, and excluding port 22 stops your SSH session from capturing itself capturing itself.

Ready to use it? The network challenges are built to be solved with exactly what is on this page, in roughly this order.