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).


Wireshark Dissector Tutorial [Practical Examples]


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".

For example:

  • When the first byte is 0x01, it means the client is questioning the server.
    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. 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

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.

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.


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")

Wireshark Dissector Tutorial [Practical Examples]


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)

Wireshark Dissector Tutorial [Practical Examples]


Step-3: Register your fields.

ulive_protocol.fields = {msg_type,question_type,answer_type}

Wireshark Dissector Tutorial [Practical Examples]

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 .. ")")
			mtype_str = "Other question?" 
			subtree:add_le(question_type,buffer(1,1)):append_text(" (" .. mtype_str .. ")")
	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 .. ")")
			mtype_str = "No, the service is down" 
			subtree:add_le(answer_type,buffer(1,1)):append_text(" (" .. mtype_str .. ")")


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 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"
    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
    host_ip = socket.gethostbyname('') # 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")
s.connect((host_ip, port))
s.send(bytes.fromhex(MESSAGE1)) # it will test MESSAGE1


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))
print("socket is listening")

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


Adding the dissector to Wireshark

Step-1: Navigate to "Help → About Wireshark" menu.

Wireshark Dissector Tutorial [Practical Examples]


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.

Wireshark Dissector Tutorial [Practical Examples]


Paste your Lua file in this directory.

Wireshark Dissector Tutorial [Practical Examples]


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

Wireshark Dissector Tutorial [Practical Examples]


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



Didn't find what you were looking for? Perform a quick search across GoLinuxCloud

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can either use the comments section or contact me form.

Thank You for your support!!

Leave a Comment