Teaser Dragon CTF 2019 - PlayCAP
Given an on-screen keyboard and a Nintendo Switch Pro Controller USB traffic capture in pcapng format, determine what was typed.
Attempt #1: opening the pcapng file in Wireshark, skimming the HID spec and trying to understand what is going on. The capture consists of several
According to the spec, the
Here the luck ends. According to the descriptor, report 0x30 should start with 10 bits corresponding to button states. In reality it starts with some kind of timestamp byte.
Attempt #2: dumping
Attempt #3: googling for Nintendo Switch Pro Controller reversing topics, finally finding the proposed Linux Kernel patch, which contains:
Hey, that's our goddamn timestamp. And the button statuses. Why doesn't this correspond to the HID Report?!
Writing a small python script that tracks bit flips and correlating its output with the keyboard confirms that
Using this knowledge to update the script to also track x/y coordinates reveals the flag.
Other writeups:
Lessons learned:
Attempt #1: opening the pcapng file in Wireshark, skimming the HID spec and trying to understand what is going on. The capture consists of several
GET DESCRIPTOR
s followed by tons of URB_INTERRUPT
s.According to the spec, the
HID Report
descriptor contains, among other things, the formats of reports sent via interrupt mechanism. The following observations confirm this:- All report identifiers are also the first bytes of
URB_INTERRUPT
payloads - Almost all
URB_INTERRUPT
s contain report 0x30, which is related to button states
Here the luck ends. According to the descriptor, report 0x30 should start with 10 bits corresponding to button states. In reality it starts with some kind of timestamp byte.
Attempt #2: dumping
URB_INTERRUPT
payloads using pyshark and trying to figure out what byte means what. No luck - bits appear to change randomly.Attempt #3: googling for Nintendo Switch Pro Controller reversing topics, finally finding the proposed Linux Kernel patch, which contains:
> +struct switchcon_input_report { > + u8 id; > + u8 timer; > + u8 bat_con; /* battery and connection info */ > + u8 button_status[3];
Hey, that's our goddamn timestamp. And the button statuses. Why doesn't this correspond to the HID Report?!
Writing a small python script that tracks bit flips and correlating its output with the keyboard confirms that
switchcon_input_report
does indeed correctly describe the packet format. It takes a few minutes to guess which bit corresponds to which button without looking at the spec (ain't trusting it no more).Using this knowledge to update the script to also track x/y coordinates reveals the flag.
Other writeups:
- https://ctftime.org/writeup/16575
- https://github.com/mkorman9/dragonsectorteaser2019/tree/master/PlayCAP
- https://hxp.io/blog/59/Teaser-Dragon-CTF-2019-PlayCAP-writeup/
Lessons learned:
- Don't blindly trust what you think the spec is saying
- Don't be shy to google a little bit more