USB PCAP Forensics: Graphics Tablet (NSEC CTF 2021 Writeup, Part 2/3)
For this second challenge, we were given a different PCAP which can be found here.
Goldsmiths’ Guild Part 2
I have heard that you have successfully gotten access into the Goldsmiths’ Guild. We’ll now need to take that covert action to the next step. Good luck.
The lobby is a small chamber with a second locked door and a desk on its side.
You hear from the other side of the door: “You need to sign the certificate”.
Upon inspection, you see a screen that the voice called the “certificate”. You find a jack and you plug your sniffer on it before leaving the guild.
You obtain Signatures Captures and go analyze them.
Flag 1: What are the vendor and the product name of the USB device? Format: flag-usb_[vendor][product]
Vendor hint: do not add Ltd., inc., corp., etc[/i]
Flag 2: Decode the device input.
Note: If you have not read part 1, it would be a good idea to do so, as I will not repeat explanations that overlap with it.
Exploring the PCAP
As with last time, let’s do a bit of exploration to see what kind of data we’re dealing with. Obviously, it’s another USB PCAP. We have more packets (~4400) that span over ~60 seconds. Finally, we see that there are bytes in the “HID Data” column:
The beginning of the PCAP also looks the same as part 1:
Great, so let’s look at the 2nd GET DESCRIPTOR Response DEVICE:
By googling, we find out that this device is a graphics tablet. Cool!
Flag 1: flag-usb_wacom_CTE-440
Since we saw earlier that this is also an HID device, let’s look at the GET DESCRIPTOR Response CONFIGURATION packet:
So it turns out that a graphics tablet is simply a fancy mouse from the perspective of the host machine.
Extracting and understanding the data
Let’s use the same technique as with part 1. Simple and effective.
By googling “USB mouse HID”, I found this very helpful link that describes the format of the mouse data:
This information is very straightforward. We need to extract three bytes to reconstruct what was “written” (1). I assumed that when the left button is pressed (2), it behaves like MSPaint and something is drawn. Notice in (3) that a mouse does not set the absolute position of the cursor, it moves it relative to its current position.
Using the same trick as in part 1, we see that only the 2nd, 3rd and 4th bytes seem to change from packet to packet. These are the 3 bytes mentionned in (1). Let’s extract them using Cyberchef:
Now, onto the code!
Recovering what was written
For this part, I used the python-Pillow library to create an image from scratch. The code is pretty self-explanatory:
from PIL import Image
mouse_events = [(0x80, 0x01, 0xfd), (0x80, 0x01, 0xfe), ... (0x80, 0xff, 0xfa)]
# Make the image big because we don't know how long the message is
img = Image.new('RGB', (10000, 10000), color='white')
canvas = img.load()
# Start the cursor in the middle of the canvas
mouse_x = 5000
mouse_y = 5000
for data in mouse_events:
# Get the left mouse button status
left_button_pressed = data & 0b00000001
# Get the mouse movement in x and y
x_offset = int.from_bytes(data[1:2], "big", signed=True)
y_offset = int.from_bytes(data[2:3], "big", signed=True)
mouse_x += x_offset
mouse_y += y_offset
# These two for loops are to make the pixels thicker
for i in range(5):
for j in range(5):
# Write a black pixel on the canvas
canvas[round(mouse_x) + i, round(mouse_y) + j] = (0, 0, 0)
# Save the image to disk
We run this script, open “final.png” and zoom in to see this:
Flag 2: flag-sir_mon3y_l4und3ring
This was also a great challenge that built on what we learned in part 1, but required a little bit more fancy parsing and using an image canvas to get the flag.
Stay tuned for part 3!