TLDR Wireshark UDP Dissector

|

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:

  1. Open Wireshark.
  2. Open “About Wireshark” dialog.
    • On Linux / Windows goto “Help -> About Wireshark”
    • On Mac goto “Wireshark -> About Wireshark”
  3. Change to “Folders” tab.
  4. Double click the location shown to open it.
  5. Drop your Lua file in this directory.

Here’s the “About Wireshark” dialog on my Linux machine as an example.

Wireshark About Dialog

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:

Simple Protocol Dissector in Action

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

Wireshark Lua Reference

Hope it helps!

Was this article helpful?
YesNo
,

Leave a Reply

Your email address will not be published. Required fields are marked *