Introduction
Recently while working on my own…admittedly slightly hacky UDP protocol I had a need to nose at it within Wireshark.
I started by capturing the raw UDP datagrams, tilting my head at the right angle and squinting at the bytes really hard. It worked….but I decided a custom Wireshark dissector plugin might be a better bet.
Mika’s Tech Blog includes an excellent in-depth series of posts on the subject which I followed, ending up with a working dissector. However If you’re like me (or future me), looking for a short example to get going read on.
Packet Source
To decode a packet we need some packets. Here’s some Python which generates and sends a simple datagram to your machine’s loopback address:
import socket
import struct
import time
try:
# Create socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Prepare and send datagrams until interrupted
counter = 0
payload_bytes = "The quick brown fox jumped over the lazy dog".encode()
print("Sending frames...")
while True:
# Pack new datagram, relying on struct.pack to truncate counter to the required size each time
datagram = struct.pack("<QBHL", int(time.time() * 1000), counter % 256, counter % 65536, counter % 4294967296) + payload_bytes
# Send datagram to localhost on port 65432
sock.sendto(datagram, ("127.0.0.1", 65432))
# Increment counter
counter += 1
# Nap time
time.sleep(0.01)
except KeyboardInterrupt:
pass
Wireshark Lua Dissector
Wireshark supports dissectors written in either C or Lua. For speed and ease, Lua wins.
Here’s a simple dissector for the datagrams being transmitted by the Python above:
-- declare protocol
simple_protocol = Proto("SimpleProtocol", "Example UDP protocol")
-- declare fields
timestamp = ProtoField.uint64("simple.timestamp", "timestamp", base.DEC)
field_a = ProtoField.uint8("simple.field_a", "field_a", base.DEC)
field_b = ProtoField.uint16("simple.field_b", "field_b", base.DEC)
field_c = ProtoField.uint32("simple.field_c", "field_c", base.DEC)
payload_bytes = ProtoField.bytes("simple.payload", "payload_bytes", base.NONE)
payload_str = ProtoField.string("simple.payload_str", "payload_str")
simple_protocol.fields = { timestamp, field_a, field_b, field_c, payload_bytes, payload_str }
function simple_protocol.dissector(buffer, pinfo, tree)
-- retrieve buffer length
length = buffer:len()
-- filter empty packets
if length == 0 then
return
end
-- Set protocol name
pinfo.cols.protocol = simple_protocol.name
-- Add protocol to tree
local subtree = tree:add(simple_protocol, buffer(), "Simple Protocol")
-- Add fields to tree
subtree:add_le(timestamp, buffer(0, 8))
subtree:add_le(field_a, buffer(8, 1))
subtree:add_le(field_b, buffer(9, 2))
subtree:add_le(field_c, buffer(11, 4))
subtree:add(payload_bytes, buffer(15, length - 15)) -- Remove header
subtree:add(payload_str, buffer(15, length - 15)) -- Remove header
end
-- Match protocol by UDP port
local udp_port = DissectorTable.get("udp.port")
udp_port:add(65432, simple_protocol)
Hint: If you’re data is in big endian format (network order), unlike my little endian data here, replace add_le with add when adding fields to the subtree.
Installing
Installation is as simple as dropping the Lua file into your Wireshark “Personal Lua Plugins” folder.
To locate it:
- Open Wireshark.
- Open “About Wireshark” dialog.
- On Linux / Windows goto “Help -> About Wireshark”
- On Mac goto “Wireshark -> About Wireshark”
- Change to “Folders” tab.
- Double click the location shown to open it.
- Drop your Lua file in this directory.
Here’s the “About Wireshark” dialog on my Linux machine as an example.

Using
Start a capture as usual and if by magic your newly defined protocol will be matched based on its UDP port number and decided based on the fields we defined.
As you add more fields / debug the “Reload Lua Plugins” option in the “Analyze” menu is super useful.
Here’s the “Simple Protocol” generated by the example Python above, being decoded by the example dissector above:

If you’ve got this far you’ll likely find the Wireshark Lua dissector reference page useful when adding additional fields.
Hope it helps!

Leave a Reply