You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/generic-methodologies-and-resources/basic-forensic-methodology/pcap-inspection/usb-keystrokes.md
+73-5Lines changed: 73 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,19 +6,87 @@ If you have a pcap containing the communication via USB of a keyboard like the f
6
6
7
7
.png>)
8
8
9
-
You can use the tool [**ctf-usb-keyboard-parser**](https://github.com/TeamRocketIst/ctf-usb-keyboard-parser) to get what was written in the communication:
9
+
USB keyboards usually speak the HID **boot protocol**, so every interrupt transfer towards the host is only 8 bytes long: one byte of modifier bits (Ctrl/Shift/Alt/Super), one reserved byte, and up to six keycodes per report. Decoding those bytes is enough to rebuild everything that was typed.
10
+
11
+
## USB HID report basics
12
+
13
+
The typical IN report looks like:
14
+
15
+
| Byte | Meaning |
16
+
| --- | --- |
17
+
| 0 | Modifier bitmap (`0x02` = Left Shift, `0x20` = Right Alt, etc.). Multiple bits can be set simultaneously. |
18
+
| 1 | Reserved/padding but often reused by gaming keyboards for vendor data. |
19
+
| 2-7 | Up to six concurrent keycodes in USB usage ID format (`0x04 = a`, `0x1E = 1`). `0x00` means "no key". |
20
+
21
+
Keyboards without NKRO usually send `0x01` in byte 2 when more than six keys are pressed to signal "rollover". Understanding this layout helps when you only have the raw `usb.capdata` bytes.
22
+
23
+
## Extracting HID data from a PCAP
24
+
25
+
### Wireshark workflow
26
+
27
+
1.**Isolate the device**: filter on interrupt IN traffic from the keyboard, e.g. `usb.transfer_type == 0x01 && usb.endpoint_address.direction == "IN" && usb.device_address == 3`.
28
+
2.**Add useful columns**: right-click the `Leftover Capture Data` field (`usb.capdata`) and your preferred `usbhid.*` fields (e.g. `usbhid.boot_report.keyboard.keycode_1`) to follow keystrokes without opening every frame.
29
+
3.**Hide empty reports**: apply `!(usb.capdata == 00:00:00:00:00:00:00:00)` to drop idle frames.
30
+
4.**Export for post-processing**: `File -> Export Packet Dissections -> As CSV`, include `frame.number`, `usb.src`, `usb.capdata`, and `usbhid.modifiers` to script the reconstruction later.
31
+
32
+
### Command-line workflow
33
+
34
+
`ctf-usb-keyboard-parser` already automates the classic tshark + sed pipeline:
Those per-device files drop straight into any decoder. If the capture came from BLE keyboards tunneled over GATT, filter on `btatt.value && frame.len == 20` and dump the hex payloads before decoding.
51
+
52
+
## Automating the decoding
53
+
54
+
-**ctf-usb-keyboard-parser** remains handy for quick CTF challenges and already ships in the repository.
55
+
-**CTF-Usb_Keyboard_Parser** (`main.py`) parses both `pcap` and `pcapng` files natively, understands `LinkTypeUsbLinuxMmapped`/`LinkTypeUsbPcap`, and does not require tshark, so it works nicely inside isolated sandboxes.
56
+
-**USB-HID-decoders** adds keyboard, mouse, and tablet visualizers. You can either run the `extract_hid_data.sh` helper (tshark backend) or `extract_hid_data.py` (scapy backend) and then feed the resulting text file to the decoder or replay modules to watch the keystrokes unfold.
Feed it with the plain hex lines dumped earlier to get an instant rough reconstruction without pulling a full parser into the environment.
78
+
79
+
## Troubleshooting tips
22
80
81
+
- If Wireshark does not populate `usbhid.*` fields, the HID report descriptor was probably not captured. Replug the keyboard while capturing or fall back to raw `usb.capdata`.
82
+
- Windows captures require the **USBPcap** extcap interface; make sure it survived Wireshark upgrades, as missing extcaps leave you with empty device lists.
83
+
- Always correlate `usb.bus_id:device:interface` (e.g. `1.9.1`) before decoding anything — mixing multiple keyboards or storage devices leads to nonsense keystrokes.
0 commit comments