
أداة تزويد (fuzzer) قائمة على المحاكاة للبرامج الثابتة (firmware) الخاصة بـ MSP430، تكتشف وتحلل أخطاء تلف الذاكرة مع تقارير أعطال مفصلة ومدخلات قابلة لإعادة الإنتاج.
انهيارات تم العثور عليها في ملفات MSP430 الثنائية بواسطة Icicle.
| # | Target | الوصف |
|---|---|---|
| I03 | Goodwatch | مقارنة غير صحيحة عند الكتابة إلى dmesg_buffer |
| I04 | Goodwatch | الطول الصفري للرسالة |
| I05 | Goodwatch | تجاوز RNG |
| I06 | Goodwatch | وصول خارج النطاق في ضغطة مفتاح OOK |
| I07 | Goodwatch | وصول خارج النطاق في ساعة الإيقاف |
| I08 | Goodwatch | وصول خارج النطاق عند عرض يوم الأسبوع |
| I09 | Goodwatch | تطبيق عارض Hex |
| I10 | Goodwatch | أوامر المراقبة PEEK/POKE |
| I11 | H4_PacketProtocol | فهرس واجهة غير مُتحقق منه في Get Descriptor |
| I12 | H4_PacketProtocol | تجاوز سعة المخزن المؤقت في Set Report |
dmesg bufferputchar يسبب كتابة خارج النطاق بمقدار بايت واحد عند 0x2c00.مثال لمكدس الاستدعاءات أثناء الانهيار:
UnhandledException(code=WriteUnmapped, value=0x2c00):
0x000000c81a: putchar+0x1c
0x000000c832: dmesg_putc+0x6
0x0000009706: tfp_format+0x22
0x000000ad9c: tfp_printf+0x12
0x000000b924: key_scan.part.0+0x68
0x000000cd3c: PORT2_ISR+0x1a
0x0000008e04: <unknown>
يتم التعامل بشكل غير صحيح مع الرسائل المُرسلة إلى واجهة UART عندما يكون حقل الطول مضبوطًا على صفر. في حالة MSG، بعد تخزين البايت الذي تم استلامه للتو عند index الحالي في uart_buffer، يتم زيادة index ثم التحقق من أنه أصبح الآن يساوي length، ولكن نظرًا لأن تخزين index وزيادته يحدثان قبل المقارنة مع length، فإن شرط index == length لن يتحقق أبدًا بالنسبة للرسائل ذات الطول الصفري.
في النهاية سيتجاوز index مصفوفة uart_buffer مما يسمح بتعديل المتغيرات العامة المخزنة بعد uart_buffer. يؤدي هذا عادةً إلى انهيار البرنامج عند استبدال مؤشر الدالة stdout_putf أو stdout_putp وطباعة رسالة تصحيح.
المدخلات المسببة للانهيار:
./run_goodwatch.sh I04a
مكدس الاستدعاءات أثناء الانهيار:
UnhandledException(code=InvalidInstruction)
0x000000d3d3: <unknown>
0x0000009648: putchw+0x40
0x0000009826: tfp_format+0x142
0x000000ad9c: tfp_printf+0x12
0x000000b924: key_scan.part.0+0x68
0x000000cd3c: PORT2_ISR+0x1a
0x0000008e04: <unknown>
appindex (أو subindex)، مما يسبب انهيارًا عند تحميل applet التالي باستخدام appindex (مثلًا في app_draw).مكدس الاستدعاءات أثناء الانهيار:
UnhandledException(code=InvalidInstruction)
0x000000531c: <unknown>
0x0000009a96: app_init+0xe
0x000000c0a8: settime_draw+0x28
0x0000009b0a: app_draw+0x3e
0x000000ce78: watchdog_timer+0x6a
0x0000008e04: <unknown>
RANDINT إلى قيام البرنامج الثابت (firmware) بتوليد وإرسال قائمة من الأرقام العشوائية. ومع ذلك، يتم التحكم في عدد القيم العشوائية التي سيتم توليدها بواسطة الأمر المستلم. إذا كان عدد القيم المطلوب توليدها كبيرًا جدًا، فسيتجاوز rints المساحة المحجوزة للمكدس مما يؤدي إلى كتابة خارج النطاق.المدخلات المسببة للانهيار:
./run_goodwatch.sh I05
مكدس الاستدعاءات أثناء الانهيار:
UnhandledException(code=WriteUnmapped, value=0x6e6a)
0x000000cbd4: USCI_A0_ISR+0x24c (inlined `send_randint`)
0x0000008e04: <unknown>
ook keypress:يرسل تطبيق OOK حزمة OOK مُعدة مسبقًا من button_array عند الضغط على أحد المفاتيح الرقمية (0-9). ومع ذلك، لا يتحقق ook_keypress من أن المفتاح المضغوط يقع ضمن حدود مصفوفة button_array. يوجد 10 أزرار رقمية (0-9) بينما تحتوي button_array على 9 عناصر فقط.
تحتوي button_array على مصفوفة من المؤشرات، وعند الضغط على الزر 9 في تطبيق OOK ستقرأ دالة setrate مؤشرًا خارج نطاق button_array وتفك مرجعه مما يسبب انهيار البرنامج.
المؤشر الذي تقرؤه هو القيمة الأولى من ook_settings (0x3012) وهي غير موجودة في الذاكرة.
المدخلات المسببة للانهيار:
./run_goodwatch.sh I06
مكدس الاستدعاءات أثناء الانهيار:
UnhandledException(code=ReadUnmapped, value=0x3012)
0x000000b87a: ook_keypress+0x2c
0x000000cd7e: PORT2_ISR+0x5c
0x0000008e04: <unknown>
يطبق البرنامج الثابت عملية تحويل الأعداد الصحيحة إلى النظام العشري المشفر ثنائيًا (BCD) باستخدام جدول بحث، لكن جدول البحث (bcdtable) يحتوي فقط على قيم لتحويل الأعداد الصحيحة من 0 إلى 59. بالنسبة لتحويل الثواني والدقائق فهذا جيد لأن هذه القيم تلتف عند 60 عند العد، ومع ذلك يمكن أن يتجاوز متغير hour قيمة 60 مما يتسبب في تجاوز الفهرس خارج النطاق.
تم العثور على هذا الخطأ فقط بواسطة المُشوش (fuzzer) كأثر جانبي للتلف الناتج عن خطأ طول الرسالة الصفري. في الانهيار الذي عثر عليه المُشوش، يتم إتلاف كل من المتغيرين العامين min و hour عند تجاوز سعة uart_buffer.
المدخلات المسببة للانهيار:
./run_goodwatch.sh I07
مكدس الاستدعاءات أثناء الانهيار:
UnhandledException(code=ReadUnmapped, value=0x4b57)
0x000000a3e4: stopwatch_draw+0x9e
0x0000009b0a: app_draw+0x3e
0x000000ce78: watchdog_timer+0x6a
0x0000008e04: <unknown>
خطأ إيجابي كاذب سببه توليد المُشوش (fuzzer) لقيمة كبيرة لطرفية RTCDOW.
الضغط على الزر 9 في تطبيق الساعة يحاول رسم يوم الأسبوع الحالي على شاشة LCD. تتم قراءة يوم الأسبوع مباشرة من سجل RTCDOW الخاص بطرفية RTC، وتحدد ورقة البيانات لهذا السجل أن القيمة المُعادة تتراوح بين 0-6، لكن أثناء fuzzing تكون قيمة هذا السجل غير مقيدة. نظرًا لأن القيمة تُستخدم كفهرس إلى مصفوفة dayofweek، إذا ولّد المُشوش قيمة أكبر من 6 لسجل RTCDOW، فسيقرأ البرنامج مؤشرًا خارج مصفوفة daysofweek مما يؤدي إلى انهيار (إيجابي كاذب).
يمكن أن يحدث هذا الانهيار في كل من clock_keypress و hebrew_keypress.
المدخلات المسببة للانهيار:
./run_goodwatch.sh I08a
مكدس الاستدعاءات أثناء الانهيار:
UnhandledException(code=ReadUnmapped, value=0x5150)
0x0000009e6e: lcd_string+0x8
0x000000c1dc: clock_keypress+0x6c
0x000000cd7e: PORT2_ISR+0x5c
0x0000008e04: <unknown>
المدخلات المسببة للانهيار:
./run_goodwatch.sh I08b
مكدس الاستدعاءات أثناء الانهيار:
UnhandledException(code=ReadPerm, value=0x1006)
0x0000009e6e: lcd_string+0x8
0x000000b2aa: hebrew_keypress+0x116
0x000000c48c: clock_keypress+0x31c
0x000000cd7e: PORT2_ISR+0x5c
0x0000008e04: <unknown>
المدخلات المسببة للانهيار:
./run_goodwatch.sh I09
مكدس الاستدعاءات أثناء الانهيار:
UnhandledException(code=ReadUnmapped, value=0x7000)
0x0000009c74: hex_draw.part.0+0x3c
0x0000009c88: hex_draw+0x8
0x0000009b0a: app_draw+0x3e
0x000000cd8c: PORT2_ISR+0x6a
0x0000008e04: <unknown>
المدخلات المسببة للانهيار لـ PEEK:
./run_goodwatch.sh I10a
مكدس الاستدعاءات أثناء الانهيار:
UnhandledException(code=ReadUnmapped, value=0x5100)
0x000000cb00: USCI_A0_ISR+0x178
0x0000008e04: <unknown>
المدخلات المسببة للانهيار لـ POKE:
./run_goodwatch.sh I10b
مكدس الاستدعاءات أثناء الانهيار:
UnhandledException(code=WritePerm, value=0x4b00)
0x000000cb32: USCI_A0_ISR+0x1aa
0x0000008e04: <unknown>
Get_Descriptor. يمكن أن يتسبب هذا في وصول خارج النطاق. على سبيل المثال:GetHidDescriptor:
./run_H4_PacketProtocol.sh I11a
مكدس الاستدعاءات أثناء الانهيار:
UnhandledException(code=ReadUninitialized, value=0xe90e)
0x0000011176: usbSendNextPacketOnIEP0 at ./USB_API/USB_Common/usb.c:1082.13
0x0000011c12: usbGetHidDescriptor at ./USB_API/USB_HID_API/UsbHidReq.c:78.5
0x0000010fb0: usbDecodeAndProcessUsbRequest at ./USB_API/USB_Common/usb.c:1655.5
0x0000011724: SetupPacketInterruptHandler at ./USB_config/UsbIsr.c:250.5
0x0000004410: iUsbInterruptHandler at ./USB_config/UsbIsr.c:88.9
0x0000004572: _c_int00_noargs
GetReportDescriptor:
./run_H4_PacketProtocol.sh I11b
مكدس الاستدعاءات أثناء الانهيار:
UnhandledException(code=ReadUninitialized, value=0xa44c)
0x0000011c28: usbGetReportDescriptor at ./USB_API/USB_HID_API/UsbHidReq.c:85.5
0x0000010fb0: usbDecodeAndProcessUsbRequest at ./USB_API/USB_Common/usb.c:1655.5
0x0000011724: SetupPacketInterruptHandler at ./USB_config/UsbIsr.c:250.5
0x00000044fe: iUsbInterruptHandler at ./USB_config/UsbIsr.c:166.9
0x0000004572: _c_int00_noargs
Set_Report، يخصص البرنامج الثابت مخزنًا مؤقتًا لتخزين التقرير في pbOEP0Buffer، وطول التقرير في wBytesRemainingOnOEP0. ومع ذلك، لا يتحقق البرنامج الثابت مما إذا كان التقرير مناسبًا للمخزن المؤقت المخصص، مما يتسبب في تجاوز سعة المخزن المؤقت عند الكتابة إليه لاحقًا في usbReceiveNextPacketOnOEP0.في المدخلات المسببة للانهيار أدناه، يتم تعيين عنوان مصفوفة من 8 بايتات (0x24a4: abUsbRequestIncomingData) إلى pbOEP0Buffer، وبعد تجاوز سعة المصفوفة، يتم إتلاف مؤشر دالة (0x24b4: USB_RX_memcpy) مما يسبب انهيارًا عند استدعاء مؤشر الدالة لاحقًا.
./run_H4_PacketProtocol.sh I12
مكدس الاستدعاءات أثناء الانهيار:
UnhandledException(code=InvalidInstruction, value=0xf95b7)
0x00000f95b7: <unknown>
0x0000011066: HidCopyUsbToBuff at ./USB_API/USB_HID_API/UsbHid.c:417.5
0x0000010172: USBHID_receiveData at ./USB_API/USB_HID_API/UsbHid.c:577.13
0x000001026a: main at ./main.c:115.25
0x0000004572: _c_int00_noargs