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 portusername: 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 stringproduct_name: Product stringserial_number: Serial numbersize: Size of the backing store to create withfallocate. 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 storelabel: 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)