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
blog.DidierStevens.com
(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.