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