USB ํ‚ค์ŠคํŠธ๋กœํฌ

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ

If you have a pcap containing the communication via USB of a keyboard like the following one:

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.

USB HID report basics

The typical IN report looks like:

Byte์˜๋ฏธ
0Modifier bitmap (0x02 = Left Shift, 0x20 = Right Alt, etc.). Multiple bits can be set simultaneously.
1Reserved/padding but often reused by gaming keyboards for vendor data.
2-7Up to six concurrent keycodes in USB usage ID format (0x04 = a, 0x1E = 1). 0x00 means โ€œno keyโ€.

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.

Extracting HID data from a PCAP

Wireshark workflow

  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.
  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.
  3. Hide empty reports: apply !(usb.capdata == 00:00:00:00:00:00:00:00) to drop idle frames.
  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.

Command-line workflow

ctf-usb-keyboard-parser already automates the classic tshark + sed pipeline:

tshark -r ./usb.pcap -Y 'usb.capdata && usb.data_len == 8' -T fields -e usb.capdata | sed 's/../:&/g2' > keystrokes.txt
python3 usbkeyboard.py ./keystrokes.txt

์ตœ์‹  ์บก์ฒ˜์—์„œ๋Š” ์žฅ์น˜๋ณ„๋กœ ๋ฐฐ์น˜ ์ฒ˜๋ฆฌํ•˜์—ฌ usb.capdata์™€ ๋” ํ’๋ถ€ํ•œ usbhid.data ํ•„๋“œ ๋‘˜ ๋‹ค ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

tshark -r usb.pcapng -Y "usb.capdata || usbhid.data" -T fields -e usb.src -e usb.capdata -e usbhid.data | \
sort -s -k1,1 | \
awk '{ printf "%s", (NR==1 ? $1 : pre!=$1 ? "\n" $1 : "") " " $2; pre=$1 }' | \
awk '{ for (i=2; i<=NF; i++) print $i > "usbdata-" $1 ".txt" }'

๊ทธ ์žฅ์น˜๋ณ„ ํŒŒ์ผ๋“ค์€ ์–ด๋–ค decoder์—๋„ ๋ฐ”๋กœ ๋„ฃ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์บก์ฒ˜๊ฐ€ GATT๋กœ ํ„ฐ๋„๋ง๋œ BLE ํ‚ค๋ณด๋“œ์—์„œ ์™”๋‹ค๋ฉด, btatt.value && frame.len == 20๋กœ ํ•„ํ„ฐ๋งํ•˜๊ณ  ๋””์ฝ”๋”ฉํ•˜๊ธฐ ์ „์— hex payloads๋ฅผ ๋คํ”„ํ•˜์„ธ์š”.

๋””์ฝ”๋”ฉ ์ž๋™ํ™”

  • ctf-usb-keyboard-parser๋Š” ๋น ๋ฅธ CTF ๊ณผ์ œ์— ์œ ์šฉํ•˜๋ฉฐ ์ด๋ฏธ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
  • CTF-Usb_Keyboard_Parser (main.py)๋Š” pcap๊ณผ pcapng ํŒŒ์ผ์„ ๋„ค์ดํ‹ฐ๋ธŒ๋กœ ํŒŒ์‹ฑํ•˜๊ณ  LinkTypeUsbLinuxMmapped/LinkTypeUsbPcap์„ ์ดํ•ดํ•˜๋ฉฐ tshark๊ฐ€ ํ•„์š” ์—†์–ด์„œ ๊ฒฉ๋ฆฌ๋œ ์ƒŒ๋“œ๋ฐ•์Šค์—์„œ๋„ ์ž˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.
  • USB-HID-decoders๋Š” ํ‚ค๋ณด๋“œ, ๋งˆ์šฐ์Šค, ํƒœ๋ธ”๋ฆฟ์šฉ ์‹œ๊ฐํ™”๊ธฐ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. extract_hid_data.sh ํ—ฌํผ(tshark ๋ฐฑ์—”๋“œ)๋‚˜ extract_hid_data.py(scapy ๋ฐฑ์—”๋“œ)๋ฅผ ์‹คํ–‰ํ•œ ๋‹ค์Œ ์ƒ์„ฑ๋œ ํ…์ŠคํŠธ ํŒŒ์ผ์„ decoder ๋˜๋Š” replay ๋ชจ๋“ˆ์— ๋„ฃ์–ด ํ‚ค ์ž…๋ ฅ์ด ์žฌ์ƒ๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋น ๋ฅธ Python decoder

#!/usr/bin/env python3
import sys
HID = {0x04:'a',0x05:'b',0x06:'c',0x07:'d',0x08:'e',0x09:'f',0x0a:'g',0x1c:'y',0x1d:'z',0x28:'\n'}
for raw in sys.stdin:
raw = raw.strip().replace(':', '')
if len(raw) != 16:
continue
keycode = int(raw[4:6], 16)
modifier = int(raw[0:2], 16)
if keycode:
char = HID.get(keycode, '?')
if modifier & 0x02:
char = char.upper()
sys.stdout.write(char)

์ด์ „์— ๋คํ”„ํ•œ 16์ง„์ˆ˜(hex) ๋ผ์ธ๋“ค์„ ์ž…๋ ฅํ•˜๋ฉด ์ „์ฒด ํŒŒ์„œ๋ฅผ ํ™˜๊ฒฝ์— ๋ถˆ๋Ÿฌ์˜ค์ง€ ์•Š๊ณ ๋„ ์ฆ‰์‹œ ๋Œ€๋žต์ ์ธ ๋ณต์›์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ ํ•ด๊ฒฐ ํŒ

  • Wireshark์ด usbhid.* ํ•„๋“œ๋ฅผ ์ฑ„์šฐ์ง€ ์•Š๋Š”๋‹ค๋ฉด, HID report descriptor๊ฐ€ ์•„๋งˆ ์บก์ฒ˜๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์บก์ฒ˜ ์ค‘์— ํ‚ค๋ณด๋“œ๋ฅผ ์žฌ์—ฐ๊ฒฐํ•˜๊ฑฐ๋‚˜ ์›์‹œ usb.capdata๋กœ ๋˜๋Œ์•„๊ฐ€์„ธ์š”.
  • Windows ์บก์ฒ˜๋Š” USBPcap extcap ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ•„์š”๋กœ ํ•ฉ๋‹ˆ๋‹ค; Wireshark ์—…๊ทธ๋ ˆ์ด๋“œ ํ›„์—๋„ ํ•ด๋‹น ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์œ ์ง€๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”. extcap์ด ์—†์œผ๋ฉด ์žฅ์น˜ ๋ชฉ๋ก์ด ๋น„์–ด ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
  • ๋””์ฝ”๋”ฉ์„ ํ•˜๊ธฐ ์ „์— ํ•ญ์ƒ usb.bus_id:device:interface (์˜ˆ: 1.9.1)๋ฅผ ์ƒํ˜ธ ์—ฐ๊ด€์‹œ์ผœ ํ™•์ธํ•˜์„ธ์š” โ€” ์—ฌ๋Ÿฌ ํ‚ค๋ณด๋“œ๋‚˜ ์Šคํ† ๋ฆฌ์ง€ ์žฅ์น˜๋ฅผ ์„ž์–ด ๋ถ„์„ํ•˜๋ฉด ๋ฌด์˜๋ฏธํ•œ ํ‚ค์ŠคํŠธ๋กœํฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

์ฐธ๊ณ ์ž๋ฃŒ

  • https://github.com/TeamRocketIst/ctf-usb-keyboard-parser
  • https://github.com/tanc7/HacktheBox_Deadly_Arthropod_Writeup
  • https://github.com/5h4rrk/CTF-Usb_Keyboard_Parser
  • https://github.com/Nissen96/USB-HID-decoders

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ