Protocol Dissectors
Wireshark's protocol dissectors decode each layer of a packet into named fields. Understanding what each dissector extracts — and what it cannot see — determines how deeply you can investigate each protocol. This chapter covers the forensically critical dissectors: HTTP, DNS, SMB, TLS, FTP, SMTP, and Kerberos.
During an investigation you encounter: an HTTP session where the response body contains base64-encoded data, a DNS exchange with unusually long TXT records, an SMB session where a named pipe is used to execute a command, a Kerberos exchange requesting service tickets for multiple SPNs in rapid succession. Each of these is visible and analyzable through the right dissector — if you know where to look and what fields mean.
HTTP Dissector
HTTP Packet Fields in Wireshark Details Pane
═══════════════════════════════════════════════════════════════════
▼ Hypertext Transfer Protocol
▼ GET /updates.rss HTTP/1.1\r\n
Request Method: GET
Request URI: /updates.rss
Request Version: HTTP/1.1
▼ Host: updates.microsoft.com\r\n
Host: updates.microsoft.com
▼ User-Agent: Mozilla/5.0...\r\n
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
▼ Cookie: __cfduid=BQDXJHAX...\r\n
Cookie: __cfduid=BQDXJHAX...
[Full request URI: http://updates.microsoft.com/updates.rss]
[HTTP request sequence number: 1]
[Response in frame: 47]
Key display filters for HTTP:
http.request.method == "POST" → POST requests (data upload)
http.request.uri contains ".exe" → executable downloads
http.user_agent contains "curl" → curl user agent
http.cookie → any packet with Cookie header
http.response.code == 200 → successful responses
http.content_length > 1000000 → large response bodies
http.transfer_encoding == "chunked" → chunked responses (reassembled)
Chunked transfer encoding:
Wireshark reassembles chunked HTTP bodies automatically.
Look for "[Reassembled HTTP]" in Details pane for chunked responses.
Follow HTTP Stream shows the fully reassembled body.
HTTP/1.1 keep-alive sessions:
Multiple request-response cycles in one TCP stream.
Each HTTP exchange has a unique sequence number.
Filter: http.request_number == 3 (third request in the session)
DNS Dissector
DNS Packet Fields
═══════════════════════════════════════════════════════════════════
▼ Domain Name System (query)
Transaction ID: 0x3f2a
Flags: 0x0100 Standard query
.... 0... = Response: Message is a query
.... ...0 = Truncated: Not truncated
.... ..1. = Recursion desired: Do query recursively
Questions: 1
▼ Queries
▼ randomxkcd234abf.evil.com: type A, class IN
Name: randomxkcd234abf.evil.com ← this is the forensic indicator
Type: A (1)
Class: IN (1)
▼ Domain Name System (response)
▼ Flags: 0x8183 Standard query response, No such name
.... 1... = Response: Message is a response
.... .... ..0. = Recursion available: No ← NXDOMAIN
RCODE: No such name (3) ← DGA candidate
Key display filters for DNS:
dns.qry.name → any packet with DNS query
dns.qry.name contains "evil.com" → specific domain
dns.flags.rcode == 3 → NXDOMAIN responses (DGA beacon)
dns.qry.type == 16 → TXT record queries (tunneling)
dns.qry.type == 28 → AAAA queries (IPv6 or covert use)
dns.resp.ttl < 60 → very low TTL (fast-flux C2)
dns.qry.name matches "[a-z0-9]{20,}" → long random-looking domain names
DGA pattern in PCAP:
→ Hundreds of NXDOMAIN responses in a short window
→ Each query is a different high-entropy subdomain
→ All queries share the same base domain (the DGA's seed domain)
→ Pattern: randomhash1.seed.com → NXDOMAIN, randomhash2.seed.com → NXDOMAIN
→ Then: randomhashN.seed.com → A record (active C2 domain found)
SMB Dissector — Lateral Movement Artifacts
SMB2 Protocol Fields (lateral movement session)
═══════════════════════════════════════════════════════════════════
▼ SMB2 (Server Message Block Protocol version 2)
▼ SMB2 Header
Command: NEGOTIATE (0)
Message ID: 0
Process Id: 0xfffe
Tree Id: 0
Session Id: 0x0000000000000000
▼ Negotiate Protocol Request
Dialect: SMB 3.1.1 (0x0311)
Capabilities: DFS, Leasing, LargeMTU, MultiChannel, Encryption
Authentication chain (NTLM):
▼ NTLMSSP_NEGOTIATE → NTLMSSP_CHALLENGE → NTLMSSP_AUTH
▼ NTLM Secure Service Provider
NTLMSSP identifier: NTLMSSP
NTLM Message Type: NTLMSSP_AUTH (0x00000003)
▼ NT-Response
NTProofStr: ab23cd45ef67... ← NTLMv2 hash (first 16 bytes)
NTLMv2 Client Challenge: ...
Domain name: CORP
User name: jsmith ← attacker's credentials
Host name: WS01
Named pipe lateral movement — look for:
smb2.filename contains "svcctl" → Service Control Manager named pipe
smb2.filename contains "atsvc" → Task Scheduler
smb2.filename contains "samr" → SAM database access
smb2.ioctl.function == 0x0011c017 → Named pipe transact
Share access:
smb2.tree.share_type == 0x01 → disk share (file access)
smb2.filename contains "ADMIN$" → admin share (lateral movement)
smb2.filename contains "IPC$" → IPC share (named pipe connection)
When an attacker uses PsExec, Impacket's smbexec, or WMI-based lateral movement, the visible network artifact is almost always an SMB session to IPC$ followed by a named pipe connection. PsExec connects to \\target\ADMIN$ to upload the service binary, then connects to the svcctl named pipe via IPC$ to start the service remotely. In Wireshark, this appears as: SMB2 TREE_CONNECT to \\target\IPC$, followed by SMB2 CREATE for \svcctl. The pipe name is the indicator — svcctl means Service Control Manager, atsvc means Task Scheduler, samr means SAM database. Each of these named pipes represents a specific lateral movement technique.
TLS Dissector — Handshake Analysis
TLS 1.2 Handshake Fields
═══════════════════════════════════════════════════════════════════
▼ TLSv1.2 Record Layer: Handshake Protocol: Client Hello
Content Type: Handshake (22)
Version: TLS 1.0 (0x0301) ← Record layer says 1.0 for compatibility
▼ Handshake Protocol: Client Hello
Handshake Type: Client Hello (1)
Version: TLS 1.2 (0x0303) ← Actual TLS version
Random: a3b4c5d6...
Session ID Length: 0
▼ Cipher Suites (13 suites)
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
... etc
▼ Extensions
▼ Extension: server_name (SNI)
Server Name: updates.microsoft.com ← forensic key indicator
▼ Extension: supported_groups
Supported Groups: x25519, secp256r1, secp384r1
▼ Extension: signature_algorithms
TLS_SIGNATURE_SHA256_RSA, ...
▼ Extension: application_layer_protocol_negotiation (ALPN)
ALPN Protocol: h2 ← HTTP/2 requested
JA3 computation (see Ch32):
JA3 string = Version + CipherSuites + Extensions + Groups + PointFormats
JA3 hash = MD5(JA3 string)
Visible in Wireshark with the JA3 plugin
Key filters:
tls.handshake.type == 1 → ClientHello
tls.handshake.extensions_server_name → SNI present
tls.handshake.ciphersuite == 0xc02f → specific cipher suite
Kerberos Dissector — Attack Detection
Kerberos TGS-REQ (service ticket request)
═══════════════════════════════════════════════════════════════════
▼ Kerberos
▼ as-req / tgs-req
pvno: 5
msg-type: krb-tgs-req (12)
▼ padata: sequence of PA-DATA
▼ PA-DATA PA-TGS-REQ
▼ req-body
kdc-options: ...
▼ sname: SEQUENCE
name-type: kRB5-NT-SRV-INST (2)
sname-string: MSSQLSvc/db01.corp.local:1433 ← SPN being requested
▼ etype: SEQUENCE
etype: eTYPE-ARCFOUR-HMAC (23) ← RC4 = KERBEROASTING INDICATOR
Kerberoasting detection in pcap:
→ Multiple TGS-REQ in rapid succession (5-50 in under 10 seconds)
→ Each requests a different SPN (different service accounts)
→ All use etype=23 (RC4) for the ticket encryption
→ All from the same source IP
Display filter for Kerberoasting:
kerberos.msg_type == 12 and kerberos.etype == 23
AS-REP Roasting (no pre-auth):
kerberos.msg_type == 10 (AS-REQ)
Look for AS-REQ with no PA-ENC-TIMESTAMP (pre-auth data missing)
The absence of PA-DATA padata-type 2 = DONT_REQUIRE_PREAUTH set
Q & A
Q: Wireshark isn't decoding my traffic as the right protocol. How do I force the correct dissector?
Wireshark assigns dissectors based on port numbers by default — port 80 = HTTP, port 443 = TLS, etc. If an application runs on a non-standard port, the packets show as raw TCP with no application-layer decoding. To force a specific dissector: (1) Right-click any packet in the session → "Decode As" → select the protocol from the dropdown (e.g., HTTP for a C2 server running on port 8888). This applies to all packets on that port for the current session. (2) Permanent decode-as rule: Analyze menu → "Decode As" → + → set port range and protocol. This persists in your Wireshark profile. (3) For TLS on non-443 ports, you need the Decode As + TLS session keys configured. Note: forced decoding means Wireshark applies the dissector even if the protocol doesn't match — malformed output means the traffic wasn't actually that protocol.