Intercepta y analiza el tráfico de almacenamiento masivo USB a nivel de bloques y archivos, emula dispositivos USB y admite stubs personalizados de Python para investigación de seguridad, análisis forense y pruebas de vulnerabilidad TOCTOU.

usb-spy es un analizador de tráfico de almacenamiento masivo USB construido alrededor de un microcontrolador con WiFi o Ethernet.
La placa expone una imagen de disco (FAT o cualquier sistema de archivos) como un dispositivo USB de almacenamiento masivo falso para un sistema objetivo, mientras que los datos de almacenamiento reales son proporcionados por un servidor remoto a través de WiFi o Ethernet. Esta configuración permite a usb-spy interceptar y analizar cada acceso a bloques realizado por el objetivo.
Más allá del rastreo a nivel de bloques, usb-spy comprende sistemas de archivos y puede mapear cada bloque accedido de vuelta al archivo y directorio correspondiente, lo que facilita ver inmediatamente qué archivo se está leyendo o escribiendo, en lugar de solo números de sector en bruto.
Además, usb-spy puede emular cualquier dispositivo USB personalizando las propiedades del dispositivo, como el ID de proveedor, ID de producto, número de serie, fabricante y nombre de producto a través de un archivo de configuración JSON. Esto le permite suplantar dispositivos USB específicos para fines de prueba y análisis.
La herramienta es fácilmente extensible mediante stubs de Python escritos por el usuario, lo que le permite implementar lógica personalizada para manejar eventos de lectura/escritura USB y operaciones a nivel de bloques.

Cuando se detecta un sistema de archivos compatible, usb-spy:
Sistemas de archivos actualmente compatibles:
Se añadirá soporte para sistemas de archivos adicionales en el futuro.
Si el sistema de archivos no es compatible, usb-spy aún puede utilizarse:
Esto garantiza que usb-spy siga siendo útil incluso con sistemas de archivos desconocidos, personalizados o propietarios.

Las instrucciones de compilación del firmware para cada placa compatible se describen aquí:
El código fuente está en el directorio src. Cargará una imagen FAT, la expondrá a través de un puerto TCP y registrará cada acceso realizado a la imagen. Para imprimir información de archivos y directorios, la herramienta se basa en la biblioteca TheSleuthKit.
Para compilar, ejecute el siguiente comando en el directorio raíz
Obtener todos los submódulos
git submodule update --init --recursive
Luego ejecute el comando de configuración de waf.
./waf configure
Si desea compilar sin soporte de integración de Python, configure con:
./waf configure --disable-python
Comprobará y compilará todas las dependencias que necesite, luego para compilar realmente el proyecto ejecute
./waf build
El binario estará en el directorio wbuild
Cuando se compila con --disable-python, las opciones de ejecución --py y --py-args no están disponibles.
Podemos hacerlo fácilmente con el paquete de utilidades mtools
Crear un archivo de 2 MB
dd if=/dev/zero of=disk.img bs=1M count=2
Poner un sistema de archivos FAT en él (use -F para FAT32, de lo contrario es automático)
mformat -i disk.img ::
Añadir un archivo
mcopy -i disk.img example.txt ::
Listar archivos
mdir -i disk.img ::
Extraer un archivo
mcopy -i disk.img ::/example.txt extracted.txt
Ejecute el spy con la imagen recién creada
./usb-spy -v disk.img
Para forzar el modo en bruto y omitir la detección automática del sistema de archivos:
./usb-spy --raw disk.img
Para proxy de acceso directamente a un dispositivo de bloques real:
./usb-spy --proxy /dev/sda
Conecte la placa al puerto USB del objetivo.
Para emular un dispositivo USB específico, los parámetros se pueden sobrescribir mediante un archivo de configuración json:
El siguiente archivo json emulará un dispositivo USB Kingston DataTraveler:
{
"vendor_id": 2385,
"product_id": 5734,
"bcd_device": 272,
"product_rev": "3.0",
"manufacturer": "Kingston",
"product_name": "DataTraveler",
"serial": "509C4BBFACCDE742880C026B",
"language": 1033
}
Ejecute el spy con este archivo de configuración
./usb-spy -c config/kingston.json disk.img
La salida de dmesg para este dispositivo:
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
Si desea implementar su propia lógica para cada evento de lectura/escritura, puede hacerlo fácilmente en Python.
Implemente la clase USBImage en Python como esta imagen dummy:
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")
Y ejecute el spy con su módulo de Python.
./usb-spy --py python/dummy.py disk.img
También puede pasar argumentos arbitrarios desde la línea de comandos a su clase de Python. Los argumentos están disponibles en kwargs.
./usb-spy --py python/dummy.py --py-args arg1=2 --py-args arg2=Hello disk.img
También puede comenzar desde el ejemplo rawimage que proporciona una implementación completa (~100 líneas de código) de lo que está implementado de forma nativa en el binario usb-spy.
Este proyecto se proporciona "tal cual". No hay garantía de corrección, seguridad o idoneidad para ningún propósito particular.
Use las herramientas y el firmware bajo su propio riesgo. El autor y los colaboradores no son responsables de ningún daño, pérdida de datos o consecuencias legales que puedan surgir del uso de este software o hardware.
¡Las contribuciones son bienvenidas! Por favor, siga estos pasos:
Este proyecto está licenciado bajo la Licencia Pública General de GNU v3.0. Consulte el archivo LICENSE para más detalles.