
يعترض ويحلل حركة مرور أجهزة التخزين الكتلي USB على مستوى الكتلة والملف، ويحاكي أجهزة USB، ويدعم برامج ثابتة مخصصة بلغة بايثون لأبحاث الأمن، والتحليل الجنائي، واختبار ثغرات TOCTOU.

usb-spy هو محلل لحركة مرور تخزين USB الشامل مبني حول متحكم دقيق يدعم WiFi أو Ethernet.
تعرض اللوحة صورة قرص (FAT أو أي نظام ملفات) كجهاز تخزين USB وهمي للنظام المستهدف، بينما يتم توفير بيانات التخزين الفعلية بواسطة خادم بعيد عبر WiFi أو Ethernet. يتيح هذا الإعداد لـ usb-spy اعتراض وتحليل كل وصول إلى كتلة يتم إجراؤه بواسطة الهدف.
إلى جانب تتبع الكتل الخام، يفهم usb-spy أنظمة الملفات ويمكنه تعيين كل كتلة تم الوصول إليها إلى الملف والدليل المقابل، مما يسهل رؤية الملف الذي تتم قراءته أو كتابته على الفور بدلاً من مجرد أرقام القطاعات الخام.
بالإضافة إلى ذلك، يمكن لـ usb-spy محاكاة أي جهاز USB عن طريق تخصيص خصائص الجهاز مثل معرف البائع ومعرف المنتج والرقم التسلسلي والشركة المصنعة واسم المنتج من خلال ملف تكوين JSON. يتيح لك ذلك انتحال أجهزة USB محددة لأغراض الاختبار والتحليل.
الأداة قابلة للتوسيع بسهولة من خلال مثبتات Python يكتبها المستخدم، مما يسمح لك بتنفيذ منطق مخصص للتعامل مع أحداث القراءة/الكتابة لـ USB وعمليات الكتل.

عند اكتشاف نظام ملفات مدعوم، يقوم usb-spy بما يلي:
أنظمة الملفات المدعومة حالياً:
سيتم إضافة دعم لأنظمة ملفات إضافية في المستقبل.
إذا لم يكن نظام الملفات مدعوماً، لا يزال بإمكان استخدام usb-spy:
يضمن ذلك بقاء usb-spy مفيداً حتى مع أنظمة الملفات غير المعروفة أو المخصصة أو الخاصة.

إرشادات بناء البرامج الثابتة لكل لوحة مدعومة موصوفة هنا:
الكود المصدري موجود في دليل src. سيقوم بتحميل صورة FAT، وعرضها عبر منفذ TCP، وتسجيل كل وصول يتم إجراؤه على الصورة. لطباعة معلومات الملفات والأدلة، تعتمد الأداة على مكتبة TheSleuthKit.
للبناء، قم بتشغيل الأمر التالي في الدليل الجذر
جلب جميع النماذج الفرعية
git submodule update --init --recursive
ثم قم بتشغيل أمر إعداد waf.
./waf configure
سيتم التحقق من جميع التبعيات وبناؤها، ثم لتشغيل البناء الفعلي للمشروع قم بتشغيل
./waf build
سيكون الملف الثنائي في دليل wbuild
يمكننا القيام بذلك بسهولة باستخدام حزمة أدوات mtools
إنشاء ملف بحجم 2 ميجابايت
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 للهدف.
لمحاكاة جهاز 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
إذا كنت ترغب في تنفيذ منطقك الخاص لكل حدث قراءة/كتابة، يمكنك القيام بذلك بسهولة في بايثون.
قم بتنفيذ فئة 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")
وقم بتشغيل الأداة مع وحدة البايثون الخاصة بك.
./usb-spy --py python/dummy.py disk.img
يمكنك أيضاً تمرير معاملات عشوائية من سطر الأوامر إلى فئة البايثون الخاصة بك. المعاملات متاحة في kwargs.
./usb-spy --py python/dummy.py --py-args arg1=2 --py-args arg2=Hello disk.img
يمكنك أيضاً البدء من مثال rawimage الذي يوفر تطبيقاً كاملاً (~100 سطر من الكود) لما تم تنفيذه أصلاً في الثنائي usb-spy.
هذا المشروع مقدم "كما هو". لا يوجد ضمان للصحة أو الأمان أو الملاءمة لأي غرض محدد.
استخدم الأدوات والبرامج الثابتة على مسؤوليتك الخاصة. المؤلف والمساهمون ليسوا مسؤولين عن أي ضرر أو فقدان بيانات أو عواقب قانونية قد تنشأ عن استخدام هذا البرنامج أو الجهاز.
المساهمات مرحب بها! يرجى اتباع هذه الخطوات:
هذا المشروع مرخص بموجب رخصة GNU العامة العامة الإصدار 3.0. راجع ملف LICENSE للحصول على التفاصيل.