
Fängt USB-Massenspeicherverkehr auf Block- und Dateiebene ab und analysiert ihn, emuliert USB-Geräte und unterstützt benutzerdefinierte Python-Stubs für Sicherheitsforschung, Forensik und TOCTOU-Schwachstellentests.

usb-spy ist ein USB-Massenspeicher-Verkehrsanalysator, der auf einem Mikrocontroller mit WiFi- oder Ethernet-Anbindung basiert.
Das Board stellt einem Zielsystem ein Festplatten-Image (FAT oder ein beliebiges Dateisystem) als gefälschtes USB-Massenspeichergerät zur Verfügung, während die tatsächlichen Speicherdaten von einem entfernten Server über WiFi oder Ethernet bereitgestellt werden. Dieses Setup ermöglicht es usb-spy, jeden vom Zielsystem durchgeführten Blockzugriff abzufangen und zu analysieren.
Über die reine Block-Level-Verfolgung hinaus versteht usb-spy Dateisysteme und kann jeden zugegriffenen Block der entsprechenden Datei und dem entsprechenden Verzeichnis zuordnen. So ist sofort ersichtlich, welche Datei gerade gelesen oder geschrieben wird, anstatt nur rohe Sektornummern zu sehen.
Darüber hinaus kann usb-spy jedes USB-Gerät emulieren, indem Geräteeigenschaften wie Vendor-ID, Produkt-ID, Seriennummer, Hersteller und Produktname über eine JSON-Konfigurationsdatei angepasst werden. Dies ermöglicht die Nachbildung bestimmter USB-Geräte für Test- und Analysezwecke.
Das Tool lässt sich leicht durch benutzerdefinierte Python-Stubs erweitern, sodass Sie eigene Logik für die Behandlung von USB-Lese-/Schreibereignissen und Block-Level-Operationen implementieren können.

Wenn ein unterstütztes Dateisystem erkannt wird, führt usb-spy Folgendes aus:
Derzeit unterstützte Dateisysteme:
Die Unterstützung für weitere Dateisysteme wird in Zukunft hinzugefügt.
Wenn das Dateisystem nicht unterstützt wird, kann usb-spy weiterhin verwendet werden:
Dadurch bleibt usb-spy auch bei unbekannten, benutzerdefinierten oder proprietären Dateisystemen nützlich.

Build-Anweisungen für die Firmware jedes unterstützten Boards sind hier beschrieben:
Der Quellcode befindet sich im Verzeichnis src. Er lädt ein FAT-Image, stellt es über einen TCP-Port bereit und protokolliert jeden Zugriff auf das Image.
Um Datei- und Verzeichnisinformationen auszugeben, verwendet das Tool die TheSleuthKit-Bibliothek.
Führen Sie zum Erstellen den folgenden Befehl im Stammverzeichnis aus
Alle Submodule abrufen
git submodule update --init --recursive
Dann den waf-Konfigurationsbefehl ausführen.
./waf configure
Wenn Sie ohne Python-Embedding-Unterstützung bauen möchten, konfigurieren Sie mit:
./waf configure --disable-python
Es prüft und erstellt alle benötigten Abhängigkeiten. Um das Projekt dann tatsächlich zu bauen, führen Sie Folgendes aus:
./waf build
Die Binärdatei befindet sich im Verzeichnis wbuild
Bei einem Build mit --disable-python stehen die Laufzeitoptionen --py und --py-args nicht zur Verfügung.
Dies lässt sich einfach mit dem mtools-Dienstprogrammpaket bewerkstelligen.
Eine 2-MB-Datei erstellen
dd if=/dev/zero of=disk.img bs=1M count=2
Ein FAT-Dateisystem darauf anlegen (mit -F für FAT32, ansonsten automatisch)
mformat -i disk.img ::
Eine Datei hinzufügen
mcopy -i disk.img example.txt ::
Dateien auflisten
mdir -i disk.img ::
Eine Datei extrahieren
mcopy -i disk.img ::/example.txt extracted.txt
Führen Sie den Spy mit dem neu erstellten Image aus
./usb-spy -v disk.img
Um den Rohmodus zu erzwingen und die Dateisystem-Autoerkennung zu überspringen:
./usb-spy --raw disk.img
Um Zugriffe direkt an ein echtes Blockgerät weiterzuleiten:
./usb-spy --proxy /dev/sda
Stecken Sie das Board in den USB-Port des Zielsystems.
Um ein bestimmtes USB-Gerät zu emulieren, können Parameter über eine JSON-Konfigurationsdatei überschrieben werden:
Die folgende JSON-Datei emuliert ein Kingston-DataTraveler-USB-Gerät:
{
"vendor_id": 2385,
"product_id": 5734,
"bcd_device": 272,
"product_rev": "3.0",
"manufacturer": "Kingston",
"product_name": "DataTraveler",
"serial": "509C4BBFACCDE742880C026B",
"language": 1033
}
Führen Sie den Spy mit dieser Konfigurationsdatei aus
./usb-spy -c config/kingston.json disk.img
Die dmesg-Ausgabe für dieses Gerät:
usb 1-8: New USB device found, idVendor=0951, idProduct=1666, bcdDevice= 1.10
usb 1-8: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 1-8: Product: DataTraveler
usb 1-8: Manufacturer: Kingston
usb 1-8: SerialNumber: 509C4BBFACCDE742880C026B
usb-storage 1-8:1.0: USB Mass Storage device detected
scsi host6: usb-storage 1-8:1.0
scsi 6:0:0:0: Direct-Access Kingston DataTraveler 3.0 PQ: 0 ANSI: 2
Wenn Sie Ihre eigene Logik für jedes Lese-/Schreibereignis implementieren möchten, können Sie dies einfach in Python tun.
Implementieren Sie die USBImage-Klasse in Python wie dieses dummy-Image:
class USBImage:
def __init__(self, *args, **kwargs):
"""
Initialize the USBImage.
:param args: should contain:
- filename: The name of the file to manage.
:param kwargs: Arbitrary arguments passed from the c++ command line including:
readOnly: Whether the interface is read-only.
verbose: Whether to enable verbose logging.
block: Whether to enable block mode.
"""
pass
def getBlockNumber(self):
"""Get block number"""
return 100
def getBlockSize(self):
"""Get block size"""
return 512
def read(self, lba, buffer, size):
"""Read block"""
print(f"read block={lba} size={size}")
for i in range(size):
buffer[i] = (lba + i) % 256 # Simulate reading data
return size
def write(self, lba, buffer, size):
"""Write block"""
print(f"write block={lba} size={size}")
print(buffer)
return size
def flush(self):
"""Flush block"""
print("flush data")