We are given a PCAPNG file with a bunch of USB packets. By scanning through the PCAP, I noticed that there appears to be a large amount of
URB_INTERRUPT packets after some initial configuration and setup. On a hunch, I immediately suspected either a USB keyboard or mouse due to the amount of data and the fact that all incoming packets were created from interrupts (i.e some kinda of slow I/O device driven by a human).
While looking at the packets, I initially assumed this was a keyboard as it would be straight forward to hide a flag in keyboard data. I tried the obvious choice and googled for some Python that already solved this problem and I came across this keyboard PCAP parser. I noticed that the offsets used in the file were not close to the size of the packets I was seeing, so I did some more research on USB HID devices and I came across this great page on USB mice packets.
The packet structure described here matched what I was seeing in the PCAP data. I confirmed this by looked for a USB descriptor packet from the device. I found the right packet at number 84 (below).
No. | Time | Source | Dest | Protocol | Length | Info ----+----------+--------+------+----------+--------+------------------------------ 84 | 6.505211 | 1.3.0 | host | USB | 46 | GET DESCRIPTOR Response DEVICE
The device descriptor decoding showed that this was definitely a mouse.
DEVICE DESCRIPTOR bLength: 18 bDescriptorType: 0x01 (DEVICE) bcdUSB: 0x0200 bDeviceClass: Device (0x00) bDeviceSubClass: 0 bDeviceProtocol: 0 (Use class code info from Interface Descriptors) bMaxPacketSize0: 8 idVendor: Logitech, Inc. (0x046d) idProduct: M90/M100 Optical Mouse (0xc05a) bcdDevice: 0x6300 iManufacturer: 1 iProduct: 2 iSerialNumber: 0 bNumConfigurations: 1
At this point, I modified the keyboard Python to extract out the mouse data which is in the binary format of
BYTE[Key State] BYTE[Signed X Offset] BYTE[Signed Y Offset]. With all of the mouse movements extracted, I needed a way to visualize this data. My first thought was to draw the mouse movements on a canvas with a pen (or turtle). I have experience with Python’s Image Library (PIL) so I immediately reached for that.
Using the X, Y, and key state, I came up with the code below to draw and display an image:
#!/usr/bin/env python # For2 - Google CTF 2016 by Grant for UFSIT # # Resources: # http://eleccelerator.com/tutorial-about-usb-hid-report-descriptors/ # https://stackoverflow.com/questions/13053443/drawing-a-line-on-an-image-with-pil # https://stackoverflow.com/questions/20060096/installing-pil-with-pip import binascii import dpkt import struct import sys from PIL import Image, ImageDraw # Start the pcap file parsing f = open(sys.argv, 'rb') pcap = dpkt.pcap.Reader(f) im = Image.new('RGBA', (1000, 1000), (0, 255, 0, 0)) points =  state =  # Then iterate over each USB frame for ts, buf in pcap: # We are interested only in packets that has the expected URB id urb_id = ''.join(reversed(buf[2:10])) if binascii.hexlify(urb_id) != 'fffffa80025896f0': continue data_length, = struct.unpack('<I', buf[0x17:0x17+4]) if data_length != 4: continue data = buf[0x1b:0x1b+4] keys = struct.unpack("B",data) X = struct.unpack("b", data) Y = struct.unpack("b", data) points.append((X, Y)) state.append(keys) cursor = (500, 500) draw = ImageDraw.Draw(im) for i,item in enumerate(points[1:]): x = item y = item cursorNew = (cursor+x, cursor+y) if state[i]: draw.line((cursor, cursor, cursorNew,cursorNew), fill=128) cursor = cursorNew im.show() #im.save("for2_key.bmp")
Here is what it produced: