diff options
-rwxr-xr-x | reference/arm64/snowcast_control | bin | 1873112 -> 1881144 bytes | |||
-rwxr-xr-x | reference/arm64/snowcast_listener | bin | 1544472 -> 1551576 bytes | |||
-rwxr-xr-x | reference/arm64/snowcast_server | bin | 2004920 -> 2078616 bytes | |||
-rw-r--r-- | util/snowcast-dissector/README.md | 68 | ||||
-rw-r--r-- | util/snowcast-dissector/cs168_snowcast.lua | 107 |
5 files changed, 175 insertions, 0 deletions
diff --git a/reference/arm64/snowcast_control b/reference/arm64/snowcast_control Binary files differindex 0f2ceaf..4336ed0 100755 --- a/reference/arm64/snowcast_control +++ b/reference/arm64/snowcast_control diff --git a/reference/arm64/snowcast_listener b/reference/arm64/snowcast_listener Binary files differindex 3991c31..0ddb872 100755 --- a/reference/arm64/snowcast_listener +++ b/reference/arm64/snowcast_listener diff --git a/reference/arm64/snowcast_server b/reference/arm64/snowcast_server Binary files differindex 587da32..5d9a380 100755 --- a/reference/arm64/snowcast_server +++ b/reference/arm64/snowcast_server diff --git a/util/snowcast-dissector/README.md b/util/snowcast-dissector/README.md new file mode 100644 index 0000000..a62522e --- /dev/null +++ b/util/snowcast-dissector/README.md @@ -0,0 +1,68 @@ +# CS1680 Snowcast Dissector + +THis directory contains a dissector (also known as a decoder) for the Snowcast +protocol implementation for CS168. + +## Installation Instructions + +The dissector is provided as a Lua script in this directory. For security +reasons, Wireshark does not run Lua scripts when run as root--therefore, you +must ensure that you are using Wireshark as your local user, not with root or +sudo. To run wireshark as a standard user, make sure your user is added to the +`wireshark` group. If you are using the provided VM, the the vagrant user is +already in the wireshark group. However, if you are running Wireshark on your +own system, you will need to configure this yourself. + +Once you have Wireshark running as your user. Add the dissector to Wireshark, +by copying the script into your plugins directory. + +To do this: + + 1. Run wireshark as your user (**not with root or sudo**). + 2. Open Wireshark's Help menu and select "About Wireshark". + 3. In the folders tab, find the entry "Personal Lua Plugins". For example: + `~/.config/wireshark/plugins` + 4. Copy the script to this directory (if it doesn't exist, create it) and + restart wireshark + 5. Open the "About Wireshark" window again and look in the Plugins tab. You + should now see cs168_rip.lua in the list of plugins. + +## Using the dissector + +_To make sure your dissector is working, please run the Snowcast reference +binaries_ + +Wireshark will automatically invoke the Snowcast dissector when it encounters a +TCP packets on port 1680. This means that if you start the Snowcast server on +port 1680, TCP packets on port 1680 will automatically be decoded as Snowcast +commands and replies. + +To use the Snowcast dissector with other port numbers we can instruct wireshark +to interpret TCP packets on a given port as Snowcast commands and responses. +We can tell wireshark to do this using Wireshark's "User-Specified Decodes" +feature: + +1. Run your binaries and to start capturing packets. You should be capturing + packets on the loopback interface. +2. Find a TCP packet related to this assignment and select it. These packets + will have a destination and source port number. One of these port numbers + should be the port number you selected when starting up the Snowcast server. +3. Right click on the TCP packet and select "Decode As..." +4. Double click "(none)" under "current" and select CS168SNOWCAST. + +Wireshark should no update and decode the TCP packets with your specified port +number as Snowcast commands and replies. + +If you do not see Snowcast commands and replies, check your "Decode As..." rule +from step 4. If you still do not see Snowcast commands and replies, make sure +that the plugin is loaded in the help menu. + +### Disclaimer + +The steps listed above will invoke the decoder only on a single TCP port. You +should repeat the steps above each time you change TCP ports + +## Feedback + +If you have questions or encounter any issues with the decoder, please post on +EdStem or see the course staff for help. diff --git a/util/snowcast-dissector/cs168_snowcast.lua b/util/snowcast-dissector/cs168_snowcast.lua new file mode 100644 index 0000000..511aa59 --- /dev/null +++ b/util/snowcast-dissector/cs168_snowcast.lua @@ -0,0 +1,107 @@ +-- CS168 Snowcast Protocol Dissector + +snowcast_protocol = Proto("CS168Snowcast", "CS168 Snowcast Protocol") + +message = ProtoField.uint8("cs168snowcast.messsage_type", "messageType", base.DEC) + +-- HELLO fields +udp_port = ProtoField.uint16("cs168snowcast.udp_port", "udpPort", base.DEC) +-- SET_STATION fields +station_number = ProtoField.uint16("cs168snowcast.station_number", "stationNumber", base.DEC) +-- WELCOME fields +num_stations = ProtoField.uint16("cs168snowcast.num_stations", "numStations", base.DEC) +-- ANNOUNCE fields +song_name_size = ProtoField.uint8("cs168snowcast.song_name_size", "songnameSize", base.DEC) +song_name = ProtoField.string("cs168snowcast.song_name", "songname") +-- INVALID_COMMAND fields +reply_string_size = ProtoField.uint8("cs168snowcast.reply_string_size", "replyStringSize", base.DEC) +reply_string = ProtoField.string("cs168snowcast.reply_string", "replyString") + +snowcast_protocol.fields = { + message, + udp_port, + station_number, + num_stations, + song_name_size, + song_name, + reply_string_size, + reply_string +} + +function snowcast_protocol.dissector(buffer, pinfo, tree) + length = buffer:len() + if length == 0 then return end + + pinfo.cols.protocol = snowcast_protocol.name + + local subtree = tree:add(snowcast_protocol, buffer(), "Snowcast Protocol Data") + + local packet_len = buffer:reported_length_remaining() + + local message_num = buffer(0, 1):uint() + local message_name = get_message_name(message_num) + + -- Add command ID and name + subtree:add(message, buffer(0, 1)):append_text(" (" .. message_name .. ") ") + + -- Clear any existing info in the info column so the TCP stuff info isn't in the way + pinfo.cols.info = "" + + pinfo.cols.info:append("Snowcast " .. message_name) + + if message_num == 0 then + -- Handling HELLO command + local udpPort = buffer(1, 2):uint() + subtree:add(udp_port, buffer(1, 2)) + pinfo.cols.info:append(" (UDP Port: " .. udpPort .. ") ") + elseif message_num == 1 then + -- Handling SET_STATION command + local stationNumber = buffer(1, 2):uint() + subtree:add(station_number, buffer(1, 2)) + pinfo.cols.info:append(" (Station Number: " .. stationNumber .. ") ") + elseif message_num == 2 then + -- Handling WELCOME reply + local numStations = buffer(1, 2):uint() + subtree:add(num_stations, buffer(1, 2)) + pinfo.cols.info:append(" (Station Number: " .. numStations .. ") ") + elseif message_num == 3 then + -- Handling ANNOUNCE reply + local songnameSize = buffer(1, 1):uint() + subtree:add(reply_string_size, buffer(1, 1)) + + local songname = buffer(2, songnameSize):string() + subtree:add(reply_string, buffer(2, songnameSize)) + + pinfo.cols.info:append(" (Song Name [" .. songnameSize .. " bytes]: " .. songname .. ") ") + elseif message_num == 4 then + -- Handling INVALID_COMMAND reply + local replyStringSize = buffer(1, 1):uint() + subtree:add(reply_string_size, buffer(1, 1)) + + local replyString = buffer(2, replyStringSize):string() + subtree:add(reply_string, buffer(2, replyStringSize)) + + pinfo.cols.info:append(" (Reply String [" .. replyStringSize .. " bytes]: " .. replyString .. ") ") + end +end + +function get_message_name(message_num) + local message_name = "UNNOWN" + + if message_num == 0 then + message_name = "HELLO" + elseif message_num == 1 then + message_name = "SET_STATION" + elseif message_num == 2 then + message_name = "WELCOME REPLY" + elseif message_num == 3 then + message_name = "ANNOUNCE REPLY" + elseif message_num == 4 then + message_name = "INVALID_COMMAND REPLY" + end + + return message_name +end + +local tcp_port = DissectorTable.get("tcp.port") +tcp_port:add(1680, snowcast_protocol) |