A Wireshark Lua Dissector for Fixed Field Length Protocols, (Mon, Jun 3rd)

Category :

SANS Full Feed

Posted On :

I developed a Wireshark dissector in Lua to parse binary protocols (over TCP) that are composed of fields with fixed lengths. I got this idea while taking a SANS ICS training: for protocol reversing, it would be useful to have a dissector where I can configure the fields (length, type, name, …).

As an example, I’m using a packet capture of a demo protocol for firmware upload (didactic).

The format of the protocol data unit (PDU) looks like this:

Byte 1: the function of the PDU (0x10 start upload, 0x11 upload, 0x12 end upload)
Byte 2: the direction (0 from client to server, 1 from server to client)
Byte 3 and 4: a PDU counter for uploads, it’s a little-endian integer
Byte 5 and 6: the length of the uploaded data, it’s a little-endian integer
Bytes 7 and following: the uploaded data

Command-line arguments are provided to configure the Lua dissector to parse this traffic:

“c:Program FilesWiresharkWireshark.exe” -X lua_script:fl-dissector.lua -X lua_script1:port:50500 -X lua_script1:protocolname:firmware -X lua_script1:fieldlengths:1:B,1:B,2:L,2:L -X lua_script1:fieldnames:Function,Direction,Counter,DataLength,Data capture-firmware-upload.pcapng

“-X lua_script:fl-dissector.lua” loads dissector fl-dissector.lua in Wireshark.

“-X lua_script1:port:50500” provides a port:50500 option value to the dissector. This specifies the TCP port (50500) of the traffic that should be dissected.

“-X lua_script1:protocolname:firmware” specifies the name of the protocol.

“-X lua_script1:fieldlengths:1:B,1:B,2:L,2:L” specifies the field lengths: 1 byte, 1 byte, 2 bytes and 2 bytes. The 2 bytes fields are little-endian integers (:L).

“-X lua_script1:fieldnames:Function,Direction,Counter,DataLength,Data” specifies the names of the fields.

Configured like this, the protocol “firmware” is added to Wireshark and used for dissecting traffic over TCP port 50500:

Once the dissector is defined, it can be used to filter traffic. For example, in the above screenshot, I use display filter “firmware” to limit the view to this firmware protocol.

I can even use tshark to extract the uploaded firmware. For this, I switch to tshark:

“c:Program FilesWiresharktshark.exe” -X lua_script:fl-dissector.lua -X lua_script1:protocolname:firmware -X lua_script1:port:50500 -X lua_script1:fieldlengths:1,1,2,2 -X lua_script1:fieldnames:Function,Direction,Counter,DataLength,Data -r capture-firmware-upload.pcapng -Y “(firmware.Function == 0x11) && (firmware.Direction == 0)” -e firmware.Data -Tfields

The arguments for the dissector are the same. I use a display filter (-Y “(firmware.Function == 0x11) && (firmware.Direction == 0)”) to filter for PDUs that upload the firmware (function == 0x11) to the server (direction == 0). I configure tshark to just output the value of field data as hexadecimal (-e firmware.Data -Tfields). This is the result:

Next, I convert this hexadecimal data to binary with my tool hex-to-bin.py, and use another tool (file-magic.py) to try to identify the uploaded data:

It is a ZIP file, this can be confirmed with my zipdump.py tool:

I created this packet capture file of a firmware upload to an IoT device for didactic purposes, e.g., to explain a process of reverse engineering a binary network protocol.

If you want to know more about this, take a look at my blog post “Reversing A Network Protocol” and YouTube video “Reversing A Network Protocol“.


Didier Stevens
Senior handler

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.