نكتب برامج تشغيل USB للأجهزة المهجورة



في الآونة الأخيرة على موقع eBay ، صادفت مجموعة من أجهزة USB المثيرة للاهتمام (Epiphan VGA2USB LR) ، والتي تتلقى مدخلات VGA وإرسال الفيديو إلى USB ككاميرا ويب. لقد سُررت بفكرة أنني لن أضطر أبدًا إلى القلق مع شاشات VGA مرة أخرى ، وبالنظر إلى الدعم المعلن لنظام Linux ، انتهزت فرصة واشتريت المجموعة بالكامل مقابل حوالي 20 جنيهًا (25 دولارًا أمريكيًا).

بعد تلقي الحزمة ، قمت بتوصيل الجهاز ، لكنه لم يفكر حتى في الظهور في النظام على أنه UVC . ما هو الخطأ؟

لقد درست موقع الشركة المصنعة ووجدت أن هناك حاجة إلى سائق خاص للعمل. بالنسبة لي ، كان هذا مفهومًا جديدًا ، نظرًا لأن نواة توزيع Linux لدي عادة برامج تشغيل لجميع الأجهزة.

لسوء الحظ ، انتهى دعم برنامج التشغيل لهذه الأجهزة في نظام التشغيل Linux 4.9. وبالتالي ، لن يشاهدها أي من أنظمةي (Debian 10 على Linux 4.19 أو أحدث إصدار من LTS Ubuntu على Linux 5.0).

ولكن يمكن أن تكون ثابتة ، أليس كذلك؟ بالطبع ، تأتي الملفات في حزمة DKMS ، والتي تجمع ، عند الطلب ، برنامج التشغيل من الكود المصدري ، مثل العديد من برامج التشغيل العادية ...

إنه لأمر محزن. ولكن هنا ليس كذلك.

داخل الحزمة كان فقط vga2usb.o ثنائي precompiled. لقد بدأت في دراستها ، وأتساءل عن مدى تعقيد الهندسة العكسية ، ووجدت بعض الخطوط المهمة:

 $ strings vga2usb.ko | grep 'v2uco' | sort | uniq v2ucom_autofirmware v2ucom_autofirmware_ezusb v2ucom_autofirmware_fpga 

فهل هو حقا FPGA على اساس العصا؟ كيف تصنع شيئا مثل هذا العمل؟

آخر اكتشاف مضحك ومقلق بعض الشيء هو الخط مع المعلمات الخاصة DSA المفتاح. هذا جعلني أتساءل: ما الذي يمكن أن يحمي داخل السائق؟

 $ strings vga2usb.ko | grep 'epiphan' | sort | uniq epiphan_dsa_G epiphan_dsa_P epiphan_dsa_Q 

لدراسة برنامج التشغيل في بيئته العادية ، التقطت جهازًا افتراضيًا من Debian 9 (الإصدار الأخير المدعوم) وأعدت KVM USB Passthrough لتوفير وصول مباشر إلى الجهاز. ثم قمت بتثبيت برنامج التشغيل وتأكد من أنه يعمل.

بعد ذلك ، أردت أن أرى كيف يبدو بروتوكول الاتصال. كنت آمل أن يرسل الجهاز إطارات أولية أو شبه أولية ، لأن ذلك سيجعل من الأسهل كتابة برنامج تشغيل لمساحة المستخدم.

للقيام بذلك ، قمت بتحميل وحدة usbmon على usbmon الجهاز الظاهري وأطلقت Wireshark لالتقاط حركة مرور USB من وإلى الجهاز أثناء بدء التشغيل والتقاط الفيديو.



لقد وجدت أنه عند إطلاقه ، يتم نقل عدد كبير من الحزم الصغيرة إلى الجهاز قبل أن يبدأ في التقاط الصورة. من المرجح أن يعتمد على منصة FPGA بدون تخزين البيانات. في كل مرة بعد الاتصال ، يقوم برنامج التشغيل بنقل البرنامج الثابت في شكل تيار بتنسيق FPGA إلى الجهاز.

كنت مقتنعا بذلك من خلال فتح أحد الصناديق:



أحمر

ISL98002CRZ-170 - يعمل ADC لإشارات VGA

أصفر

XC6SLX16 - Xilinx Spartan 6 FPGA

اليانوجين غاز سام سريع الإشتعال

64 ميغابايت DDR3

أرجواني

CY7C68013A - وحدة تحكم USB / الواجهة الأمامية


نظرًا لقيامك "بتنزيل" الجهاز الذي تريد إرساله إليه ، فإنه يجب عليك البحث عنه في ثنائيات مُجمَّعة مسبقًا. قمت بتشغيل binwalk -x وبدأت في البحث عن بعض الكائنات المضغوطة (zlib). للقيام بذلك ، كتبت نص بحثًا عن تسلسل سداسي عشرية - وحددت ثلاث بايتات من الحزمة التي تم اعتراضها.

 $ bash scan.sh "03 3f 55" trying 0.elf trying 30020 trying 30020.zlib trying 30020.zlib.decompressed ... trying 84BB0 trying 84BB0.zlib trying 84BB0.zlib.decompressed trying AA240 trying AA240.zlib trying AA240.zlib.decompressed 000288d0 07 2f 03 3f 55 50 7d 7c 00 00 00 00 00 00 00 00 |./.?UP}|........| trying C6860 trying C6860.zlib 

بعد تفريغ ملف AA240.zlib ، اتضح أنه لم تكن هناك بيانات كافية لدفق البت الكامل. لذلك قررت الاستيلاء على البرامج الثابتة من حزم USB.

يمكن لكل من tshark و tcpdump قراءة حزم USB من ملفات pcap ، لكن كلاهما يحفظها جزئيًا فقط. نظرًا لأن كل أداة مساعدة تحتوي على أجزاء مختلفة من اللغز ، فقد كتبت برنامجًا صغيرًا يجمع بين إخراج كلا البرنامجين في هياكل الانتقال من أجل تشغيل الحزم مرة أخرى على الجهاز.

في هذه المرحلة ، لاحظت أن التنزيل يتم على مرحلتين: أولاً وحدة تحكم USB ، ثم FPGA.

لقد تعطلت لعدة أيام: يبدو أن مجرى البتات بأكمله كان قيد التحميل ، لكن الجهاز لم يبدأ ، على الرغم من أن الحزم من برنامج التشغيل الحقيقي والمحاكاة تبدو متشابهة.

في النهاية ، قمت بحل المشكلة عن طريق فحص pcap بعناية مع مراعاة وقت الاستجابة لكل حزمة - ولاحظت فارق التوقيت الكبير في حزمة واحدة محددة:



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

ومع ذلك ، يومض المصباح أخيرًا على الجهاز! إنجاز ضخم!


لقد كان من السهل نسبيًا تكرار نفس الحزم التي أدت إلى نقل البيانات ، لذا فقد تمكنت من كتابة نقطة النهاية لـ USB Bulk ومسح البيانات إلى القرص على الفور!

هذا هو المكان الذي بدأت الصعوبات الحقيقية. لأنه بعد التحليل اتضح أن البيانات لم يتم ترميزها بشكل واضح بأي طريقة.

للبدء ، ركضت بشكل مثالي للحصول على فكرة أساسية عن تتبع مكدس السائق في وقت التشغيل:



على الرغم من أنني أستطيع التقاط وظائف ببيانات الإطار ، إلا أنني لم أستطع فهم تشفير البيانات نفسها.



لفهم ما يجري داخل برنامج التشغيل الحقيقي بشكل أفضل ، جربت أداة Ghidra من NSA:



على الرغم من أن Ghidra لا تصدق (عندما استخدمتها لأول مرة بدلاً من IDA Pro) ، إلا أنها لا تزال غير جيدة بما يكفي لمساعدتي في فهم برنامج التشغيل. الهندسة العكسية تتطلب مسارًا مختلفًا.

قررت التقاط الجهاز الظاهري لنظام التشغيل Windows 7 وإلقاء نظرة على برنامج تشغيل Windows ، وفجأة سوف يطرح الأفكار. ثم لاحظت وجود SDK للأجهزة. تحولت إحدى الأدوات إلى اهتمام خاص:

 PS> ls Directory: epiphan_sdk-3.30.3.0007\epiphan\bin Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 10/26/2019 10:57 AM 528384 frmgrab.dll -a--- 10/27/2019 5:41 PM 1449548 out.aw -a--- 10/26/2019 10:57 AM 245760 v2u.exe -a--- 10/26/2019 10:57 AM 94208 v2u_avi.exe -a--- 10/26/2019 10:57 AM 102400 v2u_dec.exe -a--- 10/26/2019 10:57 AM 106496 v2u_dshow.exe -a--- 10/26/2019 10:57 AM 176128 v2u_ds_decoder.ax -a--- 10/26/2019 10:57 AM 90112 v2u_edid.exe -a--- 10/26/2019 10:57 AM 73728 v2u_kvm.exe -a--- 10/26/2019 10:57 AM 77824 v2u_libdec.dll PS> .\v2u_dec.exe Usage: v2u_dec <number of frames> [format] [compression level] <filename> - sets compression level [1..5], - captures and saves compressed frames to a file v2u_dec x [format] <filename> - decompresses frames from the file to separate BMP files 

تتيح لك هذه الأداة "التقاط" إطارات مفردة ، وفي البداية لا يتم ضغطها ، بحيث يمكن معالجة الإطارات لاحقًا على جهاز أسرع. هذا مثالي تقريبًا ، ولقد قمت بنسخ تسلسل حزم USB للحصول على هذه النقاط غير المضغوطة. عدد البايتات تقابل حوالي ثلاثة (RGB) لكل بكسل!

أعطت المعالجة الأولية لهذه الصور (مجرد قبول الإخراج وكتابتها على شكل وحدات بكسل RGB) شيئًا غامضًا يذكرنا بالصورة الحقيقية التي تلقاها الجهاز عبر VGA:



بعد تصحيح الأخطاء في محرر hex ، اتضح أن كل علامة تتكرر كل 1028 بايت. انها محرجة قليلا كم من الوقت قضيت في كتابة مرشح. من ناحية أخرى ، في هذه العملية يمكن للمرء أن يستمتع ببعض أمثلة الفن المعاصر.



ثم أدركت أن ميل الصورة وتشويهها ناتج عن تخطي الالتفاف بالبكسل على كل سطر (x = 799 لا تساوي x = 800). ثم ، أخيرًا ، حصلت على صورة صحيحة تقريبًا ، باستثناء اللون:



في البداية ، اعتقدت أن مشكلة المعايرة كانت بسبب أخذ عينات البيانات عندما كان إدخال VGA عالقًا بلون خالص. لتصحيح ، قمت بعمل صورة اختبار جديدة لتحديد هذه المشاكل. بعد فوات الأوان ، أدركت أنه كان عليك استخدام شيء مثل بطاقة اختبار Philips PM5544 .



لقد حمّلت الصورة إلى كمبيوتر محمول ، وأنتجت صورة VGA هذه:



ثم حصلت على ذكرى بعض الأعمال القديمة في عرض / تظليل ثلاثي الأبعاد. كان مشابها جدا لنظام الألوان YUV .

كنتيجة لذلك ، انغمس في قراءة أدب YUV وتذكرت أنه خلال الهندسة العكسية للسائق الرسمي للنواة ، إذا وضعت نقطة توقف على وظيفة تسمى v2ucom_convertI420toBGR24 ، فإن النظام سوف يتجمد دون إمكانية التجديد. لذلك ربما كان الإدخال هو ترميز I420 (من -pix_fmt yuv420p ) ، وكان الإخراج RGB؟

بعد استخدام وظيفة Go المضمنة YCbCrToRGB ، أصبحت الصورة فجأة أقرب إلى الأصل.



لقد فعلنا ذلك! حتى السائق الخام أنتج 7 إطارات في الثانية. بصراحة ، هذا يكفي بالنسبة لي ، لأنني أستخدم VGA فقط في حالة وقوع حادث كعرض نسخ احتياطي.

الآن ، نحن نعرف هذا الجهاز جيدًا بما يكفي لشرح الخوارزمية لبدء تشغيله من البداية:

  1. تحتاج إلى تهيئة وحدة تحكم USB . استنادا إلى كمية المعلومات ، في الواقع ، يقوم السائق بتمرير الرمز إليه لتنزيله.
  2. عند الانتهاء من تحميل USB ، سينقطع الجهاز عن ناقل USB وبعد لحظة سيعود بنقطة نهاية USB واحدة.
  3. يمكنك الآن إرسال تدفق البتات FPGA ، حزمة USB سعة 64 بايت لكل عملية نقل للتحكم.
  4. في نهاية النقل ، سيومض المؤشر الموجود على الجهاز باللون الأخضر. في هذه المرحلة ، يمكنك إرسال ما يبدو كسلسلة من المعلمات (الخصائص الزائدة وغيرها من الخصائص).
  5. ثم قم بتشغيل حزمة التحكم للحصول على الإطار ، الحزمة المحددة إذن. إذا قمت بإرسال طلب لإطار 4: 3 لإدخال الشاشة العريضة ، فعادةً ما يؤدي ذلك إلى تلف الإطار.

لسهولة الاستخدام القصوى ، قمت بتنفيذ خادم ويب صغير في برنامج التشغيل. من خلال MediaRecorder API المستندة إلى المستعرض ، فإنه يسجل الدفق بسهولة من الشاشة إلى ملف فيديو.



منع الإدعاءات الحتمية لجودة الشفرة التجريبية ، سأقول على الفور: أنا لست فخوراً بذلك. ربما ، هو في مثل هذه الحالة ، وهو ما يكفي بالنسبة لي للاستخدام مقبول.

توجد التعليمات البرمجية والبنيات الجاهزة لنظامي التشغيل Linux و OSX على GitHub .

حتى لو لم يبدأ أي شخص البرنامج ، فقد كان بالنسبة لي بمثابة رحلة مثيرة عبر بروتوكولات USB ، وتصحيح الأخطاء في النواة ، وعكس هندسة الوحدة النمطية وتنسيق فك ترميز الفيديو! إذا كنت تحب هذه الأشياء ، فيمكنك التحقق من مشاركات المدونة الأخرى .

Source: https://habr.com/ru/post/ar476434/


All Articles