This weekend, I participated in the Google CTF. This CTF was a lot of fun, forcing participants to learn lots of Google-specific technologies, providing a wide range of challenging content for people.
One particularly interesting challenge was For2: the challenge started out with a pcap file, which turned out to be USB traffic:
Upon closer inspection, two things were of interest:
- In packet 84, a response to a GET DESCRIPTOR request, the device states that it’s a Logitech M90/M100 Mouse
- Each data packet (98 onwards), there are four extra bytes of data at the end of the packet.
My first thought was that this represented some manner of mouse movement, which would “draw out” the flag, as if the user was tracing it with his/her mouse. After fruitlessly reading through the URB_INTERRUPT dissection in Wireshark, my initial approach was to trawl through the M90/M100 driver source code to understand the format.
Fortunately, computer peripherals generally need to be compatible: that is, as a rule, you should be able to plug a mouse in and have it work, without the need to install anything (especially not “cloud-based drivers”. Holy fucking shit Razer, what the fuck bro).
Instead, I took a look at the OSDev Wiki article on Mouse Input, which provided a really concise description of the extra 4 bytes in URB_INTERRUPT packets from mouse movement:I extracted the packet data using tshark:
tshark -r "capture.pcapng" -T fields -e usb.capdata -Y "usb.data_len == 4" >> usbdata.txt
From here, a quick Python script can plot out the movements of the user’s mouse into a bitmap, using the lovely Python Imaging Library, revealing the flag:
Note that my initial script had a ton of mouse noise – on further inspection of the URB_INTERRUPT data, many of the packets had the first byte of payload data as 0: this indicated that the user was not clicking anything. By discarding these packets, we get a clean render.
Thanks to Google for creating a great CTF with a variety of interesting puzzles – looking forward to next year’s!