Intercepta e analisa o tráfego de dispositivos de armazenamento em massa USB nos níveis de bloco e arquivo, emula dispositivos USB e suporta stubs personalizados em Python para pesquisa em segurança, perícia forense e testes de vulnerabilidade TOCTOU.

usb-spy é um analisador de tráfego de armazenamento em massa USB construído em torno de um microcontrolador com suporte a WiFi ou Ethernet.
A placa expõe uma imagem de disco (FAT ou qualquer sistema de arquivos) como um dispositivo USB de armazenamento em massa falso para um sistema alvo, enquanto os dados de armazenamento reais são fornecidos por um servidor remoto via WiFi ou Ethernet. Essa configuração permite que o usb-spy intercepte e analise cada acesso a bloco realizado pelo alvo.
Além do rastreamento bruto em nível de bloco, o usb-spy entende sistemas de arquivos e pode mapear cada bloco acessado de volta ao arquivo e diretório correspondente, facilitando a visualização imediata de qual arquivo está sendo lido ou gravado, em vez de apenas números brutos de setores.
Adicionalmente, o usb-spy pode emular qualquer dispositivo USB personalizando propriedades do dispositivo, como ID do fornecedor, ID do produto, número de série, fabricante e nome do produto, por meio de um arquivo de configuração JSON. Isso permite que você se passe por dispositivos USB específicos para fins de teste e análise.
A ferramenta é facilmente extensível por meio de stubs Python escritos pelo usuário, permitindo implementar lógica personalizada para lidar com eventos de leitura/gravação USB e operações em nível de bloco.

Quando um sistema de arquivos suportado é detectado, o usb-spy:
Sistemas de arquivos atualmente suportados:
Suporte para sistemas de arquivos adicionais será adicionado no futuro.
Se o sistema de arquivos não for suportado, o usb-spy ainda pode ser usado:
Isso garante que o usb-spy permaneça útil mesmo com sistemas de arquivos desconhecidos, personalizados ou proprietários.

As instruções de compilação do firmware para cada placa suportada estão descritas aqui:
O código-fonte está no diretório src. Ele carregará uma imagem FAT, a exporá por meio de uma porta TCP e registrará cada acesso feito à imagem. Para imprimir informações de arquivos e diretórios, a ferramenta depende da biblioteca TheSleuthKit.
Para compilar, execute o seguinte comando no diretório raiz
Busque todos os submódulos
git submodule update --init --recursive
Em seguida, execute o comando de configuração do waf.
./waf configure
Se você quiser compilar sem suporte a incorporação de Python, configure com:
./waf configure --disable-python
Ele verificará e compilará todas as dependências necessárias; em seguida, para realmente compilar o projeto, execute
./waf build
O binário estará no diretório wbuild
Quando compilado com --disable-python, as opções de execução --py e --py-args não estão disponíveis.
Podemos fazer isso facilmente com o pacote utilitário mtools
Crie um arquivo de 2 MB
dd if=/dev/zero of=disk.img bs=1M count=2
Coloque um sistema de arquivos FAT nele (use -F para FAT32, caso contrário é automático)
mformat -i disk.img ::
Adicione um arquivo a ele
mcopy -i disk.img example.txt ::
Liste os arquivos
mdir -i disk.img ::
Extraia um arquivo
mcopy -i disk.img ::/example.txt extracted.txt
Execute o spy com a imagem recém-criada
./usb-spy -v disk.img
Para forçar o modo bruto e pular a detecção automática de sistema de arquivos:
./usb-spy --raw disk.img
Para fazer proxy de acesso diretamente a um dispositivo de bloco real:
./usb-spy --proxy /dev/sda
Conecte a placa à porta USB do alvo.
Para emular um dispositivo USB específico, os parâmetros podem ser sobrescritos por meio de um arquivo de configuração json:
O seguinte arquivo json emulará um 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
}
Execute o spy com este arquivo de configuração
./usb-spy -c config/kingston.json disk.img
A saída do 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
Se você quiser implementar sua própria lógica para cada evento de leitura/gravação, pode fazê-lo facilmente em Python.
Implemente a classe USBImage em Python como esta imagem 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")
E execute o spy com seu módulo Python.
./usb-spy --py python/dummy.py disk.img
Você também pode passar argumentos arbitrários da linha de comando para sua classe Python. Os argumentos estão disponíveis nos kwargs.
./usb-spy --py python/dummy.py --py-args arg1=2 --py-args arg2=Hello disk.img
Você também pode começar pelo exemplo rawimage, que fornece uma implementação completa (~100 linhas de código) do que é implementado nativamente no binário usb-spy.
Este projeto é fornecido "como está". Não há garantia de correção, segurança ou adequação para qualquer finalidade específica.
Use as ferramentas e o firmware por sua conta e risco. O autor e os colaboradores não são responsáveis por qualquer dano, perda de dados ou consequências legais que possam surgir do uso deste software ou hardware.
Contribuições são bem-vindas! Por favor, siga estes passos:
Este projeto é licenciado sob a GNU General Public License v3.0. Consulte o arquivo LICENSE para obter detalhes.