USB Devices

ForTrace++ identifies USB devices based on their Vendor ID (VID) and Product ID (PID) and forwards them to a VM, by modifying the live XML description. This means that this change is not persistent, and rebooting the VM will detach the USB device.

Include real devices in scenarios

To include real devices in a scenario, obtain their VID & PID. In the example below, the VID is 0x0951, the PID is 0x160b.

$ lsusb
[...]
Bus 001 Device 010: ID 0951:160b Kingston Technology DataTraveler 2.0 (2GB)
[...]

The device can now be attached to a VM:

domain.attach_usb_device("0x0951", "0x160b")
# [...]
domain.detach_usb_device("0x0951", "0x160b")

You can also attach multiple devices to the same domain, at the same time, if there are sufficient USB hubs. Just call the attach_usb_device multiple times.

Note

Remember to call detach_sub_device, once you are done. If not, the device will stay connected until the VM is shut down.

USB device spoofing with Raspberry Pi

The Raspberry Pi needs to be configured in advance to act as a USB spoofing device. You may follow the guide about Raspberry-Pi USB Spoofing.

Once completed, and the device can be reached with SSH, it can be integrated with the USBSpoofer class. Therefore, create following section in a scenario configuration file. Make sure the usb-spoofer script is located in /home/<username>/usb-spoofer.

usb_host:
  hostname: "10.10.10.43"
  port: 22
  username: "varg"
  password: "password" # optional
  devices:
    - gadget_name: "usb_1"
      keep_backing_store: False # optional: default False
      vendor_id: "0x0951"
      product_id: "0x160b"
      manufacturer: "Kingston Technology"
      product_name: "DataTraveler 2.0 (2GB)"
      serial_number: "5404A6C0AFF8F170B9600284"
      size: 2G
      file_system: "fat32"
      label: "MYDATA" # optional
  • hostname: IP or hostname to reach the Raspberry Pi in the network.

  • port: SSH port

  • username: Username to use for the SSH connection.

  • password: Optional password to use for SSH connection.

  • devices: List of devices to create on the Raspberry Pi.

  • gadget_name: Unique name that identifies all configured gadgets on the Raspberry Pi. Will also determine the name of the backing store.

  • keep_backing_store: Optional boolean, whether to clean up the backing store file during the destruction of the spoofer. The backing store is located below /root/<gadget_name>

  • vendor_id: 2 Byte hex code of the vendor ID.

  • product_id: 2 Byte hex code of the product ID.

  • manufacturer: Manufacturer string

  • product_name: Product string

  • serial_number: Serial number

  • size: Size of the backing store to create with fallocate. Keep in mind that the sum of all backing stores has to fit on the microSD card of the Raspberry Pi.

  • file_system: File system to use for the backing store

  • label: Label to assign to the created partition

In case you want to get valid combinations of VID, PID, manufacturer string, and product string, take a look at fortrace.utility.usb_spoofing.usb_device. This script provides a small CLI to filter and generate ForTrace++ compatible configurations. For example, to generate a device of the manufacturer SanDisk, run the following command. Provide the --help option, for a more detailed explanation.

$ python src/fortrace/utility/usb_spoofing/usb_device.py -m SanDisk
[{'vendor_id': '0x0781', 'product_id': '0x8183',
'product_name': 'Hi-Speed Mass Storage Device', 'manufacturer': 'SanDisk Corp.',
'serial_number': 'd660f28028e8487d', 'file_system': 'nfts', 'size': '256M',
'label': None}]

Make sure the Raspberry Pi is turned on and can be reached under the specified IP. Afterward, you can create the USBSpoofer as follows. This call will already allocate every specified device on the Raspberry Pi, so they can be used directly. Since this class implements the context management protocol, the cleanup of the devices is handled automatically.

with USBSpoofer(config["usb_host"]) as spoofer:
# [...]

USB gadgets can then be activated and forwarded to the domain.

with spofer.activate("usb_1") as gadget:
    domain.attach_usb_device(gadget.device.vendor_id, gadget.device.product_id)
    # [...]
    domain.detach_usb_device(gadget.device.vendor_id, gadget.device.product_id)