
USB 대용량 저장장치 트래픽을 블록 및 파일 수준에서 가로채고 분석하며, USB 장치를 에뮬레이션하고, 보안 연구, 포렌식 및 TOCTOU 취약점 테스트를 위한 맞춤형 Python 스텁을 지원합니다.

usb-spy는 WiFi 또는 Ethernet 지원 마이크로컨트롤러를 기반으로 구축된 USB 대용량 저장소 트래픽 분석기입니다.
이 보드는 디스크 이미지(FAT 또는 모든 파일시스템)를 대상 시스템에 가짜 USB 대용량 저장소 장치로 노출하며, 실제 저장 데이터는 WiFi 또는 Ethernet을 통해 원격 서버에서 제공됩니다. 이러한 구성 덕분에 usb-spy는 대상 시스템이 수행하는 모든 블록 접근을 가로채고 분석할 수 있습니다.
단순한 원시 블록 수준 추적 외에도 usb-spy는 파일시스템을 이해하고 각 접근된 블록을 해당 파일 및 디렉터리로 매핑할 수 있어, 원시 섹터 번호만 보는 대신 어떤 파일이 읽히거나 쓰이는지 즉시 확인할 수 있습니다.
또한 usb-spy는 JSON 구성 파일을 통해 공급업체 ID, 제품 ID, 일련번호, 제조업체, 제품 이름과 같은 장치 속성을 사용자 지정하여 모든 USB 장치를 에뮬레이션할 수 있습니다. 이를 통해 테스트 및 분석 목적으로 특정 USB 장치를 가장할 수 있습니다.
이 도구는 사용자가 작성한 Python 스텁을 통해 쉽게 확장할 수 있어, USB 읽기/쓰기 이벤트 및 블록 수준 작업을 처리하는 사용자 정의 로직을 구현할 수 있습니다.

지원되는 파일시스템이 감지되면 usb-spy는 다음을 수행합니다:
현재 지원되는 파일시스템:
추가 파일시스템 지원은 향후 추가될 예정입니다.
파일시스템이 지원되지 않는 경우에도 usb-spy를 계속 사용할 수 있습니다:
이를 통해 usb-spy는 알 수 없거나, 사용자 정의 또는 독점 파일시스템에서도 유용하게 사용할 수 있습니다.

각 지원 보드에 대한 펌웨어 빌드 지침은 여기에 설명되어 있습니다:
소스 코드는 src 디렉터리에 있습니다. FAT 이미지를 로드하여 TCP 포트를 통해 노출하고 이미지에 대한 모든 접근을 로깅합니다. 파일 및 디렉터리 정보를 출력하기 위해 이 도구는 TheSleuthKit 라이브러리를 사용합니다.
빌드하려면 루트 디렉터리에서 다음 명령을 실행하세요.
모든 서브모듈 가져오기
git submodule update --init --recursive
그런 다음 waf configure 명령을 실행하세요.
./waf configure
Python 임베딩 지원 없이 빌드하려면 다음으로 구성하세요:
./waf configure --disable-python
필요한 모든 종속성을 확인하고 빌드한 다음, 실제로 프로젝트를 빌드하려면 다음을 실행하세요.
./waf build
바이너리는 wbuild 디렉터리에 있습니다.
--disable-python으로 빌드한 경우 --py 및 --py-args 런타임 옵션은 사용할 수 없습니다.
mtools 유틸리티 패키지를 사용하여 쉽게 생성할 수 있습니다.
2MB 파일 생성
dd if=/dev/zero of=disk.img bs=1M count=2
FAT 파일시스템 생성 (-F를 사용하면 FAT32, 그렇지 않으면 자동)
mformat -i disk.img ::
파일 추가
mcopy -i disk.img example.txt ::
파일 목록 보기
mdir -i disk.img ::
파일 추출
mcopy -i disk.img ::/example.txt extracted.txt
새로 생성된 이미지로 스파이 실행
./usb-spy -v disk.img
원시 모드를 강제하고 파일시스템 자동 감지를 건너뛰려면:
./usb-spy --raw disk.img
실제 블록 장치로 직접 프록시 접근하려면:
./usb-spy --proxy /dev/sda
보드를 대상 USB 포트에 연결하세요.
특정 USB 장치를 에뮬레이션하려면 JSON 구성 파일을 통해 매개변수를 재정의할 수 있습니다:
다음 JSON 파일은 Kingston DataTraveler USB 장치를 에뮬레이션합니다:
{
"vendor_id": 2385,
"product_id": 5734,
"bcd_device": 272,
"product_rev": "3.0",
"manufacturer": "Kingston",
"product_name": "DataTraveler",
"serial": "509C4BBFACCDE742880C026B",
"language": 1033
}
이 구성 파일로 스파이 실행
./usb-spy -c config/kingston.json disk.img
이 장치에 대한 dmesg 출력:
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
모든 읽기/쓰기 이벤트에 대해 사용자 정의 로직을 구현하려면 Python으로 쉽게 구현할 수 있습니다.
다음 dummy 이미지처럼 Python에서 USBImage 클래스를 구현하세요:
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")
그리고 Python 모듈로 스파이를 실행하세요.
./usb-spy --py python/dummy.py disk.img
명령줄에서 Python 클래스로 임의의 인수를 전달할 수도 있습니다. 인수는 kwargs에서 사용할 수 있습니다.
./usb-spy --py python/dummy.py --py-args arg1=2 --py-args arg2=Hello disk.img
또한 usb-spy 바이너리에 기본적으로 구현된 기능의 완전한 구현(~100줄의 코드)을 제공하는 rawimage 예제에서 시작할 수도 있습니다.
이 프로젝트는 "있는 그대로" 제공됩니다. 정확성, 보안 또는 특정 목적에 대한 적합성을 보장하지 않습니다.
도구와 펌웨어는 사용자 책임 하에 사용하세요. 작성자와 기여자는 이 소프트웨어 또는 하드웨어 사용으로 인해 발생할 수 있는 손상, 데이터 손실 또는 법적 결과에 대해 책임을 지지 않습니다.
기여를 환영합니다! 다음 단계를 따르세요:
이 프로젝트는 GNU General Public License v3.0에 따라 라이선스가 부여됩니다. 자세한 내용은 LICENSE 파일을 참조하세요.