Last active
March 24, 2025 05:51
-
-
Save masterex1000/ab9874b1d31763fc9e7993c174a7dfa7 to your computer and use it in GitHub Desktop.
A basic dissector that can decode pictochat beacons. Doesn't decode any messages.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| -- Pictochat Beacon Dissector for Wireshark | |
| -- References | |
| -- https://problemkaputt.de/gbatek-ds-wifi-nintendo-beacons.htm | |
| local is_enabled = true | |
| nifi_beacon_proto = Proto("NiFi_Beacon", "Nintendo DS NiFi Beacon") | |
| local f_oui_prefix = ProtoField.uint24("nifi.oui_prefix", "OUI", base.HEX) | |
| local f_oui_vendor = ProtoField.uint24("nifi.oui_vendor_code", "Vendor OUI Code", base.HEX) | |
| local f_stepping_offset = ProtoField.uint16("nifi.stepping_offset", "Stepping Offset", base.HEX) | |
| local f_video_sync = ProtoField.uint16("nifi.video_sync", "Video Sync", base.HEX) | |
| local f_fixed_command = ProtoField.uint16("nifi.fixed_command", "Fixed Value", base.HEX) | |
| local f_game_id = ProtoField.uint16("nifi.game_id", "Game ID", base.HEX) | |
| local f_stream_code = ProtoField.uint16("nifi.stream_code", "Stream Code", base.HEX) | |
| local f_data_length = ProtoField.uint8("nifi.data_length", "Data Length", base.DEC) | |
| local f_beacon_type = ProtoField.uint8("nifi.beacon_type", "Beacon Type", base.HEX) | |
| local f_cmd_data_size = ProtoField.uint16("nifi.cmd_data_size", "CMD Data Size", base.HEX) | |
| local f_reply_data_size = ProtoField.uint16("nifi.reply_data_size", "REPLY Data Size", base.HEX) | |
| local f_picto_fixed = ProtoField.uint16("nifi.pictochat.fixed", "Fixed Value", base.HEX) | |
| local f_picto_unknown = ProtoField.uint16("nifi.pictochat.unknown", "Unknown", base.HEX) | |
| local f_picto_room_number = ProtoField.uint8("nifi.pictochat.room", "Room Number", base.DEC) | |
| local f_picto_user_count = ProtoField.uint8("nifi.pictochat.users", "User Count", base.DEC) | |
| local f_picto_fixed_b = ProtoField.uint16("nifi.pictochat.fixed_b", "Fixed Value", base.HEX) | |
| nifi_beacon_proto.fields = { | |
| f_oui_prefix, | |
| f_oui_vendor, | |
| f_stepping_offset, | |
| f_video_sync, | |
| f_fixed_command, | |
| f_game_id, | |
| f_stream_code, | |
| f_data_length, | |
| f_beacon_type, | |
| f_cmd_data_size, | |
| f_reply_data_size, | |
| f_picto_fixed, | |
| f_picto_unknown, | |
| f_picto_room_number, | |
| f_picto_user_count, | |
| f_picto_fixed_b | |
| } | |
| function nifi_beacon_proto.dissector(buffer, pkt, root) | |
| local oui = buffer(0, 3):uint() | |
| local oui_vendor = buffer(3, 1):uint() | |
| if not (oui == 0x0009bf and oui_vendor == 0x00) then | |
| return | |
| end | |
| local subtree = root:add(nifi_beacon_proto, buffer()) | |
| pkt.cols.protocol = nifi_beacon_proto.name | |
| subtree:add(f_oui_prefix, buffer(0x00, 3)) | |
| subtree:add(f_oui_vendor, buffer(0x03, 1)) | |
| subtree:add(f_stepping_offset, buffer(0x04, 2)) | |
| subtree:add(f_stepping_offset, buffer(0x06, 2)) | |
| subtree:add_le(f_fixed_command, buffer(0x08, 4)) | |
| subtree:add_le(f_game_id, buffer(0x0c, 4)) | |
| subtree:add_le(f_stream_code, buffer(0x10, 2)) | |
| subtree:add_le(f_data_length, buffer(0x12, 1)) | |
| subtree:add(f_beacon_type, buffer(0x13, 1)) | |
| subtree:add_le(f_cmd_data_size, buffer(0x14, 2)) | |
| subtree:add_le(f_reply_data_size, buffer(0x16, 2)) | |
| -- Try to decode pictochat header | |
| if buffer(0x12, 1):le_uint() == 8 then | |
| local pictotree = subtree:add("Pictochat Header", buffer(0x18, 8)) | |
| pictotree:add_le(f_picto_fixed, buffer(0x18, 2)) | |
| pictotree:add_le(f_picto_unknown, buffer(0x1a, 2)) | |
| pictotree:add_le(f_picto_room_number, buffer(0x1c, 1)) | |
| pictotree:add_le(f_picto_user_count, buffer(0x1d, 1)) | |
| pictotree:add_le(f_picto_fixed_b, buffer(0x1e, 2)) | |
| end | |
| end | |
| -- Initialization routine | |
| function nifi_beacon_proto.init() | |
| end | |
| local tag_dissector_table = DissectorTable.get("wlan.tag.number") | |
| -- For whatever reason, executing the default dissector causes a stack overflow. | |
| -- Instead you'll just have to manually disable the plugin if you want to get | |
| -- any of the default dissectors for vendor specific types | |
| -- dissector = tag_dissector_table:get_dissector(221) | |
| if is_enabled then | |
| tag_dissector_table:add(221, nifi_beacon_proto) | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment