kavklaw@llm $ cat wireshark-guide.md
โฑ๏ธ 25 min read ยท From your first capture to forensic-level packet analysis and CTF pcap challenges
Need to analyze a pcap file (a saved recording of network traffic) right now? Here's the 90-second version:
wireshark capture.pcap # Open in GUI
tshark -r capture.pcap | head -50 # Quick CLI overview
tshark -r capture.pcap -Y "http" # Find HTTP traffic
tshark -r capture.pcap --export-objects http,exported_files/ # Extract files
tshark -r capture.pcap -Y "http.request.method == POST" -T fields -e http.file_data # Credentials
tshark -r capture.pcap -z "follow,tcp,ascii,0" # Follow a TCP stream
That covers the essentials. Now let's understand how Wireshark works, how to filter like a pro, and how to crack CTF pcap challenges.
Wireshark lets you see packets visible at your capture point. It captures traffic flowing across a network interface and breaks it down into a readable format โ you see exactly what's happening, byte by byte.
Started as Ethereal in 1998, renamed Wireshark in 2006. You'll use it for:
Wireshark speaks hundreds of protocols โ from Ethernet and IP at the bottom to HTTP, DNS, SMB, TLS at the top. It breaks each packet into its fields, color-codes traffic by type, and lets you filter down to exactly what you're looking for.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Wireshark Packet Dissection (what you see per packet) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Layer 7 Application โ HTTP, DNS, FTP, SMB, TLS โ
โ Layer 4 Transport โ TCP / UDP (ports, flags) โ
โ Layer 3 Network โ IP (src/dst addresses) โ
โ Layer 2 Data Link โ Ethernet (MAC addresses) โ
โ Layer 1 Raw โ Frame bytes (hex dump) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Wireshark expands each layer โ click to drill down โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
The real power is the display filter engine. The right filter pulls a single login attempt out of millions of packets. Master the filters and you master Wireshark.
Wireshark comes pre-installed on Kali Linux and Parrot OS. For other systems:
# Kali/Debian/Ubuntu
sudo apt update && sudo apt install wireshark tshark
sudo usermod -aG wireshark $USER # Allow capture without root
# Fedora/RHEL
sudo dnf install wireshark wireshark-cli
# Arch Linux
sudo pacman -S wireshark-qt
# macOS (via Homebrew)
brew install --cask wireshark
# Verify installation
wireshark --version
tshark --version
โ ๏ธ Permissions matter: Raw packet capture requires root privileges or membership in the wireshark group. During installation on Debian/Ubuntu, you'll be asked "Should non-superusers be able to capture packets?" โ select YES, then add your user to the wireshark group with the usermod command above. Log out and back in (or run newgrp wireshark) for the group change to take effect. Without this, you can only analyze existing pcap files โ live capture won't work.
๐ก Pro Tip: You don't always need the GUI.tshark(the terminal-based Wireshark) is faster for scripting and remote analysis. If you're SSH'd into a machine,tsharkis your best friend. Many CTF challenges can be solved entirely from the command line.
Raw packet capture normally requires root privileges. The wireshark group method above avoids running Wireshark as root (which is a security risk). Alternatively, capture with tcpdump as root and analyze the resulting pcap file as a regular user:
sudo tcpdump -i eth0 -w capture.pcap
Then open capture.pcap in Wireshark as non-root.
When you open Wireshark, the welcome screen shows all available network interfaces with sparkline traffic graphs. Double-click an interface to start capturing.
tshark -D # List available interfaces
Common interfaces:
eth0 โ Wired Ethernetwlan0 โ Wirelesslo โ Loopback (localhost traffic)tun0 โ VPN tunnel (HTB/THM)any โ Capture on ALL interfacestshark -i tun0 -w htb_capture.pcap # HTB/THM โ always capture on tun0
tshark -i lo -w localhost_capture.pcap # Local web app testing โ use loopback
Promiscuous mode (default) captures all traffic the NIC (Network Interface Card โ your network adapter) can see, not just traffic destined for your MAC address (the hardware address unique to your network adapter). On a switched network, you'll mostly see your own traffic plus broadcasts.
Monitor mode (wireless only) puts your wireless adapter into a raw capture mode that can see all WiFi frames in range, including traffic between other devices. This is essential for wireless pentesting.
sudo airmon-ng start wlan0 # Enable monitor mode โ creates wlan0mon
tshark -i wlan0mon -c 1000 -w wifi_capture.pcap
This distinction trips up every beginner. Wireshark has two completely different filter systems with different syntax:
Applied before packets are captured. Uses Berkeley Packet Filter (BPF) syntax, the same language used by the tcpdump command-line tool. These filters limit what's saved to the capture file. Use them when you know exactly what traffic you want and need to keep file sizes manageable.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ CAPTURE FILTERS (BPF) โ set BEFORE capture starts โ
โ Syntax: tcpdump-style Where: Capture Options dialog โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ host 10.10.10.100 Traffic to/from a specific host โ
โ port 80 Only port 80 traffic โ
โ tcp port 443 Only TCP port 443 โ
โ net 192.168.1.0/24 Traffic on a subnet โ
โ src host 10.10.10.100 Only FROM this host โ
โ dst port 22 Only TO port 22 โ
โ not arp Exclude ARP traffic โ
โ tcp and port 80 TCP traffic on port 80 โ
โ host 10.10.10.1 and port 445 SMB traffic to specific host โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ DISPLAY FILTERS (Wireshark) โ applied AFTER capture โ
โ Syntax: Wireshark-native Where: filter bar (green/red) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ ip.addr == 10.10.10.100 Traffic to/from a host โ
โ tcp.port == 80 TCP port 80 โ
โ http All HTTP traffic โ
โ dns All DNS traffic โ
โ tcp.flags.syn == 1 SYN packets only โ
โ http.request.method == "POST" HTTP POST requests โ
โ frame contains "password" Packets containing "password" โ
โ !(arp or dns) Exclude ARP and DNS noise โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Applied after capture. Uses Wireshark's own powerful filter language. Filters what's displayed โ the full capture is still in memory. This is what you'll use 95% of the time. See the diagram above for a side-by-side comparison.
Filter:
http.request.method == "POST" shows only HTTP POST requests. This is essential for finding login attempts, form submissions, and file uploads in a capture. Note the Wireshark filter syntax uses == (double equals) and string values in quotes. Combine it with frame contains "password" to find credential submissions.Filter:
!(arp || dns || icmp) removes the three most common sources of noise in a capture: ARP broadcasts, DNS queries/responses, and ICMP ping traffic. This is often the first filter to apply when opening any pcap file, as it lets you focus on the interesting traffic like HTTP, FTP, and SMB. Some analysts also add stp (Spanning Tree Protocol) to the exclusion list.โ ๏ธ Critical Distinction:port 80is a capture filter.tcp.port == 80is a display filter. They go in different places and use different syntax. Putting display filter syntax in the capture filter box will give you an error. The display filter bar is the green/red bar at the top of the main Wireshark window โ green means valid syntax, red means invalid.
Here are the filters you'll use most often, organized by scenario:
http # All HTTP traffic
dns # All DNS queries/responses
tcp # All TCP traffic
udp # All UDP traffic
icmp # All ICMP (ping) traffic
arp # All ARP traffic
ftp # All FTP traffic
ssh # All SSH traffic (encrypted payload)
smb || smb2 # All SMB traffic
tls # All TLS/SSL traffic
ip.addr == 10.10.10.100 # To or from this IP
ip.src == 10.10.10.100 # FROM this IP only
ip.dst == 10.10.10.100 # TO this IP only
eth.addr == aa:bb:cc:dd:ee:ff # MAC address filter
tcp.port == 80 # TCP port 80 (either direction)
tcp.dstport == 443 # Destination port 443
tcp.srcport == 8080 # Source port 8080
udp.port == 53 # UDP port 53 (DNS)
ip.addr == 10.10.10.0/24 # Entire subnet
tcp.port in {80, 443, 8080, 8443} # Multiple ports
http.request # HTTP requests only
http.response # HTTP responses only
http.request.method == "GET" # GET requests
http.request.method == "POST" # POST requests
http.request.uri contains "login" # URIs containing "login"
http.host == "target.htb" # Specific Host header
http.response.code == 200 # 200 OK responses
http.response.code >= 400 # Error responses (4xx, 5xx)
http.content_type contains "json" # JSON responses
http.cookie contains "session" # Cookie inspection
http.set_cookie # Set-Cookie headers
http.authorization # Authorization headers
http.request.uri contains "api" # API endpoint traffic
frame contains "password" # Search raw bytes for string
frame contains "flag{" # CTF flag hunting!
http.file_data contains "admin" # Search HTTP body content
tcp contains "login" # TCP payload search
data.data contains "secret" # Data field search
frame matches "flag\{[a-zA-Z0-9]+\}" # Regex match (slower)
tcp.flags.syn == 1 && tcp.flags.ack == 0 # SYN packets (new connections)
tcp.flags.reset == 1 # RST packets (rejected connections)
tcp.flags.fin == 1 # FIN packets (closing connections)
tcp.analysis.retransmission # Retransmitted packets
tcp.analysis.zero_window # Zero window (flow control)
tcp.analysis.duplicate_ack # Duplicate ACKs
tcp.stream eq 5 # Specific TCP stream number
Use && (AND), || (OR), ! (NOT), and parentheses to build complex filters:
http.request.method == "POST" && ip.dst == 10.10.10.100 # AND โ both conditions
dns || http # OR โ either condition
!arp && !dns && !icmp # NOT โ remove noise
(http.request.method == "POST" || http.request.method == "PUT") &&
ip.src == 192.168.1.50 # Complex combination
(tcp.port == 80 || tcp.port == 443) && ip.addr == 10.10.10.100 # Parentheses for grouping
๐ก Pro Tip: Learn to type !(arp || dns || icmp || stp) as your first filter when opening any pcap. This removes protocol noise and lets you focus on interesting traffic. You can save this as a filter button in Wireshark for one-click access.
This is one of Wireshark's most powerful features, and it's very beginner-friendly. "Following a stream" reconstructs the full conversation between two endpoints, showing you exactly what was sent and received in order. Think of it like reading a chat transcript between two computers. Instead of looking at individual packets, you see the whole conversation at once.
In the GUI: Right-click any packet โ Follow โ TCP Stream (or UDP/HTTP/TLS). A new window shows the full reconstructed conversation. Client data appears in red, server data in blue.
tshark -r capture.pcap -z "follow,tcp,ascii,0" # Stream 0 โ change number for others
tshark -r capture.pcap -z "follow,http,ascii,0" # Follow HTTP stream
tshark -r capture.pcap -z "conv,tcp" # List all TCP streams & endpoints
tshark -r capture.pcap -Y "tcp.stream eq 5" -T fields -e data.data # Specific stream
๐ก Pro Tip: In the Follow Stream window, use the "Stream" dropdown at the bottom to cycle through all streams. In many CTF challenges, the flag is in one specific stream โ systematically check each one. The stream number also appears in the display filter bar, so you can easily jump back and forth.
HTTP is cleartext, which means Wireshark can dissect every request and response in full detail. This is where you'll find credentials, API keys, uploaded files, and exploitation attempts.
Filter for all HTTP requests with http.request, then expand the packet in Wireshark to see full details:
Hypertext Transfer Protocol
Request Method: POST
Request URI: /login.php
Host: target.htb
User-Agent: Mozilla/5.0 ...
Content-Type: application/x-www-form-urlencoded
Cookie: PHPSESSID=abc123def456
HTML Form URL Encoded: application/x-www-form-urlencoded
Form item: "username" = "admin"
Form item: "password" = "P@ssw0rd123" โ CREDENTIALS IN CLEARTEXT!
tshark -r capture.pcap -Y "http.request.method == POST" \
-T fields -e http.host -e http.request.uri -e http.file_data # POST form data
tshark -r capture.pcap -Y "http.request" \
-T fields -e http.host -e http.request.full_uri # All requested URLs
tshark -r capture.pcap -Y "http.cookie" \
-T fields -e ip.src -e http.cookie # Cookies
tshark -r capture.pcap -Y "http.user_agent" \
-T fields -e ip.src -e http.user_agent | sort -u # User-Agents (ID tools)
Directory brute forcing (many 404s from one source):
tshark -r capture.pcap -Y "http.response.code == 404" \
-T fields -e ip.dst -e http.request.uri | head -20
Web shell traffic detection:
http.request.uri contains "cmd="
http.request.uri contains "exec="
http.request.uri contains "shell"
frame contains "
SQL injection attempts:
http.request.uri contains "UNION"
http.request.uri contains "' OR "
frame contains "sqlmap"
Here's why unencrypted traffic is a critical security risk: when data travels across a network without encryption, anyone on the same network segment can read it. Think of it like sending a postcard instead of a sealed letter โ every mail carrier along the way can read your message. On a shared network (coffee shop WiFi, corporate LAN, compromised router), an attacker running Wireshark or tcpdump can capture login credentials, session tokens, personal data, and API keys in real time. This is why HTTPS and encrypted protocols exist โ they turn that postcard into a sealed, tamper-proof envelope.
One of the most common pentest findings (and CTF challenges) involves extracting credentials from unencrypted traffic. Many protocols transmit credentials in cleartext or with weak encoding.
FTP โ credentials sent in plaintext (you'll see USER admin โ PASS secretpassword):
ftp.request.command == "USER" || ftp.request.command == "PASS"
HTTP Basic Auth โ Base64 encoded (trivially decoded with echo "YWRtaW46cGFzc3dvcmQ=" | base64 -d โ admin:password):
http.authorization
HTTP Form Login โ POST body in cleartext:
http.request.method == "POST" && frame contains "password"
Other cleartext protocols โ use these display filters:
telnet # Everything in cleartext, character by character
smtp.req.command == "AUTH" # SMTP Auth โ Base64 encoded
pop.request.command == "USER" || pop.request.command == "PASS" # POP3
imap.request contains "LOGIN" # IMAP
ldap.bindRequest && !(ldap.bindRequest_element.authentication == 3) # LDAP Simple Bind
snmp.community # SNMP community strings
tshark -r capture.pcap -Y "ftp.request.command == USER || ftp.request.command == PASS" \
-T fields -e ftp.request.command -e ftp.request.arg # FTP credentials
tshark -r capture.pcap -Y "http.authorization" \
-T fields -e ip.src -e http.authorization # HTTP Basic Auth
tshark -r capture.pcap -Y "snmp" \
-T fields -e ip.src -e ip.dst -e snmp.community # SNMP community strings
tshark -r capture.pcap -Y "http.request.method == POST && http.request.uri contains login" \
-T fields -e frame.time -e http.file_data | head -30 # Brute force detector
$ tshark -r capture.pcap -z "io,phs" -q
Protocol Hierarchy Statistics:
eth
ip
tcp
http 45.2%
tls 30.1%
udp
dns 20.5%
data 4.2%
-sT (TCP connect scan) through SOCKS proxies. SYN scans (-sS) require raw sockets which don't work through SOCKS. ICMP (ping) doesn't work either, so always add -Pn to skip ping. UDP scans (-sU) also won't work. The full command through proxychains is: proxychains nmap -sT -Pn target.๐ก Pro Tip: Use Edit โ Find Packet (Ctrl+F) in Wireshark, set it to "String" and search for common credential keywords:password,passwd,pass,login,user,token,secret,key,auth. This brute-force approach catches credentials across all protocols.
TLS (Transport Layer Security, the encryption behind HTTPS) makes traffic unreadable in Wireshark. All you see is "Application Data" with no visible content. But there are several ways to decrypt it if you have the right keys:
Even without decryption keys, the TLS handshake reveals useful metadata:
tls.handshake # All handshake messages
tls.handshake.type == 1 # Client Hello
tls.handshake.type == 2 # Server Hello
tls.handshake.type == 11 # Certificate
tls.handshake.extensions_server_name # SNI (Server Name Indication) โ which hostname was requested
Extract SNI hostnames, TLS versions, and JA3 fingerprints (JA3 is a method of fingerprinting TLS clients by hashing their handshake parameters โ useful for identifying specific tools or malware):
tshark -r capture.pcap -Y "tls.handshake.type == 1" \
-T fields -e ip.dst -e tls.handshake.extensions_server_name | sort -u # SNI hostnames
tshark -r capture.pcap -Y "tls.handshake.type == 2" \
-T fields -e tls.handshake.version | sort | uniq -c # TLS versions
tshark -r capture.pcap -Y "tls.handshake.type == 1" \
-T fields -e tls.handshake.ja3 # JA3 fingerprint
If you have the server's private key (RSA key exchange only) or the SSLKEYLOGFILE (pre-master secrets), you can decrypt TLS traffic:
Method 1: SSLKEYLOGFILE (works with modern TLS including PFS โ Perfect Forward Secrecy, where each session uses a unique key so compromising one session doesn't compromise others). Set this environment variable before starting the browser:
export SSLKEYLOGFILE=/tmp/tls_keys.log
Then in Wireshark: Edit โ Preferences โ Protocols โ TLS โ (Pre)-Master-Secret log filename โ set to /tmp/tls_keys.log. Wireshark will now decrypt TLS traffic.
Method 2: RSA private key (only works with RSA key exchange, no PFS). In Wireshark: Edit โ Preferences โ Protocols โ TLS โ RSA keys list โ add IP, Port, Protocol, Key file.
Decrypt with tshark:
tshark -r capture.pcap -o "tls.keylog_file:/tmp/tls_keys.log" -Y http
๐ก Pro Tip: In CTF challenges, if you're given both a pcap and a private key file (.pem/.key), the challenge almost certainly wants you to decrypt TLS traffic. Load the key in Wireshark's TLS settings and the encrypted traffic will magically become readable HTTP.
DNS traffic is a goldmine. It reveals what hosts were contacted, can expose data exfiltration, and in CTFs often hides flags in DNS queries or TXT records.
Basic DNS filters:
dns # All DNS traffic
dns.flags.response == 0 # DNS queries only
dns.flags.response == 1 # DNS responses only
dns.qry.name contains "target.htb" # Queries for specific domain
dns.flags.rcode == 3 # NXDOMAIN (domain not found)
DNS query types:
dns.qry.type == 1 # A records
dns.qry.type == 28 # AAAA records
dns.qry.type == 5 # CNAME (Canonical Name โ alias pointing to another domain)
dns.qry.type == 16 # TXT records (often hide data!)
dns.qry.type == 15 # MX records (mail servers)
dns.qry.type == 33 # SRV records (service discovery)
dns.qry.type == 252 # AXFR (zone transfer โ downloads the ENTIRE DNS zone!)
Extract and analyze DNS data with tshark:
tshark -r capture.pcap -Y "dns.flags.response == 0" \
-T fields -e dns.qry.name | sort -u # All queried domains
tshark -r capture.pcap -Y "dns.qry.name" \
-T fields -e dns.qry.name | awk 'length > 50' # DNS tunneling (long labels)
tshark -r capture.pcap -Y "dns.txt" \
-T fields -e dns.txt # TXT record answers
DNS tunneling/exfiltration encodes data in DNS queries (usually as long subdomain labels). Watch for:
tshark -r capture.pcap -Y "dns.qry.name" \
-T fields -e dns.qry.name | \
awk -F. '{for(i=1;i<NF;i++) if(length($i)>20) print}' | sort -u # Long labels
tshark -r capture.pcap -Y "dns.qry.name contains exfil.evil.com" \
-T fields -e dns.qry.name | \
sed 's/.exfil.evil.com//' | base64 -d # Decode exfil data
Wireshark's statistics features give you a high-level overview before diving into individual packets. Always check statistics first when analyzing an unfamiliar pcap.
In the GUI: Statistics menu โ various options. With tshark:
tshark -r capture.pcap -z "io,phs" # Protocol hierarchy (% per protocol)
tshark -r capture.pcap -z "conv,ip" # Conversations โ who's talking to whom?
tshark -r capture.pcap -z "conv,tcp" # TCP conversations (src, dst, packets, bytes)
tshark -r capture.pcap -z "endpoints,ip" # List all IP addresses
tshark -r capture.pcap -z "http,tree" # All HTTP requests
tshark -r capture.pcap -z "dns,tree" # DNS query statistics
tshark -r capture.pcap -z "io,stat,1" # IO graph (1-second intervals)
๐ก Pro Tip: When you first open a CTF pcap, go to Statistics โ Protocol Hierarchy. This immediately tells you what protocols are present. If you see FTP โ look for credentials. HTTP โ look for web traffic. DNS โ check for tunneling. This 5-second check sets your analysis direction.
Wireshark can reconstruct and export files transferred over HTTP, SMB, TFTP, and other protocols. This is critical for CTF challenges where files are hidden in pcaps.
File โ Export Objects โ HTTP/SMB/TFTP/DICOM
This shows all files transferred over the selected protocol. You can save individual files or export all at once.
mkdir http_objects
tshark -r capture.pcap --export-objects http,http_objects/
mkdir smb_objects
tshark -r capture.pcap --export-objects smb,smb_objects/
mkdir tftp_objects
tshark -r capture.pcap --export-objects tftp,tftp_objects/
After exporting, always check file types โ some files might be renamed or disguised:
file http_objects/*
xxd http_objects/suspicious_file | head # Check magic bytes
When automatic export doesn't work, you can manually extract files:
For binary files in HTTP: follow the HTTP stream, show as Raw, save โ but remove the HTTP headers manually. Alternatively, use Export Packet Bytes (Ctrl+Shift+X) on just the data portion.
๐ก Pro Tip: After exporting HTTP objects, runfile *andstringson everything. CTF flags are often hidden in images (steganography), PDFs, or disguised files. An exported "image.png" might actually be a ZIP file โ check the magic bytes!
tshark is the command-line version of Wireshark. It has the same dissection capabilities but is perfect for scripting, automation, and working on remote servers without a GUI.
tshark -r capture.pcap # Basic read โ like tcpdump
tshark -r capture.pcap -Y "http.request" # Apply display filter
tshark -r capture.pcap -Y "http.request" \
-T fields -e frame.number -e ip.src -e http.request.method -e http.request.uri # Custom fields
tshark -r capture.pcap -Y "http.request" \
-T fields -E separator=, -e ip.src -e http.host -e http.request.uri # CSV output
tshark -r capture.pcap -Y "http.request" -T json | python3 -m json.tool # JSON output
tshark -r capture.pcap -Y "http.response.code == 404" | wc -l # Count packets
tshark -r capture.pcap -Y "frame.number == 42" -V # Packet details
Live capture and ring buffer:
sudo tshark -i tun0 -Y "http.request" -T fields -e http.host -e http.request.uri
sudo tshark -i eth0 -b filesize:10000 -b files:5 -w capture.pcap # Rotate files
tshark -r capture.pcap -T fields -e ip.src -e ip.dst | \
tr '\t' '\n' | sort -u # All unique IPs
tshark -r capture.pcap -Y "http.request" \
-T fields -e frame.time -e ip.src -e http.request.method \
-e http.request.full_uri # HTTP timeline
tshark -r capture.pcap -Y "tcp.flags.syn == 1 && tcp.flags.ack == 0" \
-T fields -e ip.src -e tcp.dstport | \
sort | uniq -c | sort -rn | head -20 # Detect port scanning
tshark -r capture.pcap -T fields -e frame.protocols -e data.data 2>/dev/null | \
grep -oP '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' # Extract emails
tshark -r capture.pcap -z "endpoints,ip" -q # Bandwidth per IP
Network forensics is a staple CTF category. Here are the most common patterns and how to solve them:
tshark -r challenge.pcap --export-objects http,exported/ # Step 1: Export objects
tshark -r challenge.pcap -Y 'frame contains "flag{"' # Step 2: Search for flag
tshark -r challenge.pcap -Y 'frame contains "CTF{"'
tshark -r challenge.pcap -Y "http.response" \
-T fields -e http.file_data | strings | grep -i flag # Step 3: Response bodies
tshark -r challenge.pcap -Y "ftp.request.command == USER || ftp.request.command == PASS" \
-T fields -e ftp.request.command -e ftp.request.arg # FTP credentials
tshark -r challenge.pcap -Y "ftp-data" -z "follow,tcp,ascii,0" # FTP transferred files
tshark -r challenge.pcap -z "follow,tcp,ascii,0" | grep -A 500 "Telnet" # Telnet session
Identify file transfers by looking for magic bytes:
tshark -r challenge.pcap -Y "tcp" -T fields -e data.data | \
grep -i "504b0304" # ZIP magic bytes (PK..)
tshark -r challenge.pcap -Y "tcp" -T fields -e data.data | \
grep -i "89504e47" # PNG magic bytes
To export: in Wireshark, Follow TCP Stream โ Show as Raw โ Save As.
Look for encoded subdomains (e.g., dGhlIGZsYWcgaXM.evil.com โ base64 of flag data):
tshark -r challenge.pcap -Y "dns.qry.name" \
-T fields -e dns.qry.name | sort -u # All DNS queries
tshark -r challenge.pcap -Y "dns.qry.name contains evil.com" \
-T fields -e dns.qry.name | \
sed 's/.evil.com//g' | tr -d '\n' | base64 -d # Decode exfil subdomains
tshark -r challenge.pcap -Y "dns.txt" -T fields -e dns.txt # Hidden TXT records
WiFi management frame filters:
wlan.fc.type == 0 # Management frames
wlan.fc.type_subtype == 0x08 # Beacon frames (network names)
wlan.fc.type_subtype == 0x04 # Probe requests
wlan.fc.type_subtype == 0x0b # Authentication frames
eapol # EAPOL (Extensible Authentication Protocol over LAN)
# โ captures the WPA 4-way handshake needed for WiFi password cracking
tshark -r wifi.pcap -Y "wlan.fc.type_subtype == 0x08" \
-T fields -e wlan.ssid | sort -u # Extract SSIDs (network names)
Export EAPOL frames and crack with aircrack-ng or hashcat.
Data hidden in ICMP echo request/reply payloads:
tshark -r challenge.pcap -Y "icmp" -T fields -e data.data # Raw hex
tshark -r challenge.pcap -Y "icmp.type == 8" -T fields -e data.data | xxd -r -p # Hex โ ASCII
๐ก Pro Tip: For CTF pcap challenges, always follow this checklist: (1) Protocol hierarchy โ what's in the capture? (2) Export HTTP/SMB objects. (3) Search for flag format strings. (4) Follow every TCP stream. (5) Check DNS for hidden data. (6) Look for encoded payloads (Base64, hex). (7) Check ICMP payloads. (8) Extract and analyze any files found.
When analyzing a pcap file, whether for a CTF, incident response, or pentest, follow this systematic approach:
capinfos capture.pcap # Capture file info
tshark -r capture.pcap -z "io,phs" -q # Protocol hierarchy
tshark -r capture.pcap -z "conv,ip" -q # Conversations
tshark -r capture.pcap -z "endpoints,ip" -q # Endpoints
tshark -r capture.pcap -T fields -e frame.time | head -1 # First packet time
tshark -r capture.pcap -T fields -e frame.time | tail -1 # Last packet time
mkdir exported && tshark -r capture.pcap --export-objects http,exported/ # Export HTTP objects
# Search for common flag formats
for pattern in "flag{" "CTF{" "FLAG{" "ctf{" "key{"; do
echo "=== Searching: $pattern ==="
tshark -r capture.pcap -Y "frame contains \"$pattern\"" 2>/dev/null
done
tshark -r capture.pcap -Y "ftp.request.command == USER || ftp.request.command == PASS" \
-T fields -e ftp.request.arg 2>/dev/null # FTP creds
tshark -r capture.pcap -Y "http.authorization" \
-T fields -e http.authorization 2>/dev/null # HTTP auth
tshark -r capture.pcap -Y "http.request" \
-T fields -e frame.time -e ip.src -e http.request.method -e http.request.full_uri # HTTP detail
tshark -r capture.pcap -z "follow,tcp,ascii,0" # Follow streams
tshark -r capture.pcap -Y "dns.flags.response == 0" \
-T fields -e dns.qry.name | sort -u # DNS queries
tshark -r capture.pcap -z "expert" -q # Expert info (anomalies)
For complex file extraction, use the Wireshark GUI, NetworkMiner for automated carving, or foremost/binwalk on raw stream data for hidden files.
Timeline reconstruction:
tshark -r capture.pcap -Y "http.request || ftp.request || dns.flags.response==0" \
-T fields -e frame.time_relative -e ip.src -e ip.dst \
-e _ws.col.Protocol -e _ws.col.Info | head -50
โ Mistake #1: Confusing display filters with capture filters.
port 80is BPF syntax (capture filter).tcp.port == 80is Wireshark syntax (display filter). Using the wrong syntax in the wrong box gives you errors or no results. The display filter bar turns green when the syntax is valid, red when it's wrong.
โ Mistake #2: Not checking Statistics โ Protocol Hierarchy first.
Before searching for anything specific, understand what's in the capture. A 5-second protocol hierarchy check tells you whether to focus on HTTP, FTP, DNS, or something else entirely.
โ Mistake #3: Ignoring DNS traffic.
DNS queries reveal every hostname contacted. DNS tunneling hides data in subdomain labels. DNS TXT records can contain flags, tokens, or configuration data. Always check DNS.
โ Mistake #4: Only using the GUI.
The GUI is great for exploration, buttsharkis essential for automation, large pcap files, and scripted analysis. Learn both. Many CTF challenges are faster to solve with a one-liner than clicking through the GUI.
โ Mistake #5: Not exporting HTTP objects.
File โ Export Objects โ HTTPextracts all transferred files with one click. Many challenges hide flags in images, documents, or other files embedded in HTTP traffic. Always export and examine every object.
โ Mistake #6: Forgetting to check ICMP payloads.
ICMP echo (ping) packets can carry data in their payload. This is commonly used for ICMP tunneling and data exfiltration. In CTFs, flags are frequently hidden in ICMP payloads.
Best for: Interactive analysis, protocol deep-dives, following streams, CTF pcap challenges. The go-to for visual packet inspection.
Best for: Remote capture on headless servers, quick traffic checks over SSH, lightweight packet capture with BPF filters. Pre-installed on most Linux systems.
Best for: Automated pcap analysis, scripted field extraction, piping output to other tools. Wireshark's power without the GUI overhead.