الهندسة العكسية للبرامج الثابتة للجهاز باستخدام مثال "وحيد القرن" الوامض. الجزء 2


نقدم انتباهكم إلى الجزء الثاني من مقالة الهندسة العكسية لبرنامج Flashing Rhino الثابت المستند إلى ورشة عمل في مؤتمر SMARTRHINO-2018 .

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

في الجزء الثاني ، سيتم إجراء تحليل لمهام البرامج الثابتة المتبقية.

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

ملف البرنامج الثابت متاح للدراسة المستقلة.

يتم توفير جميع المعلومات للأغراض التعليمية فقط.

تحت القطة هناك الكثير من وحيد القرن وامض.

مهمة LED


باختصار: تحليل كامل للمهمة المسؤولة عن تبديل المصابيح. تحليل أنواع البيانات والمتغيرات العالمية.

يتم تمثيل مهمة LED بواسطة دالة x_leds_task الموجودة في 0x08005A08 .

بالإضافة إلى الخطوط الغريبة "لدي قوة خارقة ..." في الوظيفة الرئيسية لمهمة LED ، يمكنك الانتباه إلى السطر "hue> max: change shine \ r \ n" .



في الوقت نفسه ، نرى حالة مألوفة - (WORD *) (آية ٢٦ + ٤). في قائمة السياق للمتغير v26 ، حدد العنصر "تحويل إلى بنية *" ، ثم حدد البنية التي تم إنشاؤها مسبقًا:



بالنظر إلى أن v5 = v26 ، فإننا نكرر عملية "التحويل إلى البنية *" للمتغير v5.

نواصل هيكلة الكود والبيانات. تعيين التمثيل السداسي في كل مكان. إعادة التسمية:

  • v5 - بقيادة ؛
  • الإصدار 6 - idx ؛
  • الإصدار 8 - hue_1 ؛
  • الإصدار 9 - hue_2 ؛
  • الإصدار 26 - _led ؛

الكود يتحسن. لكن بعض المتغيرات لا تزال تؤذي العين ، على سبيل المثال ، المتغير v23:





على ما يبدو ، v23 عبارة عن صفيف من 4 بايت.
idx هو مؤشر LED. يضاف هذا الفهرس إلى العنوان الأساسي ؛ بهذه الطريقة ، يتم الوصول إلى العناصر في نفس عمليات الإزاحة - هذه هي الطريقة التي تتصرف بها المصفوفات.

نحن نعين النوع char v23[4] ونعيد تسميته إلى leds_smth ، ويصبح الكود أجمل:



يمكنك أيضًا ملاحظة أن نتيجة دالة x_queue_recv يتم إرجاعها إلى المتغير v25:

 x_queue_recv(&v25, leds_queue, 1000); 

ولكن قد لا يكون من الواضح كيف تكون البيانات التي تحتاجها في البنية _led . والحقيقة هي أن المتغيرين v25 و _led يقعان بالقرب من المكدس - ويمكن فهم ذلك من خلال حقيقة أنهما في الملف المترابط يتم كتابتهما في السطور المجاورة. يمكن رؤية موقع المتغيرات على المكدس في نافذة منفصلة إذا قمت بالنقر المزدوج على المتغير:



ربما تكون بنية ، أو قام المترجم ببعض التحسين. وبالتالي ، يمكن القول أن البيانات من مهمة Bluetooth يتم إرسالها إلى مهمة LED. لمعرفة أكثر دقة ، سوف أتحقق من الجهاز - للحصول على مؤشر LED صفر عبر Bluetooth ، سأرسل القيم 0x208 ، 0x2D0 ، 0x398 ، 0x3E9 ، والتي يمكن ملاحظتها في الرمز:



نتائج التحقق من قيمة الصبغة على الجهاز:

  • 0x208 - توقفت مؤشرات LED عن التبديل بسلاسة وتم تعيينها في الألوان: الأحمر والأخضر والأزرق والأرجواني ؛
  • 0x2D0 - بدأت المصابيح في التبديل مرة أخرى ؛
  • 0x398 - لم يتغير شيء ؛
  • 0x3E9 - لم يتغير شيء.

إذا نظرت إلى الرمز مرة أخرى ، يمكنك أن ترى أنه يمكن ربط القيمة 0x398 منطقيًا بقيمة أقل من 0x167 (يتم تعيين قيم مختلفة لعنصر الصفيف leds_smth ). لذلك ، سأقوم بإجراء هذا الفحص: أولاً ، سأقوم بتعيين أول LED إلى اللون الأخضر (hue = 0x78 ، LED 010078FF20 ) ، بينما تستمر المصابيح الثلاثة الأخرى في تبديل ألوانها.


الآن سأقوم LED 010398FFFF بروتوكول Bluetooth LED 010398FFFF - بعد ذلك تحول LED الأول إلى وضع تبديل اللون العام.

وبالتالي ، فإن قيمة الصبغة 0x398 تعيد تعيين قيمة اللون الثابتة ، مما يعني أن الصفيف leds_smth يحتوي على أعلام (0 أو 1) لشغل مصابيح LED:

  • 0 - LED غير مشغول ، يشارك في التبديل السلس للألوان ( hue = 0x398 ) ؛
  • 1 - الصمام مشغول ، يقوم المستخدم بتعيين لون ثابت (صبغة <= 0x167 ).

إعادة تسمية leds_smth إلى leds_busy .

الآن يجب أن يكون الغرض من كتلة التعليمات البرمجية التالية واضحًا:



تؤدي الدورة في الخطوط 83-101 فسيفساء ألوان ناعمة مع خطوة تبديل اللون من 5: v12 += 5 . إذا كان مؤشر LED يحتوي على لون ثابت قيد التشغيل ، فإن هذا المؤشر لا يشارك في الفسيفساء. بعد الدورة ، توجد خطوط لإدراج جميع مصابيح LED على المدى القصير.

إعادة التسمية:

  • sub_800678A - x_led_set_hsv ؛
  • الإصدار 12 - hue_step ؛
  • v13 ، v17 ، v18 ، v19 - led0_busy ، led1_busy ، led2_busy ، led3_busy ؛
  • v11 ، v20 ، v21 ، v22 - hue0 ، hue1 ، hue2 ، hue3 ؛
  • dword_200004C4 - led_control .

من المفترض أن تؤدي وظيفة sub_80039FE مهلة (وإلا لم تتغير مصابيح LED بسلاسة ، ولكن على الفور) ، فلنطلق عليها x_sleep ، والمتغير v16 هو led_timeout .

الغرض من وظيفة sub_8006934 ليس واضحًا بعد ، ولكن يتم استخدامه في كل مكان بعد تعيين اللون على مصابيح LED - يمكنك تسميتها بـ x_led_fix_color .

بعد إعادة التسمية هذه ، من السهل فهم الوظيفة sub_8006944 (التي يتم استدعاؤها في الصبغة <= 0x167 الفرع):



يقوم ببساطة بإجراء فحص إضافي لتحديد لون LED. أعد تسمية الوظيفة sub_8006944 إلى x_led_set_hsv_wrap (اللاحقة _wrap - توضيح أن هذا "غلاف" على وظيفة أخرى) وقم بتعيين النموذج الأولي الخاص به:

 signed int __fastcall x_led_set_hsv_wrap(int led_control, signed int idx, int hue, char sat, char val) 

دعنا نرجع مستوى واحد إلى وظيفة x_leds_task. مرة أخرى بالنظر إلى الرمز ، يمكنك أن تجد أن الفرع "hue> 0x3E8" بدأ يبدو كما يلي:



بمعنى ، يجب أن تغير قيمة الصبغة الأكبر من 0x3E8 مهلة الفسيفساء الملونة. سوف أتحقق من خلال إرسال بعض القيم إلى الجهاز:

  • hue = 0x3E9 - بدأت مصابيح LED بالتبديل بسرعة:


  • hue = 0xFFFF - بدأت مصابيح LED في التبديل ببطء شديد:



عند الخروج من الدورة الرئيسية لمهمة LED ، يتم استخدام وظيفة sub_8003C44 ، والتي تُستخدم أيضًا في وظيفة sub_8005070:



إعادة التسمية:

  • sub_8005070 - x_freeMsg ؛
  • sub_8003C44 - x_free_queue .

علاوة على ذلك ، في مهمة LED ، لا يمكن للفرع التالي إلا جذب الانتباه:



يمكنك محاولة تنفيذ الأمر LED B816D8D90000FFFF . ولكن إذا تذكرت أنه تم أخذ حرفين فقط كمؤشر LED ، فمن الواضح أن محاولة الوصول إلى هذا الرمز ستفشل. اترك هذا الخيط لوقت لاحق. أعد تسمية الوظيفة sub_8004AE8 إلى x_mad_blinking ، وحان الوقت لإصلاح توقيع وظيفة x_printf (آخر مرة كتبت فيها توقيعًا خاطئًا):

 void x_printf(const char *format, ...) 

تم تفكيك الدورة الرئيسية لمهمة LED ، ولكن لا يزال هناك رمز في بداية المهمة.

دعونا نلقي نظرة على الرمز:



في السطر 49 ، من المرجح أن يتم التحقق من توفر مؤشرات LED ، وفي حالة حدوث خطأ ، يتم إجراء مكالمة إلى الدالة sub_8004BBC ، والتي تعمل على إيقاف المقاطعات وبدء حلقة لا نهائية يتم فيها استخدام السطر "../Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_gpio.c". على الأرجح ، أنها وظيفة تأكيد أو ما شابه.

إعادة التسمية:

  • sub_8004BBC - x_gpio_assert ؛
  • sub_800698C - x_check_gpio .

سيصبح الغرض من وظيفة sub_8006968 واضحًا إذا نظرت بعناية إلى الجهاز عند تشغيله:


يتم تشغيل مصابيح LED الأربعة معًا باللون الأحمر أولاً ، ثم باللون الأخضر ، ثم باللون الأزرق. بعد ذلك ، يتم تعيينها حسب اللون: 0-أحمر ، 1-أخضر ، 2-أزرق ، 3 بنفسجي. وعندها فقط يبدأون في تبديل الفسيفساء.

نظرًا لأن الفسيفساء تبدأ في دورة المهام الرئيسية ، فمن المنطقي أن تكون الخطوط من 58 إلى 61 قبل الدورة الرئيسية مسؤولة عن تضمين ألوان مختلفة على المدى القصير في مصابيح LED ، والخطوط 52-56 مسؤولة عن تعيين الأحمر والأخضر والأزرق على جميع مصابيح LED في وقت واحد. قم بإعادة تسمية الوظيفة sub_8006968 إلى x_led_all_set_rgb (RGB - على حدس بحت ، وفقًا للوسيطات التي تم تمريرها).

الشذوذ في مهمة LED


باختصار: تحديد وظيفة التعليمات البرمجية التي تحتوي على خطوط غريبة. إنشاء كلمة مرور للجهاز.

لننتقل الآن إلى بداية دالة x_leds_task:



"Eraze" ، "gen" ، "flash" ، "reset" - لماذا هذا كله ؟؟؟

دعونا نحاول معرفة ذلك.

دع sub_80066BC يكون x_leds_task_init .

دعونا نلقي نظرة على sub_8006B38:



مذكرة المياه النقية ، توافق؟



عودة إلى x_leds_task. هناك خطأ ما في نوع المتغير v24:



ارتكبت المؤسسة الدولية للتنمية خطأً قليلاً من النوع ، لكن التعليق بعلامة مكدس يساعدنا. بين المتغيرات v24 و v25 بقدر 12 بايت (0x44 - 0x38). لذلك ، نقوم بإعادة تسمية v24 إلى buf وتعيين النوع unsigned __int8 buf[12] (ستحذر Ida من أن نوع البيانات الجديد أكبر من القديم - نحن نتفق).

التالي. الوظيفة sub_8004CE4:



إعادة تسمية a1 إلى buf ، v1 إلى _buf .

الوظيفة sub_8006B26:



هل تعرفت عليها؟

وإذا كان بدون مكياج؟

بالطبع memcpy . إعادة تسمية.

ثم الغرض من الدالة sub_8004CE4 هو الحصول على بعض البيانات على العنوان 0x08007C00 . بالمناسبة ، يقع هذا العنوان في نطاق عناوين الذاكرة المحمولة لوحدة التحكم الدقيقة (والبرامج الثابتة ، على وجه الخصوص). إعادة تسمية sub_8004CE4 إلى x_read_data_0x08007C00 .

X_leds_task سطر الوظائف 36:

 if ( (unsigned int)buf[0] - 65 > 0x19 ) 

قم بتغيير عرض البيانات (مفتاح R على الرقم 65 ، مفتاح H على الرقم 0x19):

 if ( (unsigned int)buf[0] - 'A' > 25 ) 

بعد القليل من التفكير ، يمكنك أن تفهم أن هذا اختبار لمدى الأبجدية اللاتينية AZ.

بعد ذلك ، باستخدام المطالبات في شكل سلاسل التنسيق ، أعد تسمية:

  • sub_8004C10 - x_erase ؛
  • sub_80059C8 - x_gen ؛
  • sub_8004C84 - x_flash .

لا تعمل وظيفة sub_8003C66 شيئًا رائعًا - فهي تزيد فقط من بعض المتغير العام - إعادة تسمية sub_8003C66 إلى x_smth_inc .

لا تقبل الدالة x_erase بالفعل أي وسيطات - يمكن التحقق من ذلك في أداة التفكيك:



داخل x_erase ، يتم استخدام العنوان المألوف 0x08007C00 ويتم الوصول إلى ثلاث وظائف غير معروفة:



نظرة سريعة على هذه الوظائف الثلاث ، نرى أنها تصل إلى عناوين في النطاق 0x40022000 - 0x400223FF . توضح وثائق وحدة التحكم الدقيقة بوضوح أن هذا هو نطاق "واجهة FLASH" . أي أن وظيفة x_erase تمحو قطعة من ذاكرة الفلاش - رائعة!

على ما يبدو ، تكتب وظيفة x_flash إلى ذاكرة فلاش ، بعد التحقق من طول السطر للكتابة (بالمناسبة ، الحجج a2 و a3 غير ضرورية هنا - سنساعد Idea):



وكل هذا يحدث في "جهاز الإضاءة" ؟؟؟

حسنًا ، ماذا عن وظيفة x_gen ؟ بعد نظرة سريعة وإعادة تسمية المتغيرات ، ستبدو كما يلي:



تبدو الدالة sub_8006CB4 كما يلي:



و sub_8006D10 - مثل هذا:



لا تتراجع عن الرغبة في البحث على الإنترنت عن هذه الثوابت الجميلة غير اللائقة: 0xABCD و 0x1234 و 0xE66D و 0xDEEC و 0x4C957F2D و 0x5851F42D . إذا لم يتم حظر الإنترنت بالكامل بعد ، فربما ستجد هذه الثوابت في المصدر لوظائف عشوائية . لا عجب أن تسمى الوظيفة الأم x_gen.

هذا أيضًا موقف نموذجي للغاية: استدعاء srand () قبل الحلقة ، واستدعاء عشوائي () في الحلقة ، لذا أعد تسميته:

  • sub_8006D10 - x_rand ؛
  • sub_8006CB4 - x_srand.

يمكن للقارئ الفضولي ، من خلال النظر في الدالة sub_8005098 ، معرفة مصدر البذور لوظيفة srand.

وبالتالي ، فإن الدالة x_gen تولد سلسلة عشوائية من الحجم المحدد .

بعد كتابة الخط الذي تم إنشاؤه في ذاكرة فلاش ، يقوم الجهاز بإعادة التشغيل:



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

يمكن اعتبار مهمة LED باستثناء وضع MadBlinking تحليلها.

دعنا ننظر عبر الخطوط إلى المهام الأخرى الموجودة في النظام:



بعد استعادة الروابط إلى السلاسل في التعليمات البرمجية ، يمكنك مشاهدة هذه الصورة:



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



لننفذ عمليات إعادة التسمية المفقودة:

  • sub_80050FC - x_sensor_task ؛
  • sub_8004AAC - x_watchdogTask ؛
  • sub_8005440 - x_uartRxTask .

مهمة المراقبة


لا تقوم هيئة مراقبة المهام بأي شيء مثير للاهتمام بشكل خاص:



إعادة التسمية:

  • dword_200003F8 - wd_variable ؛
  • sub_8001050 - x_update_wd_var .

مهمة UART


باختصار: ابحث عن البيانات والوظائف التي لها روابط من وظائف مختلفة. تحديد الغرض منها.

تتيح لك نظرة سريعة على مهمة UART اكتشاف إرسال البيانات إلى قائمة انتظار غير معروفة محددة بواسطة المتغير unk_200003EC :



بعد استعادة المراجع لهذا المتغير عبر البحث الثنائي ، سنرى أنه بالإضافة إلى x_uartRxTask يتم استخدامه في الرئيسي (هناك قائمة الانتظار التي تم إنشاؤها ، على ما يبدو) وفي الوظيفة غير معروفة حتى الآن sub_80051EC :



إعادة التسمية:

  • sub_80051EC - x_recvMsg_uart_queue ؛
  • unk_200003EC - uart_queue .

راجع المراجع التبادلية لـ x_recvMsg_uart_queue:

  • sub_8005250 ؛
  • x_bluetooth_task.

أولاً ، راجع الدالة sub_8005250 :



بعد التفكير ، أعد تسمية:

  • unk_2000034C - cmd_count ؛
  • a1 - كمد ؛
  • الإصدار 4 - _ سمد ؛
  • الإصدار 6 هو rsp ؛
  • sub_8005250 - x_bluetooth_cmd .

دعونا نرى الآن حيث لا يزال يستخدم x_bluetooth_cmd. جميع الروابط الإضافية فقط من مهمة Bluetooth ، حان الوقت للعودة إليها.

الرجوع إلى مهمة البلوتوث


باختصار: التحليل النهائي لمهمة البلوتوث. ابحث عن التفويض بدون كلمة مرور.



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

الآن sub_8006DBC . لنلق نظرة عليه (تمت إعادة تسمية المتغيرات بالفعل):



باستدعاء وظائف مكتبة C القياسية للعمل مع السلاسل ، سنرى strstr (البحث عن سلسلة فرعية) هنا وإعادة تسميتها بجرأة.

دعنا نذهب من خلال كود الوظيفة x_bluetooth_task - ربما تغير شيء ما هنا منذ آخر زيارة . في هذه العملية ، نقوم بتسمية المتغيرات:

  • الإصدار 2 - _ الحالة ؛
  • الإصدار 3 - data_len .

توجد وظيفة sub_80052E2 بجوارها مباشرة . عن طريق القياس مع الوظائف التي تسحب الأرقام من أمر Bluetooth ، فإنها تسحب سلسلة بطول محدد - دعنا نسميها x_get_str .

نواصل:

  • الإصدار 26 - isEcho ؛
  • الإصدار 6 - meow_str ؛
  • الإصدار 10 - uart_cmd_byte ؛
  • الإصدار 11 - uart_cmd_str ؛
  • الإصدار 12 - str_0 ؛
  • الإصدار 13 - str_1 ؛
  • الإصدار 14 - format_str ؛
  • sub_8000F5C - x_blink_small_led .

الانتهاء بإعادة تسمية سريعة:

  • الإصدار 19 - كلمة المرور ؛ (حيث توجد خطوط حول التفويض وكلمة المرور بجواره)
  • sub_8004CC0 - x_check_password ؛
  • sub_8006AF4 - x_free (نظرًا لأن كلمة المرور و cmd و bt_args تشير إلى كائنات ديناميكية (تحقق من ذلك!) ، يجب تحرير الذاكرة بعد استخدامها) ؛
  • sub_8006DAC - x_strcpy ( جربه !).

استكشف الآن الفروع READ ، WRIT ، AUTP ، SETP .

كما أظهر اختبار على جهاز قيد التشغيل ، يلزم الحصول على إذن لأوامر READ و WRIT و SETP. تقودنا محاولة التفويض باستخدام الأمر AUTP إلى وظيفة x_check_password للتحقق من كلمة المرور:



اتضح أن طول كلمة المرور يجب أن يكون 8 أحرف وأن تتم مقارنة كلمة المرور (في الدالة sub_8006B08) بالبايت في العنوان 0x08007C00 - حيث يتم تخزين سلسلة الأحرف العشوائية AZ.

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

انتبه إلى مكان استخدام متغير auth_flag :



اتضح أنه يتم استخدامه ليس فقط في مهمة Bluetooth. وهنا فقط لم ننظر في مهمة الاستشعار بعد. نذهب هناك.

مهمة الاستشعار


باختصار: ماذا يفعل زر اللمس؟

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



خط لخط ...

  • "TSC٪ d \ r \ n" - يجب أن يجعلك هذا الخط تفكر في وحدة تحكم الاستشعار باللمس لأجهزة التحكم الدقيقة STM32 ؛
  • "AUTH BTN \ r \ n" - زر التفويض ؟؟؟
  • "تعيين AUTH٪ d \ r \ n" - هل تريد تعيين علامة المصادقة؟

دعونا نرى كيف سيتصرف الجهاز إذا ضغطت على زر اللمس (هل أدركت أن وحيد القرن على الساق لديه زر لمس؟):



عند الضغط لفترة وجيزة ، يضيء مصباح LED الأحمر الصغير. مع الضغط لفترة طويلة ، يتم تشغيل هذا الصمام لفترة طويلة.

إذا ربطنا ذلك بالكود ، يمكننا أن نفترض أن الدالة sub_8000708 هي دالة للحصول على الوقت الحالي. ثم ، إذا كان الفرق بين الوقت الحالي وبداية لمس المستشعر أكثر من 1000 (ثانية واحدة) ، فسيتم تشغيل LED لمدة 0xEA60 مللي ثانية (دقيقة واحدة). لكن متغير auth_flag ذو أهمية كبيرة ، والذي تم تعيينه إلى 1 بضغطة طويلة على زر اللمس ، مما يمنح المهاجم الوصول إلى المسؤول عن "تركيبات الإضاءة" للوصول إلى الوظائف المميزة.

وهكذا ، بعد التفويض "عن طريق الزر" ، يمكنك قراءة كلمة المرور المخزنة في الجهاز (الأمر READ) أو الكتابة إلى ذاكرة الوصول العشوائي (وظيفة WRIT) أو تعيين كلمة مرور جديدة (SETP).

يومض بجنون


بإيجاز: هل يمكن تنفيذ فرع رمز Mad Blinking غريب؟

دعنا نعود إلى مهمة Bluetooth ونقوم ببعض إعادة التسمية.

  • v21 - vip_smth (لم يتضح بعد ما هو موجود) ؛
  • v22 - vip_str (سلسلة غير معروفة الحجم ، مستخرجة من الوسيطات) ؛
  • الإصدار 23 - mad_led - خصص "التحويل إلى البنية *" وحدد Struct_LED .

وهنا نرى الرقم 0xB816D8D9 (تم العثور عليه في الجزء الأول من المقالة في مهمة Bluetooth) كمؤشر LED. سيتم تنفيذ هذا الرمز إذا تم التحقق:

 if ( sub_8005520(vip_str, vip_smth) == 0x46F70674 ) 

إعادة تسمية sub_8005520 إلى x_vip_check وإلقاء نظرة عليه:



بالنظر إلى أن الوسيطة الأولى عبارة عن سلسلة (على الأقل يتم تمرير السلسلة إلى هذه الدالة) ، يوضح هذا الرمز أن الوسيطة الثانية هي طول هذه السلسلة (أو الطول الذي يجب معالجته). إعادة التسمية:

  • a1 - شارع ؛
  • أ 2 - لين .

دعونا نلقي نظرة على الدالة sub_8000254 :



انظر الآن إلى sub_8000148 . ها هي بدايتها:



هذه ليست سوى ثلث الوظيفة ... مممم ... لذيذ! سوف يرى حفار ذو خبرة هنا بسهولة ...

ماذا؟
عملية تقسيم عدد صحيح.

كيف يمكن استخراجه؟
إذا قمت بجهد ، فيمكنك من خلال الدالة sub_8000254 الوصول إلى x_printf (من خلال العديد من الوظائف الأخرى). من النقاط المهمة التي يجب إثارتها في هذه المرحلة أنه عادة ما تكون جميع الوظائف القياسية قياسية إلى حد ما . هذا يعني أنه يمكنك محاولة العثور في المجال العام على الأقل على بعض التعليمات البرمجية المصدر للوظيفة قيد البحث ، بحيث تكون الدراسة أكثر إنتاجية.

لذا ، نأخذ مصدر printf ، ثم ننظر إلى vfprintf ، ونقارنه برمز البرامج الثابتة المدروسة. باستخدام شفرة المصدر ، نخرج إلى دالة itoa ونستنتج أن الدالة sub_8000254 هي عامل التشغيل٪ (مع أخذ باقي القسمة) ، وهذه الوظيفة الطويلة الرهيبة ليست أكثر من أخذ الجزء الصحيح من القسمة (عملية div).

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

لا تنسى إعادة التسمية أثناء الحفر.

وهكذا ، الدالة x_vip_check ، تحسب ... وهذا سيكون واجبك .

بالمناسبة ، إذا قمت بتنفيذ أمر VIP الصحيح ، نحصل على "وحيد القرن في الديسكو":



تقرير موجز عن البرامج الثابتة


يعتمد البرنامج الثابت للجهاز على نظام التشغيل في الوقت الحقيقي FreeRTOS. يتولى النظام المهام التالية:

  1. مهمة بلوتوث . أوامر العمليات التي تأتي في شكل نص عبر البلوتوث.
  2. مهمة LED . يتحكم في مؤشرات LED الملونة وفقًا لأوامر Bluetooth.
  3. مهمة الاستشعار . يشغّل ضوء LED الأحمر ، ويسمح بتخويل قصير الأمد بدون كلمة مرور على الجهاز.
  4. مهمة UART . يسمح لك بالتفاعل مع وحدة Bluetooth عبر منفذ UART الداخلي (المستخدم لتهيئة Bluetooth).
  5. مهمة المراقبة . يتتبع التجميد.

لم تأخذ الدراسة في الاعتبار القدرة على قراءة البيانات من منفذ UART (جهات الاتصال Tx / GND).

الملخص


أثناء الفصل الرئيسي في المؤتمر ، تم تفكيك وظيفة التحكم في LED الرئيسية فقط. وقد تم تزويد المشاركين الأكثر نشاطًا بـ "وحيد القرن" التجريبي.

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

  • كيفية العمل مع المؤسسة الدولية للتنمية ؛
  • مبادئ التفاعل بين البرامج الثابتة والجهاز ؛
  • مبادئ التشغيل RTOS.

شكرا جزيلا لجميع الذين قرأوا حتى النهاية!

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


All Articles