This challenge consists of a capture file containing USB packet. We notice that one of the USB device floods most of the capture with several hundred packets per second. The device uses the address 12, and hence can be filtered using:
usb.device_address == 12
The first packet sent by this device shows it is a mouse.
Then, the flooding packets are likely to be mouse movements and clicks that we need to replay to find the key. All of those packets contain 4 bytes of leftover data, likely to contain the mouse updates.
This website helped understanding how to read the mouse input. It seems that the first byte contains a few flags (negative movement, buttons etc.), the following two contain the X and Y movement, and the fourth the wheel movement. Though it is worth noting that in our case, the first byte is either 0x00 or 0x01, and the fourth is always 0x00. This means that either the mouse never goes backward, or in our case the second and third bytes contain signed values.
Having an idea on how to read the data, it is time to process our packets. To use the data easily in python, I've filtered the interesting packets by updating the previous filter as:
usb.device_address == 12 && usb.endpoint_number.endpoint == 1
Then, in wireshark, I exported the data of the selected packets as a C array. By doing a few search and replace, I had 15k+ arrays ready to use in python. Some of them were emmited by the mouse, others by the USB hub. I filtered them by looking at one particular byte that was different depending on the source.
Another solution would have been to filter using the size of the packet, as only packets from the mouse have those extra 4 bytes. Now, we can write simple functions to read the data from the mouse, taking into account that the packet itself contains 65 bytes, and assuming we have signed movements:
Using those functions, we can go through all the packets, and plot the movements, as well as dots where each click happens. Here is the result:
This looks a lot like clicks happening on a on-screen keyboard! So here we can either manually follow the mouse movements, or write an ugly function to automatize that. I went for the second by first sorting the y positions of the clicks and sort them by row.
I then did similar functions for each row (you can see the functions by downloading my solution but I won't paste the functions here). Finally, the only thing left was to print the corresponding character each time the mouse button is clicked to obtain the key for that challenge:
the quick brown fox jumps ovver the lazy dog thekeyisiheardyoulikedsketchyetchingglastyear
We can see that some letters are repeated (ovver, etchingg), these are due to the mouse button being pressed over two packets and being interpreted as two clicks by my solution, these can be ignored to get the final flag:
Thanks a lot to motsu and tinfoil for their help with this challenge!