
MSP430 फ़र्मवेयर के लिए एमुलेशन-आधारित फ़ज़र जो विस्तृत क्रैश रिपोर्ट और पुनरुत्पादनीय इनपुट के साथ मेमोरी-भ्रष्टाचार बग्स का पता लगाता है और उनका विश्लेषण करता है।
Icicle द्वारा MSP430 बाइनरीज़ में पाए गए क्रैश।
| # | लक्ष्य | विवरण |
|---|---|---|
| I03 | Goodwatch | dmesg_buffer में लिखते समय गलत तुलना |
| I04 | Goodwatch | शून्य संदेश लंबाई |
| I05 | Goodwatch | RNG ओवरफ्लो |
| I06 | Goodwatch | OOK कीप्रेस में आउट-ऑफ-बाउंड्स एक्सेस |
| I07 | Goodwatch | स्टॉपवॉच में आउट-ऑफ-बाउंड्स एक्सेस |
| I08 | Goodwatch | DOW प्रदर्शित करते समय आउट-ऑफ-बाउंड्स एक्सेस |
| I09 | Goodwatch | हेक्स व्यूअर एप्लिकेशन |
| I10 | Goodwatch | PEEK/POKE मॉनिटर कमांड्स |
| I11 | H4_PacketProtocol | Get Descriptor में अनचेक्ड इंटरफ़ेस इंडेक्स |
| I12 | H4_PacketProtocol | Set Report में बफर ओवरफ्लो |
dmesg buffer में लिखते समय गलत तुलनाputchar में ऑफ-बाय-वन त्रुटि के कारण 0x2c00 पर सिंगल बाइट OOB राइट होता है।क्रैश के दौरान उदाहरण कॉल-स्टैक:
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 अवस्था में, uart_buffer में वर्तमान index पर अभी प्राप्त बाइट को संग्रहीत करने के बाद यह 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) ओवरराइट हो जाता है, जिससे अगली बार appindex का उपयोग करके applet लोड होने पर क्रैश हो जाता है (जैसे 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 मॉनिटर कमांड फर्मवेयर को यादृच्छिक संख्याओं की एक सूची उत्पन्न करने और भेजने के लिए प्रेरित करता है। हालाँकि, उत्पन्न करने के लिए यादृच्छिक मानों की संख्या प्राप्त कमांड द्वारा नियंत्रित होती है। यदि उत्पन्न करने के लिए मानों की संख्या बहुत अधिक है, तो rints स्टैक के लिए आरक्षित स्थान से अधिक हो जाएगा, जिससे OOB राइट ट्रिगर होगा।क्रैश इनपुट:
./run_goodwatch.sh I05
क्रैश के दौरान कॉल-स्टैक:
UnhandledException(code=WriteUnmapped, value=0x6e6a)
0x000000cbd4: USCI_A0_ISR+0x24c (inlined `send_randint`)
0x0000008e04: <unknown>
ook keypress में आउट-ऑफ-बाउंड्स एक्सेस:OOK एप्लिकेशन जब संख्यात्मक कुंजियों (0-9) में से एक दबाई जाती है तो button_array से पूर्व-कॉन्फ़िगर्ड OOK पैकेट भेजता है। हालाँकि, ook_keypress यह सत्यापित नहीं करता है कि दबाई गई कुंजी button_array सरणी की सीमा के भीतर है या नहीं। 10 संख्यात्मक बटन (0-9) हैं, button_array में केवल 9 प्रविष्टियाँ हैं।
button_array में पॉइंटर्स की एक सरणी होती है; जब OOK एप्लिकेशन पर 9 बटन दबाया जाता है, तो प्रोग्राम 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 से अधिक हो सकता है, जिससे इंडेक्स सीमा से बाहर हो जाता है।
यह बग केवल फ़ज़र द्वारा शून्य संदेश लंबाई बग के कारण होने वाले भ्रष्टाचार के दुष्प्रभाव के रूप में पाया गया था। फ़ज़र द्वारा पाए गए क्रैश में, uart_buffer के ओवरफ्लो होने पर min और hour दोनों वैश्विक चर दूषित हो जाते हैं।
क्रैश इनपुट:
./run_goodwatch.sh I07
क्रैश के दौरान कॉल-स्टैक:
UnhandledException(code=ReadUnmapped, value=0x4b57)
0x000000a3e4: stopwatch_draw+0x9e
0x0000009b0a: app_draw+0x3e
0x000000ce78: watchdog_timer+0x6a
0x0000008e04: <unknown>
फ़ज़र द्वारा RTCDOW पेरिफेरल के लिए एक बड़ा मान उत्पन्न करने के कारण हुआ गलत-सकारात्मक बग।
क्लॉक एप्लिकेशन पर बटन 9 दबाने से LCD पर सप्ताह का वर्तमान दिन प्रदर्शित करने का प्रयास होता है। सप्ताह का दिन सीधे RTC पेरिफेरल के RTCDOW रजिस्टर से पढ़ा जाता है; इस रजिस्टर के लिए डेटाशीट निर्दिष्ट करती है कि लौटाया गया मान 0-6 के बीच होता है, हालाँकि फ़ज़िंग के दौरान इस रजिस्टर का मान अप्रतिबंधित होता है। चूँकि मान का उपयोग dayofweek सरणी में इंडेक्स के रूप में किया जाता है, यदि फ़ज़र RTCDOW रजिस्टर के लिए 6 से बड़ा मान उत्पन्न करता है, तो प्रोग्राम 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