Fetch the Flag CTF 2025 Write-Up: ClickityClack

Fetch the Flag CTF 2025 Write-Up: ClickityClack

Written by Kim Hallberg on Mar 4th, 2025 Views Report Post

For this challenge, we were given a PCAP file containing USB captures. Our goal was to analyze the captures and extract the flag — the description is as follows.

My friend said that he kept trying to message me the flag but it wouldn't work. He sent me a packet capture of his USB Bus to prove he was typing the flag, can you help me figure out what the flag is?

With our click.pcapng file in hand, we can fire up Wireshark to look through the USB Bus capture.

click-response-device.png

Filtering our search to devices we can see three devices, a Logitech G502 SE Hero Gaming Mouse, a Logitech G815 Mechanical Keyboard, and a USB hub.

From that and the challenge description of "message me the flag," we can safely deduce that our flag will be in the data stream from the keyboard and not any other device.

click-hid-data.png

And this is where I hit a road block, my knowledge of USB captures and USB HID in general at the time of the challenge was zero. It is still close to zero, so that meant it was time to research how to actually read the data.

After a fair amount research I came across this ctf-usb-keyboard-parser from TeamRocketIST.

gh repo clone teamrocketist/ctf-usb-keyboard-parser

So following along with their README I was able to extract the keystrokes using tshark by filtering for only the USB data from the keyboard.

tshark -r click.pcapng -Y 'usb.src == "7.2.1"' -Tfields -e usbhid.data > keystrokes.txt

Now we have a keystrokes.txt containing a list of bytes, but the keyboard parser expects a different format than what tshark returned, so as the README suggested, we can use sed to format the data.

cat keystrokes.txt | sed 's/../&:/g' > hid.txt

We can save the formatted data to hid.txt for later use. While formatting from this sed pattern isn't 100% correct, we have a trailing colon at the end of each line, it is nothing we have to worry about.

Our last step is to run usbkeyboard.py against hid.txt and fetch our flag. We aren't interested in anything other than our flag and we can use grep to only fetch that.

python3 usbkeyboard.py hid.txt | grep -o "flag{[[:alnum:]]*}"

And violá, we have now analyzed, researched, formatted and parsed a USB capture file to receive our message and fetch our flag.

flag{a3ce310e9a0dc53bc030847192e2f585}

This was a really fun forensic challenge, it felt overwhelming at first not being that familiar with Wireshark, only ever used it a few times with HTTP requests and had no knowledge of the USB protocol.

Despite that I managed to finish the challenge it time, I hope I retain something from this challenge. Only time will tell, maybe for Fetch the Flag 2026.

Comments (0)