وحيد القرن داخل القط - قم بتشغيل البرامج الثابتة في محاكي Kopycat


في إطار الاجتماع 0x0A DC7831 DEF CON نيجني نوفغورود في 16 فبراير قدمنا ​​تقريرًا عن المبادئ الأساسية لمضاهاة الكود الثنائي وتطويرنا - محاكي لمنصات الأجهزة Kopycat .


في هذه المقالة ، سوف نصف إطلاق البرنامج الثابت للجهاز في المحاكي ، وإظهار التفاعل مع المصحح وإجراء تحليل ديناميكي صغير للبرنامج الثابت.


قبل التاريخ


منذ زمن طويل في مجرة ​​بعيدة


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


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


وكانت النتيجة محاكي أنظمة الحوسبة Kopycat .



لماذا كوبيكات؟

هناك مسرحية على الكلمات.


  1. copycat (الإنجليزية ، n. [ɒkɒpɪkæt]) - تقليد ، تقليد
  2. قطة (الإنجليزية ، n. []kæt]) - قطة ، قطة - حيوان مفضل لأحد المبدعين في المشروع
  3. رسالة "K" - من لغة البرمجة Kotlin

Kopycat


عند إنشاء المحاكي ، تم تحديد أهداف محددة تمامًا:


  • القدرة على إنشاء محيط ، وحدة نمطية ، معالج جديد بسرعة ؛
  • القدرة على تجميع جهاز افتراضي من وحدات مختلفة ؛
  • القدرة على تحميل أي بيانات ثنائية (البرامج الثابتة) في ذاكرة الجهاز الظاهري ؛
  • القدرة على العمل مع لقطات (لقطات لحالة النظام) ؛
  • القدرة على التفاعل مع المحاكي من خلال مصحح الأخطاء المضمّن ؛
  • لغة حديثة لطيفة لتطوير.

ونتيجة لذلك ، تم اختيار Kotlin للتنفيذ ، وهيكل الحافلة (هذا عندما تتواصل الوحدات مع بعضها البعض عبر حافلات البيانات الافتراضية) ، و JSON كتنسيق وصف الجهاز ، و GDB RSP كبروتوكول للتفاعل مع المصحح.


استمرت التنمية لأكثر من عامين بقليل وهي مستمرة بنشاط. خلال هذا الوقت ، تم تنفيذ النوى MIPS ، x86 ، V850ES ، ARM ، PowerPC.


المشروع ينمو ، وقد حان الوقت لعرضه على الجمهور. سنقدم وصفًا تفصيليًا للمشروع لاحقًا ، ولكن الآن سنركز على استخدام Kopycat.


الأكثر نفاد الصبر - يمكن تنزيل الإصدار الترويجي من المحاكي هنا .


وحيد القرن في المضاهاة


تذكر أنه في وقت سابق من أجل مؤتمر SMARTRHINO-2018 ، تم إنشاء جهاز اختبار "وحيد القرن" للتدريب على مهارات الهندسة العكسية. تم وصف عملية تحليل البرامج الثابتة الثابتة في هذه المقالة .


الآن دعونا نحاول إضافة "مكبرات صوت" وتشغيل البرامج الثابتة في المحاكي.


سنحتاج:
1) جافا 1.8
2) بيثون وجيب وحدة لاستخدام بيثون داخل المحاكي. يمكن تنزيل مجموعة WHL لوحدة Jep لنظام التشغيل Windows هنا .


لنظام التشغيل Windows:
1) com0com
2) المعجون


لنظام التشغيل Linux:
1) سقراط


يمكنك استخدام Eclipse أو IDA Pro أو radare2 كعميل GDB.


كيف يعمل؟


من أجل أداء البرامج الثابتة في المحاكي ، يجب عليك "تجميع" جهاز افتراضي ، وهو بمثابة جهاز حقيقي.


يمكن عرض الجهاز الحقيقي ("وحيد القرن") في مخطط كتلة:


دارة الجهاز الحقيقي

يحتوي المحاكي على بنية معيارية ويمكن وصف الجهاز الظاهري النهائي في ملف JSON.


JSON على 105 خطوط
{ "top": true, // Plugin name should be the same as file name (or full path from library start) "plugin": "rhino", // Directory where plugin places "library": "user", // Plugin parameters (constructor parameters if jar-plugin version) "params": [ { "name": "tty_dbg", "type": "String"}, { "name": "tty_bt", "type": "String"}, { "name": "firmware", "type": "String", "default": "NUL"} ], // Plugin outer ports "ports": [ ], // Plugin internal buses "buses": [ { "name": "mem", "size": "BUS30" }, { "name": "nand", "size": "4" }, { "name": "gpio", "size": "BUS32" } ], // Plugin internal components "modules": [ { "name": "u1_stm32", "plugin": "STM32F042", "library": "mcu", "params": { "firmware:String": "params.firmware" } }, { "name": "usart_debug", "plugin": "UartSerialTerminal", "library": "terminals", "params": { "tty": "params.tty_dbg" } }, { "name": "term_bt", "plugin": "UartSerialTerminal", "library": "terminals", "params": { "tty": "params.tty_bt" } }, { "name": "bluetooth", "plugin": "BT", "library": "mcu" }, { "name": "led_0", "plugin": "LED", "library": "mcu" }, { "name": "led_1", "plugin": "LED", "library": "mcu" }, { "name": "led_2", "plugin": "LED", "library": "mcu" }, { "name": "led_3", "plugin": "LED", "library": "mcu" }, { "name": "led_4", "plugin": "LED", "library": "mcu" }, { "name": "led_5", "plugin": "LED", "library": "mcu" }, { "name": "led_6", "plugin": "LED", "library": "mcu" }, { "name": "led_7", "plugin": "LED", "library": "mcu" }, { "name": "led_8", "plugin": "LED", "library": "mcu" }, { "name": "led_9", "plugin": "LED", "library": "mcu" }, { "name": "led_10", "plugin": "LED", "library": "mcu" }, { "name": "led_11", "plugin": "LED", "library": "mcu" }, { "name": "led_12", "plugin": "LED", "library": "mcu" }, { "name": "led_13", "plugin": "LED", "library": "mcu" }, { "name": "led_14", "plugin": "LED", "library": "mcu" }, { "name": "led_15", "plugin": "LED", "library": "mcu" } ], // Plugin connection between components "connections": [ [ "u1_stm32.ports.usart1_m", "usart_debug.ports.term_s"], [ "u1_stm32.ports.usart1_s", "usart_debug.ports.term_m"], [ "u1_stm32.ports.usart2_m", "bluetooth.ports.usart_m"], [ "u1_stm32.ports.usart2_s", "bluetooth.ports.usart_s"], [ "bluetooth.ports.bt_s", "term_bt.ports.term_m"], [ "bluetooth.ports.bt_m", "term_bt.ports.term_s"], [ "led_0.ports.pin", "u1_stm32.buses.pin_output_a", "0x00"], [ "led_1.ports.pin", "u1_stm32.buses.pin_output_a", "0x01"], [ "led_2.ports.pin", "u1_stm32.buses.pin_output_a", "0x02"], [ "led_3.ports.pin", "u1_stm32.buses.pin_output_a", "0x03"], [ "led_4.ports.pin", "u1_stm32.buses.pin_output_a", "0x04"], [ "led_5.ports.pin", "u1_stm32.buses.pin_output_a", "0x05"], [ "led_6.ports.pin", "u1_stm32.buses.pin_output_a", "0x06"], [ "led_7.ports.pin", "u1_stm32.buses.pin_output_a", "0x07"], [ "led_8.ports.pin", "u1_stm32.buses.pin_output_a", "0x08"], [ "led_9.ports.pin", "u1_stm32.buses.pin_output_a", "0x09"], [ "led_10.ports.pin", "u1_stm32.buses.pin_output_a", "0x0A"], [ "led_11.ports.pin", "u1_stm32.buses.pin_output_a", "0x0B"], [ "led_12.ports.pin", "u1_stm32.buses.pin_output_a", "0x0C"], [ "led_13.ports.pin", "u1_stm32.buses.pin_output_a", "0x0D"], [ "led_14.ports.pin", "u1_stm32.buses.pin_output_a", "0x0E"], [ "led_15.ports.pin", "u1_stm32.buses.pin_output_a", "0x0F"] ] } 

انتبه إلى معلمة البرنامج الثابت في قسم params - هذا هو اسم الملف الذي يمكن تنزيله على الجهاز الظاهري كبرنامج ثابت.


يمكن تمثيل جهاز افتراضي وتفاعله مع نظام التشغيل الرئيسي على النحو التالي:


جهاز محاكاة الدائرة

تتضمن نسخة الاختبار الحالية للمضاهاة التفاعل مع منافذ COM لنظام التشغيل الرئيسي (تصحيح UART و UART لوحدة Bluetooth). يمكن أن تكون هذه منافذ حقيقية متصلة بها الأجهزة أو منافذ COM افتراضية ( com0com / socat مخصصة لهذا الغرض فقط ) .


يوجد حاليًا طريقتان رئيسيتان للتفاعل مع المحاكي من الخارج:


  • بروتوكول GDB RSP (على التوالي ، يدعم هذا البروتوكول ، الأدوات - Eclipse / IDA / radare2) ؛
  • محاكي سطر الأوامر الداخلي (Argparse أو Python).

منافذ COM الافتراضية


من أجل التفاعل مع UART للجهاز الظاهري على الجهاز المحلي من خلال الجهاز ، تحتاج إلى إنشاء اثنين من منافذ COM الظاهرية المتصلة. في حالتنا ، يستخدم منفذ واحد محاكيًا ، والثاني برنامج محطة (المعجون أو الشاشة):


منافذ COM الافتراضية

باستخدام com0com


يتم تكوين منافذ COM الظاهرية باستخدام أداة الإعداد المساعدة من مجموعة com0com (إصدار وحدة التحكم هو C: \ ملفات البرنامج (x86) \ com0com \ setup.exe ، أو إصدار واجهة المستخدم الرسومية هو C: \ ملفات البرنامج (x86) \ com0com \ setupg.exe ) :


تكوين منافذ COM الافتراضية

تحقق من تمكين خانات الاختيار تجاوز المخزن المؤقت لكافة المنافذ الظاهرية التي تم إنشاؤها ، وإلا فإن المحاكي سوف ينتظر استجابة من منفذ COM.


باستخدام socat


في أنظمة UNIX ، يتم إنشاء منافذ COM الافتراضية تلقائيًا بواسطة المحاكي باستخدام الأداة المساعدة socat. للقيام بذلك ، عند بدء تشغيل المحاكي ، حدد socat: بادئة في اسم المنفذ.


واجهة سطر الأوامر الداخلية (Argparse أو Python)


نظرًا لأن Kopycat هو تطبيق وحدة التحكم ، يوفر المحاكي خيارين لواجهة سطر الأوامر للتفاعل مع الكائنات والمتغيرات: Argparse و Python.


Argparse هي CLI المدمجة في Kopycat ، وهي متوفرة دائمًا للجميع.


CLI البديل هو مترجم Python. لاستخدامها ، تحتاج إلى تثبيت وحدة Jep Python وتكوين المحاكي للعمل مع Python (سيتم استخدام مترجم Python المثبت على النظام الرئيسي للمستخدم).


تثبيت وحدة بيثون جيب


تحت Linux ، يمكن تثبيت Jep عبر نقطة:


 pip install jep 

لتثبيت Jep ضمن Windows ، يجب أولاً تثبيت Windows SDK وبرنامج Microsoft Visual Studio المطابق. لقد قمنا بتبسيط مهمتك قليلاً وجعلنا تجميعات WHL JEP للإصدارات الحالية من Python for Windows ، بحيث يمكن تثبيت الوحدة النمطية من ملف:


 pip install jep-3.8.2-cp27-cp27m-win_amd64.whl 

للتحقق من تثبيت Jep ، يجب تشغيل سطر الأوامر:


 python -c "import jep" 

رداً على ذلك ، يجب استلام رسالة:


 ImportError: Jep is not supported in standalone Python, it must be embedded in Java. 

في ملف الدُفعات المحاكي لنظامك ( kopycat.bat لنظام Windows ، kopycat لنظام التشغيل Linux) أضف المعلمة الإضافية Djava.library.path إلى قائمة معلمات DEFAULT_JVM_OPTS - يجب أن تحتوي على المسار إلى وحدة Jep المثبتة.


نتيجةً لذلك ، بالنسبة لنظام Windows ، يجب أن تحصل على خط مثل هذا:


 set DEFAULT_JVM_OPTS="-XX:MaxMetaspaceSize=256m" "-XX:+UseParallelGC" "-XX:SurvivorRatio=6" "-XX:-UseGCOverheadLimit" "-Djava.library.path=C:/Python27/Lib/site-packages/jep" 

إطلاق Kopycat


المحاكي هو تطبيق JVM وحدة التحكم. يتم الإطلاق من خلال البرنامج النصي لسطر الأوامر لنظام التشغيل (sh / cmd).


الأمر لتشغيل تحت ويندوز:


 bin\kopycat -g 23946 -n rhino -l user -y library -p firmware=firmware\rhino_pass.bin,tty_dbg=COM26,tty_bt=COM28 

أمر التشغيل على Linux باستخدام الأداة المساعدة socat:


 ./bin/kopycat -g 23946 -n rhino -l user -y library -p firmware=./firmware/rhino_pass.bin,tty_dbg=socat:./COM26,tty_bt=socat:./COM28 

  • -g 23646 - منفذ TCP الذي سيكون مفتوحًا للوصول إلى خادم GDB ؛
  • -n rhino - اسم الوحدة الرئيسية للنظام (تجميع الجهاز) ؛
  • -l user - اسم المكتبة للبحث عن الوحدة الرئيسية ؛
  • - -y library - المسار للبحث عن الوحدات النمطية المضمنة في الجهاز ؛
  • firmware\rhino_pass.bin - المسار إلى ملف البرنامج الثابت ؛
  • COM26 و COM28 هي منافذ COM الظاهري.

ستكون النتيجة هي Python > (أو Argparse > ):


 18:07:59 INFO [eFactoryBuilder.create ]: Module top successfully created as top 18:07:59 INFO [ Module.initializeAndRes]: Setup core to top.u1_stm32.cortexm0.arm for top 18:07:59 INFO [ Module.initializeAndRes]: Setup debugger to top.u1_stm32.dbg for top 18:07:59 WARN [ Module.initializeAndRes]: Tracer wasn't found in top... 18:07:59 INFO [ Module.initializeAndRes]: Initializing ports and buses... 18:07:59 WARN [ Module.initializePortsA]: ATTENTION: Some ports has warning use printModulesPortsWarnings to see it... 18:07:59 FINE [ ARMv6CPU.reset ]: Set entry point address to 08006A75 18:07:59 INFO [ Module.initializeAndRes]: Module top is successfully initialized and reset as a top cell! 18:07:59 INFO [ Kopycat.open ]: Starting virtualization of board top[rhino] with arm[ARMv6Core] 18:07:59 INFO [ GDBServer.debuggerModule ]: Set new debugger module top.u1_stm32.dbg for GDB_SERVER(port=23946,alive=true) Python > 

التفاعل مع IDA Pro


لتبسيط الاختبار ، نستخدم البرنامج الثابت لـ Rhino كملف ELF (يتم حفظ المعلومات التعريفية هناك) كملف مصدر للتحليل في IDA.


يمكنك أيضًا استخدام البرامج الثابتة الرئيسية بدون معلومات التعريف.


بعد بدء Kopycat في IDA Pro ، في قائمة Debugger ، انتقل إلى عنصر " Switch debugger ... " وحدد " Remote GDB debugger ". بعد ذلك ، قم بتكوين الاتصال: قائمة المصحح - خيارات العملية ...


اضبط القيم:


  • التطبيق - أي قيمة
  • اسم المضيف: 127.0.0.1 (أو عنوان IP الخاص بالجهاز البعيد حيث تعمل Kopycat)
  • ميناء: 23946

تكوين الاتصال بخادم GDB

الآن يتوفر زر بدء التصحيح (المفتاح F9):



اضغط عليه - يتصل بوحدة تصحيح الأخطاء في المحاكي. ينتقل IDA إلى وضع التصحيح وتصبح هناك نوافذ إضافية متاحة: معلومات حول السجلات ، حول المكدس.


الآن يمكننا استخدام جميع الميزات القياسية للعمل مع المصحح:


  • تنفيذ التعليمات خطوة بخطوة ( الخطوة إلى الخطوة خطوة - المفاتيح F7 و F8 ، على التوالي) ؛
  • البدء وإيقاف التنفيذ ؛
  • إنشاء نقاط توقف على كل من الكود والبيانات (مفتاح F2).

لا يعني الاتصال بمصحح الأخطاء بدء تشغيل رمز البرنامج الثابت. يجب أن يكون الموضع الحالي للتنفيذ هو العنوان 0x08006A74 - بداية وظيفة Reset_Handler . إذا قمت بالتمرير لأسفل القائمة أدناه ، يمكنك رؤية الدعوة إلى الوظيفة الرئيسية . يمكنك وضع المؤشر على هذا السطر (العنوان 0x08006ABE ) وتنفيذ " تشغيل حتى تشغيل المؤشر" (المفتاح F4).


صورة


بعد ذلك ، يمكنك الضغط على المفتاح F7 للدخول إلى الوظيفة الرئيسية .


إذا قمت بتنفيذ أمر متابعة العملية (المفتاح F9) ، فستظهر نافذة "الرجاء الانتظار" مع زر تعليق واحد:



عند الضغط على Suspend ، يتم تعليق تنفيذ رمز البرنامج الثابت ويمكن أن يستمر من نفس العنوان في الكود حيث تمت مقاطعة ذلك.


إذا تابعت تنفيذ التعليمات البرمجية ، فعندئذٍ في المحطات الطرفية المتصلة بمنافذ COM الظاهرية ، يمكنك رؤية الأسطر التالية:


صورة


صورة


يشير وجود السلسلة "تجاوز الحالة" إلى أن وحدة Bluetooth الافتراضية قد تحولت إلى وضع تلقي البيانات من منفذ COM الخاص بالمستخدم.


الآن في محطة Bluetooth (في الشكل - COM29) ، يمكنك إدخال الأوامر وفقًا لبروتوكول الكركدن. على سبيل المثال ، ترجع السلسلة "mur-mur" إلى الأمر "MEOW" في محطة Bluetooth:




محاكاة لي ليس تماما


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


  • جهاز مضاهاة بالكامل مع مجموعة كاملة من الأوامر ؛
  • يتم محاكاة أوامر AT ، ويتم تلقي دفق البيانات من منفذ COM في النظام الرئيسي ؛
  • يوفر الجهاز الظاهري إعادة توجيه البيانات بالكامل إلى جهاز حقيقي ؛
  • كعنصر بسيط يعود دائمًا "موافق".

في الإصدار الحالي من المحاكي ، يتم استخدام الطريقة الثانية - تقوم وحدة Bluetooth الافتراضية بإجراء التكوين ، وبعد ذلك تقوم بالتبديل إلى وضع الوكيل للبيانات من منفذ COM الخاص بالنظام الرئيسي إلى منفذ UART الخاص بالمحاكي.



النظر في إمكانية الأجهزة بسيطة من التعليمات البرمجية إذا لم يتم تنفيذ جزء من المحيط. على سبيل المثال ، إذا لم يتم إنشاء مؤقت يتحكم في نقل البيانات في DMA (يتم إجراء التحقق في وظيفة ws2812b_wait الموجودة في 0x08006840 ) ، 0x08006840 البرامج الثابتة دائمًا الإشارة المزدحمة الموجودة في 0x200004C4 لإعادة تعيين خط بيانات DMA:



يمكننا التحايل على هذا الموقف عن طريق إعادة تعيين العلم المشغول يدويًا فور ضبطه. في IDA Pro ، يمكنك إنشاء وظيفة Python واستدعائها في نقطة توقف ، ويجب تعيين نقطة توقف في الكود بعد كتابة القيمة 1 إلى العلامة المزدحمة .


نقطة توقف معالج


أولاً ، قم بإنشاء دالة Python في المؤسسة الدولية للتنمية. ملف القائمة - القيادة النصي ...


أضف مقتطفًا جديدًا في القائمة الموجودة على اليسار ، واسمه (على سبيل المثال ، BPT ) ،
في مربع النص على اليمين ندخل رمز الوظيفة:


 def skip_dma(): print "Skipping wait ws2812..." value = Byte(0x200004C4) if value == 1: PatchDbgByte(0x200004C4, 0) return False 


بعد ذلك ، انقر فوق " تشغيل" وأغلق إطار البرنامج النصي.


الآن ، دعنا نذهب إلى الكود على 0x0800688A ، قم بتعيين نقطة توقف (مفتاح F2) ، قم بتحريره (قائمة سياق تحرير ... ) ، لا تنسَ ضبط نوع البرنامج النصي - Python:




إذا كانت القيمة الحالية للعلامة مشغول هي 1 ، فيجب تنفيذ وظيفة skip_dma في سطر البرنامج النصي:



إذا قمت بتشغيل البرنامج الثابت للتنفيذ ، فيمكنك رؤية رمز معالج نقطة الإيقاف في المؤسسة الدولية للتنمية في نافذة الإخراج على الخط Skipping wait ws2812... الآن لن تنتظر البرامج الثابتة لإعادة تعيين العلم المشغول .


تفاعل المحاكي


من غير المرجح أن يسبب مضاهاة من أجل مضاهاة البهجة والبهجة. سيكون أكثر إثارة للاهتمام إذا كان المحاكي يساعد الباحث على رؤية البيانات في الذاكرة أو لتأسيس تفاعل التدفقات.


نوضح كيفية تأسيس تفاعل مهام RTOS ديناميكيًا. أولاً ، قم بإيقاف تنفيذ التعليمات البرمجية مؤقتًا إذا كان قيد التشغيل. إذا قمت بالتبديل إلى وظيفة bluetooth_task_entry في فرع معالجة الأمر "LED" (العنوان 0x080057B8 ) ، يمكنك رؤية ما تم إنشاؤه أولاً ، ثم يتم إرسال رسالة إلى قائمة انتظار النظام ledControlQueueHandle .


صورة


يجب عليك تعيين نقطة توقف للوصول إلى متغير ledControlQueueHandle الموجود في 0x20000624 ومتابعة تنفيذ التعليمات البرمجية:



نتيجةً لذلك ، ستتوقف في 0x080057CA على العنوان 0x080057CA قبل استدعاء وظيفة osMailAlloc ، ثم في 0x08005806 قبل الاتصال بوظيفة osMailPut ، ثم بعد فترة من الوقت في العنوان 0x08005BD4 (قبل استدعاء وظيفة osMailGet ) ، التي تنتمي إلى وظيفة leds_task_entry (LED LED) ، أي كان هناك مفتاح مهمة ، والآن تلقى التحكم مهمة LED.


صورة


بهذه الطريقة البسيطة ، يمكنك تحديد كيفية تفاعل مهام RTOS مع بعضها البعض.


بالطبع ، في الواقع ، يمكن أن يكون تفاعل المهام أكثر تعقيدًا ، ولكن استخدام محاكي لتتبع هذا التفاعل يصبح أقل صعوبة.


هنا يمكنك مشاهدة مقطع فيديو قصير لإطلاق المحاكي والتفاعل مع IDA Pro.


إطلاق مع Radare2


لا يمكنك تجاهل أداة عالمية مثل Radare2.


للاتصال بالمحاكي باستخدام r2 ، سيبدو الأمر كما يلي:


 radare2 -A -a arm -b 16 -d gdb://localhost:23946 rhino_fw42k6.elf 

الآن ابدأ ( dc ) وتنفيذ الإيقاف المؤقت (Ctrl + C).


لسوء الحظ ، في الوقت الحالي في r2 ، هناك مشاكل عند العمل مع خادم gdb للأجهزة وترميز الذاكرة ، ولهذا السبب ، لا تعمل نقاط التوقف والخطوات (الأمر ds ). نأمل أن يتم إصلاح هذا في المستقبل القريب.


إطلاق مع الكسوف


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


سوف نستخدم الكسوف من Workbench System for STM32 suite باعتباره IDE.


لكي يتم تحميل البرنامج الثابت المترجم مباشرة في Eclipse إلى المحاكي ، تحتاج إلى إضافة المعلمة firmware=null إلى أمر بدء المحاكي:


 bin\kopycat -g 23946 -n rhino -l user -y library -p firmware=null,tty_dbg=COM26,tty_bt=COM28 

تكوين التصحيح


في Eclipse ، حدد القائمة Run - Debug Configurations ... في النافذة التي تفتح ، في قسم GDB Hardware Debugging ، تحتاج إلى إضافة تكوين جديد ، وبعد ذلك تشير علامة التبويب "Main" إلى المشروع الحالي والتطبيق لتصحيح الأخطاء:



في علامة التبويب Debugger ، يجب عليك تحديد أمر GDB:
${openstm32_compiler_path}\arm-none-eabi-gdb


وأدخل أيضًا المعلمات الخاصة بالاتصال بخادم GDB (المضيف والمنفذ):



يجب تحديد المعلمات التالية في علامة التبويب "بدء التشغيل":


  • تمكين خانة الاختيار تحميل الصورة (بحيث يتم تحميل صورة البرامج الثابتة المجمعة في المحاكي) ؛
  • تمكين علامة تحميل الرموز ؛
  • إضافة أمر بدء: set $pc = *0x08000004 (قم بتعيين القيمة من الذاكرة إلى سجل الكمبيوتر على العنوان 0x08000004 - يتم تخزين عنوان 0x08000004 هناك).

يرجى ملاحظة أنه إذا كنت لا ترغب في تنزيل ملف البرنامج الثابت من Eclipse ، فلن تحتاج إلى تحديد معلمات تحميل صورة وتشغيل .



بعد النقر فوق Debug ، يمكنك العمل في وضع التصحيح:


  • تنفيذ التعليمات البرمجية خطوة بخطوة
  • التفاعل مع نقاط التوقف

المذكرة. يحتوي Eclipse على بعض الميزات ... وعليك أن تعيش معهم. على سبيل المثال ، إذا ظهرت الرسالة "No source available for" 0x0 "" عند بدء تشغيل المصحح ، فقم بتشغيل الأمر Step (F5)



بدلا من الاستنتاج


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


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


اكتب التعليقات حول تجربتك مع استخدام برامج محاكاة الأجهزة. نحن ندعوك إلى مناقشة وسنكون سعداء للإجابة على الأسئلة.

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


All Articles