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

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

كجزء من الاجتماع 0x0A DC7831 ديف كون نيجني نوفغورود في 16 فبراير، قدمنا ​​تقريرًا عن المبادئ الأساسية لمحاكاة الكود الثنائي وتطويرنا - محاكي النظام الأساسي للأجهزة مقلد.

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

قبل التاريخ

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

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

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

وكانت النتيجة محاكي أنظمة الكمبيوتر مقلد.

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

هناك اللعب على الكلمات.

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

مقلد

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

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

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

لقد استمر التطوير منذ ما يزيد قليلاً عن عامين وهو مستمر بنشاط. خلال هذا الوقت، تم تنفيذ نوى معالجات MIPS وx86 وV850ES وARM وPowerPC.

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

بالنسبة لمن نفاد صبرهم، يمكن تنزيل نسخة ترويجية من المحاكي من هنا صلة.

وحيد القرن في المحاكي

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

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

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

للنوافذ:
1) com0com
2) المعجون

لنظام التشغيل Linux:
1) سوكات

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

كيف يعمل؟

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

يمكن إظهار الجهاز الحقيقي ("وحيد القرن") في المخطط التفصيلي:

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

يحتوي المحاكي على بنية معيارية ويمكن وصف الجهاز الظاهري النهائي في ملف 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 هو اسم الملف الذي يمكن تحميله على جهاز افتراضي كبرنامج ثابت.

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

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

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

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

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

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

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

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

باستخدام com0com

يتم تكوين منافذ COM الافتراضية باستخدام أداة الإعداد المساعدة من مجموعة com0com (إصدار وحدة التحكم - ج: ملفات البرنامج (x86)com0comsetupс.exe، أو إصدار واجهة المستخدم الرسومية - ج: ملفات البرنامج (x86)com0comsetupg.exe):

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

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

باستخدام سوكات

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

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

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

Argparse عبارة عن واجهة سطر الأوامر (CLI) مدمجة في Kopycat وهي متاحة دائمًا للجميع.

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

تثبيت وحدة بايثون Jep

ضمن Linux يمكن تثبيت Jep عبر النقطة:

pip install jep

لتثبيت Jep على Windows، يجب عليك أولاً تثبيت Windows SDK وMicrosoft Visual Studio المقابل. لقد جعلنا الأمر أسهل قليلا بالنسبة لك و يبني WHL JEP للإصدارات الحالية من Python لنظام التشغيل 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.

في الملف الدفعي للمحاكي لنظامك (Copycat.bat - للنوافذ، مقلد - لنظام Linux) إلى قائمة المعلمات DEFAULT_JVM_OPTS إضافة معلمة إضافية Djava.library.path - يجب أن يحتوي على المسار إلى وحدة 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"

إطلاق كوبيكات

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

أمر للتشغيل تحت نظام التشغيل Windows:

binkopycat -g 23946 -n rhino -l user -y library -p firmware=firmwarerhino_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 — مسار البحث عن الوحدات المضمنة في الجهاز؛
  • firmwarerhino_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 برو

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

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

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

تعيين القيم:

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

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

أصبح الآن زر التصحيح متاحًا (مفتاح F9):

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

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

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

  • تنفيذ التعليمات خطوة بخطوة (خطوة الى и خطوة أكثر — المفاتيح F7 وF8، على التوالي)؛
  • بدء التنفيذ وإيقافه مؤقتًا؛
  • إنشاء نقاط توقف لكل من التعليمات البرمجية والبيانات (مفتاح F2).

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

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

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

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

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

عندما تضغط تعليق يتم تعليق تنفيذ رمز البرنامج الثابت ويمكن متابعته من نفس العنوان في الكود الذي تمت مقاطعته فيه.

إذا واصلت تنفيذ التعليمات البرمجية، فسترى الأسطر التالية في المحطات المتصلة بمنافذ COM الافتراضية:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

أولاً، لنقم بإنشاء دالة بايثون في IDA. قائمة طعام ملف - أمر البرنامج النصي...

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

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

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

بعد ذلك نضغط يجري وأغلق نافذة البرنامج النصي.

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

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

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

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

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

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

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

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

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

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

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

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

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

بهذه الطريقة البسيطة يمكنك تحديد كيفية تفاعل مهام 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. يمكنك تنزيل مصادر البرامج الثابتة من هنا.

سوف نستخدم Eclipse من المجموعة باعتباره IDE منضدة النظام لـ STM32.

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

binkopycat -g 23946 -n rhino -l user -y modules -p firmware=null,tty_dbg=COM26,tty_bt=COM28

إعداد تكوين التصحيح

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

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

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

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

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

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

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

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

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

بعد النقر فوق Debug، يمكنك العمل في وضع مصحح الأخطاء:

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

لاحظ. لدى Eclipse، حسنًا... بعض المراوغات... وعليك أن تتعايش معها. على سبيل المثال، إذا ظهرت الرسالة "لا يوجد مصدر متاح لـ "0x0"" عند بدء تشغيل مصحح الأخطاء، فقم بتنفيذ أمر الخطوة (F5)

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

بدلا من خاتمة

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

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

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

يمكن للمستخدمين المسجلين فقط المشاركة في الاستطلاع. تسجيل الدخول، من فضلك.

لماذا تستخدم المحاكي؟

  • أقوم بتطوير (تصحيح) البرامج الثابتة

  • أنا أبحث عن البرامج الثابتة

  • أقوم بتشغيل الألعاب (Dendi، Sega، PSP)

  • شيء آخر (اكتب في التعليقات)

صوت 7 مستخدمًا. امتنع 2 مستخدما عن التصويت.

ما البرنامج الذي تستخدمه لمحاكاة الكود الأصلي؟

  • كيمو

  • محرك يونيكورن

  • بروتيوس

  • شيء آخر (اكتب في التعليقات)

صوت 6 مستخدمًا. امتنع 2 مستخدما عن التصويت.

ما الذي ترغب في تحسينه في المحاكي الذي تستخدمه؟

  • أريد السرعة

  • أريد سهولة الإعداد/الإطلاق

  • أريد المزيد من الخيارات للتفاعل مع المحاكي (واجهة برمجة التطبيقات، الخطافات)

  • أنا سعيد بكل شيء

  • شيء آخر (اكتب في التعليقات)

صوّت 8 مستخدمًا. امتنع مستخدم واحد عن التصويت.

المصدر: www.habr.com

إضافة تعليق