Download as pdf or txt
Download as pdf or txt
You are on page 1of 5

Wireshark Dissector Tutorial [Practical Examples]

Getting started with Wireshark Dissector


A Wireshark dissector is simply a decoder, which is interesting in a specific type of traffic. Once it finds the traffic, it
interprets the payload. In short, it is a protocol parser.

Wireshark dissectors can be useful when you are working with a custom protocol that Wireshark doesn’t already have a
dissector for.  I will create a dissector for the following payload (the data).

The first 3 packets belong to the TCP 3-way handshaking. After the TCP connection has established, the client sends some
data that Wireshark’s dissectors do not understand in packet number 4.

We will create a simple protocol and write a dissector for it. The protocol is based on a request and response. With this
protocol a client can ask the server if the service on the server is up or not. The server responses back, informing the
service is up or down.

For sake of simplicity, we will create 2 bytes protocol, which will be working in client and server architecture. The client will
be able to query the service status on the server. The server will response the client with a relevant answer. The first byte
is used to distinguish whether the message type is a "question" or an "answer". The second byte will be used for the
content of the "answer" or the  "question".
ALSO READ: Troubleshooting TLS Failures using Wireshark

For example:

When the first byte is 0x01, it means the client is questioning the server.

1. 1. When the second byte is 0x01, it means the client is asking if the service up or not.
2. When the second byte is other than 0x01, it means the client is asking some other question.

When the first byte is 0x02, it means the server is answering the client.

1. 1. When the second byte is 0x01, it means "Yes, the service is up"
2. When the second byte is 0x02, it means "No, the service is down"
3. When the second byte is other than 0x01 and 0x02, it means the answer is something else.

Below I created 4 message types.

MESSAGE1 = "0101" → "Is the service up?"


MESSAGE2 = "0102" → "Other question?"
MESSAGE3 = "0201" → "Yes, the service is up"
MESSAGE4 = "0202" → "No, the service is down"

Different types of Dissectors


There are also different types of dissectors that can be useful for different tasks.

There are dissectors that run after all the other dissectors have run, giving the programmer access to fields defined in
other dissectors. These are referred to as post-dissectors

A chained dissector is similar to the post-dissector in that it runs after other dissectors so that you can access the fields
for other dissectors.
ALSO READ: 16 Linux ip command examples to configure network interfaces (cheatsheet)

The difference is that a chained dissector doesn't run against every packet, only those packets that are handled by the
dissector off of which you are chaining. Chained dissectors are handy for extending an existing dissector without having to
rewrite it completely, whereas post-dissectors are useful for adding a new dissector that provides additional context based
on what other fields are set.

Different ways to write Wireshark Dissectors


There are 3 ways commonly used ways to write your own dissector:

C/C++ based dissectors


Most of Wireshark dissectors are written in C/C++ programing language. It is fast and efficient but It requires a full
fledged development environment.

Wireshark Generic Dissector


In this method, you describe your data using a specific format and save it in text file(s). Wireshark reads the protocol
definitions from the file(s). It is similar to a programming language. Interpreted text files are simple to use but slow for
dissecting packets. Wireshark Generic Dissector does not require a development environment. The only thing you need is a
text editor.

Scripting language based dissectors

This is a very common method used. Wireshark has a Lua implementation that makes it easy for people who are
unfamiliar with C to write dissectors. Lua is a scripting language in that Lua code is read from a plain text script/source file
and then executed by the Lua interpreter—a compiled executable itself—dynamically at runtime. Another word for scripting
language is interpreted or managed language. Because the code is interpreted at runtime, and generally all memory
access is managed by the runtime, Lua, in this case, is the interpreter.

 
ALSO READ: Kerberos Authentication Packet Analysis with Wireshark

Creating Dissectors for Wireshark


Although I am not familiar with Lua, I will use Lua for this article. It takes a little time to look at its syntax.

Step-1: Declare the protocol. My protocol short name (display filter name) will be "ulive.lua". The long name in the
protocol tree will be "Service State Protocol".
ulive_protocol = Proto("ulive",  "Service State Protocol")

Step-2: Declare the fields with their types. We will have 3 fields which are:

MessageType: It show if the packet is a request/question or response/answer.


Question: It shows the question type.
Answer: It shows the answer type.

msg_type =ProtoField.uint8("ulive.MessageType","MessageType",base.DEC)
question_type =ProtoField.uint8("ulive.Question","Question",base.DEC)
answer_type =ProtoField.uint8("ulive.Answer","Answer",base.DEC)
 

Step-3: Register your fields.


ulive_protocol.fields = {msg_type,question_type,answer_type}

The dissector must register its data fields with Wireshark so that Wireshark knows how to display them. If you do not
register the fields, you will get the error above.

Step-4: Create a dissection function which takes 3 parameters:

buffer: It is the data on the top of TCP. The dissector will walk through the buffer of bytes.
pinfo: It contains the data about the packet.
tree: The tree on which we append our subtree.

function ulive_protocol.dissector(buffer, pinfo, tree)


-- set the protocol column
pinfo.cols.protocol = ulive_protocol.name;
-- create the protocol item tree
subtree = tree:add(ulive_protocol,buffer())
-- get the first byte for distinguishing the message type
mtype = buffer(0,1):le_uint()
-- now, do the comparisons
if mtype == 1 then -- if the packet is a question
mtype_str = "Question"
subtree:add_le(msg_type,buffer(0,1)):append_text(" (" .. mtype_str .. ")")
qtype = buffer(1,1):le_uint()
-- find the question type
if qtype == 1 then
mtype_str = "Is the service up?"
subtree:add_le(question_type,buffer(1,1)):append_text(" (" .. mtype_str .. ")")
else
mtype_str = "Other question?"
subtree:add_le(question_type,buffer(1,1)):append_text(" (" .. mtype_str .. ")")
end
end
if mtype == 2 then -- if the packet is an aswer
mtype_str = "Answer"
subtree:add_le(msg_type,buffer(0,1)):append_text(" (" .. mtype_str .. ")")
atype = buffer(1,1):le_uint()
-- find the answer type
if atype == 1 then
mtype_str = "Yes, the service is up"
subtree:add_le(answer_type,buffer(1,1)):append_text(" (" .. mtype_str .. ")")
else
mtype_str = "No, the service is down"
subtree:add_le(answer_type,buffer(1,1)):append_text(" (" .. mtype_str .. ")")
end
end
end

 
ALSO READ: Analyze TCP Receive Window with Wireshark [Step-by-Step]
Step-5: Specify which port and protocol will ve used. I will use TCP and and port 12345. When Wireshark come across a
packet with these parameters, it will use my dissector.
local tcp_port = DissectorTable.get("tcp.port")
tcp_port:add(12345,ulive_protocol)

TCP client code


We need to create some data to test our dissector. For this purpose, I coded a pretty simple client and server in Python.
import socket
import sys
# define the test message types
MESSAGE1 = "0101" # "Is the service up?"
MESSAGE2 = "0102" # "Other question?"
MESSAGE3 = "0201" # "Yes, the service is up"
MESSAGE4 = "0202" # "No, the service is down"
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("Socket has successfully created")
except socket.error as err:
print("socket creation has failed with error %s" % (err))

port = 12345
try:
host_ip = socket.gethostbyname('192.168.1.5') # server ip address or host name
except socket.gaierror:
# it fails to resolve the host name
print("there has been an error resolving the host")
sys.exit()
s.connect((host_ip, port))
s.send(bytes.fromhex(MESSAGE1)) # it will test MESSAGE1
s.close()

TCP server code


import socket
# define the test message types
MESSAGE1 = "0101" # "Is the service up?"
MESSAGE2 = "0102" # "Other question?"
MESSAGE3 = "0201" # "Yes, the service is up"
MESSAGE4 = "0202" # "No, the service is down"
s = socket.socket()
print("Socket has successfully created")
port = 12345
s.bind(('', port))
print("socket has binded to %s" % (port))
s.listen(5)
print("socket is listening")

while True:
c, addr = s.accept()
print('Got connection from', addr)
#data = c.recv(1024)
c.send(bytes.fromhex(MESSAGE4))
c.close()

Adding the dissector to Wireshark


Step-1: Navigate to "Help → About Wireshark" menu.
ALSO READ: How to check if ISP is blocking website [Wireshark]

Step-2: A window appears, then click "Folder" tab and you will see a list of paths. Click on "Personal Lua Plugins". If you
have not created the directory before, click "Yes" button to create the directory.
 

Paste your Lua file in this directory.

Step-3: Reload your Wireshark to activate the dissector, then open packets you captured or my packets below. You should
see something like below.

Final thoughts
Wireshark may not dissect a proprietary protocol if you use one of them in your enterprise. With help of Lua, you can
create your own dissector and easily integrate it with Wireshark.

Further Reading
Dissectors

You might also like