Dev-usbmon
Description
Learn how to capture USB traffic and read it, using Wireshark and Tshark.
Useful resources:
- https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf
- https://wiki.wireshark.org/CaptureSetup/USB
- https://ctf-wiki.github.io/ctf-wiki/misc/traffic/protocols/USB/
Capture USB traffic
Identify USB interface
The lsusb command will list USB devices and reveals the bus number:
$ lsusb Bus 003 Device 002: ID 8087:8000 Intel Corp. Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 001 Device 002: ID 8087:8008 Intel Corp. Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 002 Device 004: ID 138a:0017 Validity Sensors, Inc. VFS 5011 fingerprint sensor Bus 002 Device 003: ID 046d:c52b Logitech, Inc. Unifying Receiver Bus 002 Device 005: ID 8087:07dc Intel Corp. Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Now, if you have a look at the /dev directory, you'll notice several usbmon{N} interfaces, where N is the bus number
$ ll /dev/ | grep usb drwxr-xr-x 2 root root 80 Mar 23 15:44 usb crw------- 1 root root 241, 0 Mar 23 17:04 usbmon0 crw------- 1 root root 241, 1 Mar 23 17:04 usbmon1 crw------- 1 root root 241, 2 Mar 23 17:04 usbmon2 crw------- 1 root root 241, 3 Mar 23 17:04 usbmon3 crw------- 1 root root 241, 4 Mar 23 17:04 usbmon4
Capture USB traffic
To dump USB traffic on Linux, you need the usbmon kernel module:
# modprobe usbmon
Start wireshark as root and you'll see the usbmon interfaces:
Read USB traffic
Keyboard
The data is composed of 8 bytes.
- The 1st byte indicates if the pressed key is upper (0x02) or lower (0x00)
- The 3rd byte indicates the key pressed (refer to [1], section #10 Keyboard/Keypad Page (0x07) for the list of codes)
Let's assume you have captured a USB traffic from a USB keyboard in a file named keyboard.pcap. You can extract the relevant data using tshark as follows:
$ tshark -r keyboard.pcap -2 -R "usb.capdata!=\"\"" -T fields -e usb.capdata > keyboard.txt
You can then use the following python script to read keys from this text file.
#!/usr/bin/python3
newmap = { 1: '[ErrorRollOver]', 2: '',#[LSHIFT]', 4: 'a', 5: 'b', 6: 'c',
7: 'd', 8: 'e', 9: 'f', 10: 'g', 11: 'h', 12: 'i', 13: 'j', 14: 'k',
15: 'l', 16: 'm', 17: 'n', 18: 'o', 19: 'p', 20: 'q', 21: 'r', 22: 's',
23: 't', 24: 'u', 25: 'v', 26: 'w', 27: 'x', 28: 'y', 29: 'z', 30: '1',
31: '2', 32: '3', 33: '4', 34: '5', 35: '6', 36: '7', 37: '8', 38: '9',
39: '0', 40: '[ENTER]', 41: '[ESC]', 42: '[DEL]', 43: '[TAB]', 44: ' ',
45: '-', 46: '=', 47: '[', 48: ']', 55: '.', 56: '/', 57: '[CAPSLOCK]',
79: '[RIGHTARROW]', 80: '[LEFTARROW]' }
myKeys = open('keyboard.txt')
output = []
i = 1
for line in myKeys:
bytesArray = bytearray.fromhex(line.strip())
keyVal = int(bytesArray[2])
if keyVal != 0:
if int(bytesArray[0]) == 2:
caps = 1
else:
caps = 0
if keyVal in newmap:
if caps == 1:
output.append(newmap[keyVal].upper())
else:
output.append(newmap[keyVal])
print ("%s\t%s\t%s\t%s\t%s" % (hex(keyVal), keyVal, newmap[keyVal], caps, bytesArray))
else:
print ('No map found for this value: ' + str(keyVal))
print(''.join(output))
Below is an output example:
0x28 40 [ENTER] 0 bytearray(b'\x00\x00(\x00\x00\x00\x00\x00') 0x13 19 p 1 bytearray(b'\x02\x00\x13\x00\x00\x00\x00\x00') 0x14 20 q 0 bytearray(b'\x00\x00\x14\x00\x00\x00\x00\x00') 0x15 21 r 0 bytearray(b'\x00\x00\x15\x00\x00\x00\x00\x00') 0x17 23 t 0 bytearray(b'\x00\x00\x17\x00\x00\x00\x00\x00') 0x2c 44 0 bytearray(b'\x00\x00,\x00\x00\x00\x00\x00') 0x1e 30 1 1 bytearray(b'\x02\x00\x1e\x00\x00\x00\x00\x00') 0x2c 44 0 bytearray(b'\x00\x00,\x00\x00\x00\x00\x00') 0x37 55 . 0 bytearray(b'\x00\x007\x00\x00\x00\x00\x00') 0x2c 44 0 bytearray(b'\x00\x00,\x00\x00\x00\x00\x00') 0xc 12 i 0 bytearray(b'\x00\x00\x0c\x00\x00\x00\x00\x00') 0x19 25 v 1 bytearray(b'\x02\x00\x19\x00\x00\x00\x00\x00') 0x5 5 b 1 bytearray(b'\x02\x00\x05\x00\x00\x00\x00\x00') 0x12 18 o 1 bytearray(b'\x02\x00\x12\x00\x00\x00\x00\x00') 0x15 21 r 1 bytearray(b'\x02\x00\x15\x00\x00\x00\x00\x00') 0x1d 29 z 0 bytearray(b'\x00\x00\x1d\x00\x00\x00\x00\x00') 0x27 39 0 1 bytearray(b"\x02\x00\'\x00\x00\x00\x00\x00") 0xe 14 k 1 bytearray(b'\x02\x00\x0e\x00\x00\x00\x00\x00') 0xa 10 g 1 bytearray(b'\x02\x00\n\x00\x00\x00\x00\x00') 0xa 10 g 0 bytearray(b'\x00\x00\n\x00\x00\x00\x00\x00') 0x12 18 o 0 bytearray(b'\x00\x00\x12\x00\x00\x00\x00\x00') 0x14 20 q 1 bytearray(b'\x02\x00\x14\x00\x00\x00\x00\x00') 0x14 20 q 1 bytearray(b'\x02\x00\x14\x00\x00\x00\x00\x00') 0x14 20 q 1 bytearray(b'\x02\x00\x14\x00\x00\x00\x00\x00') 0x14 20 q 1 bytearray(b'\x02\x00\x14\x00\x00\x00\x00\x00') 0x11 17 n 1 bytearray(b'\x02\x00\x11\x00\x00\x00\x00\x00') 0x16 22 s 1 bytearray(b'\x02\x00\x16\x00\x00\x00\x00\x00') 0x18 24 u 1 bytearray(b'\x02\x00\x18\x00\x00\x00\x00\x00') 0xb 11 h 0 bytearray(b'\x00\x00\x0b\x00\x00\x00\x00\x00') 0x8 8 e 1 bytearray(b'\x02\x00\x08\x00\x00\x00\x00\x00') 0x18 24 u 1 bytearray(b'\x02\x00\x18\x00\x00\x00\x00\x00') 0xa 10 g 0 bytearray(b'\x00\x00\n\x00\x00\x00\x00\x00') 0x14 20 q 1 bytearray(b'\x02\x00\x14\x00\x00\x00\x00\x00') 0x14 20 q 1 bytearray(b'\x02\x00\x14\x00\x00\x00\x00\x00') 0x14 20 q 1 bytearray(b'\x02\x00\x14\x00\x00\x00\x00\x00') 0x1e 30 1 1 bytearray(b'\x02\x00\x1e\x00\x00\x00\x00\x00') 0xe 14 k 0 bytearray(b'\x00\x00\x0e\x00\x00\x00\x00\x00') 0x14 20 q 1 bytearray(b'\x02\x00\x14\x00\x00\x00\x00\x00') 0x14 20 q 1 bytearray(b'\x02\x00\x14\x00\x00\x00\x00\x00') 0x14 20 q 1 bytearray(b'\x02\x00\x14\x00\x00\x00\x00\x00') 0xc 12 i 1 bytearray(b'\x02\x00\x0c\x00\x00\x00\x00\x00') 0x2e 46 = 1 bytearray(b'\x02\x00.\x00\x00\x00\x00\x00') 0x6 6 c 1 bytearray(b'\x02\x00\x06\x00\x00\x00\x00\x00') 0x14 20 q 1 bytearray(b'\x02\x00\x14\x00\x00\x00\x00\x00') 0xc 12 i 1 bytearray(b'\x02\x00\x0c\x00\x00\x00\x00\x00') 0x14 20 q 1 bytearray(b'\x02\x00\x14\x00\x00\x00\x00\x00') 0x14 20 q 1 bytearray(b'\x02\x00\x14\x00\x00\x00\x00\x00') 0x14 20 q 1 bytearray(b'\x02\x00\x14\x00\x00\x00\x00\x00') 0x28 40 [ENTER] 0 bytearray(b'\x00\x00(\x00\x00\x00\x00\x00') 0x28 40 [ENTER] 0 bytearray(b'\x00\x00(\x00\x00\x00\x00\x00') 0x28 40 [ENTER] 0 bytearray(b'\x00\x00(\x00\x00\x00\x00\x00') 0x6 6 c 0 bytearray(b'\x01\x00\x06\x00\x00\x00\x00\x00') [ENTER]Pqrt 1 . iVBORz0KGgoQQQQNSUhEUgQQQ1kQQQI=CQIQQQ[ENTER][ENTER][ENTER]c
Mouse
The data is composed of 4 bytes:
- 1st byte represents the button:
- 0x00 = no button
- 0x01 = left button
- 0x02 = right button
- 2nd byte: signed byte, with the highest bit being the sign bit
- if positive value: gives the number of pixels the mouse is horizontally shifted to the right
- if negative value, represents the number of pixels the mouse is horizontally shifted to the left
- 3rd byte: signed byte, with the highest bit being the sign bit
- if positive value: gives the number of pixels the mouse is vertically shifted to the top
- if negative value, represents the number of pixels the mouse is vertically shifted to the bottom
Suppose you have captured your USB mouse traffic in mouse.pcap. You can use UsbMiceDataHacker.py to decrypt the traffic.
The below example shows the mouse movements when the left button was pressed.
$ python2 UsbMiceDataHacker.py mouse.pcap LEFT
Here is the output:
Comments
Keywords: forensics drivers linux dev usb lsusb usbmon capture pcap