
हार्डवेयर ब्रेकपॉइंट्स का उपयोग करके एम्बेडेड सिस्टम की फ़ज़िंग
यह पेपर का सहायक कोड है: 'Fuzzing Embedded Systems using Debugger Interfaces'. पेपर का प्रीप्रिंट यहाँ पाया जा सकता है https://publications.cispa.saarland/3950/. यह कोड उपयोगकर्ताओं को पेपर में रिपोर्ट किए गए परिणामों को पुन: उत्पन्न करने और विस्तारित करने की अनुमति देता है। कृपया परिणामों की रिपोर्ट करते, पुन: उत्पन्न करते या विस्तारित करते समय उपरोक्त पेपर का उल्लेख करें।
.
├── benchmark # गूगल के फ़ज़र टेस्ट सूट को बनाने और प्रयोग चलाने के लिए स्क्रिप्ट्स
├── dependencies # GDBFuzz के लिए निर्भरताएँ स्थापित करने के लिए एक Makefile शामिल है
├── evaluation # कच्चा प्रयोग डेटा, पेपर में प्रस्तुत किया गया
├── example_firmware # एम्बेडेड उदाहरण अनुप्रयोग, मूल्यांकन के लिए उपयोग किए गए
├── example_programs # GDBFuzz का परीक्षण करने के लिए एक संकलित उदाहरण प्रोग्राम और कॉन्फ़िग्स शामिल हैं
├── src # GDBFuzz का कार्यान्वयन शामिल है
├── Dockerfile # सभी GDBFuzz निर्भरताओं के साथ एक डॉकर इमेज बनाने के लिए
├── LICENSE # लाइसेंस
├── Makefile # डॉकर इमेज बनाने या GDBFuzz स्थानीय रूप से स्थापित करने के लिए Makefile
└── README.md # यह README फ़ाइल
GDBFuzz का विचार माइक्रोकंट्रोलर्स से हार्डवेयर ब्रेकपॉइंट्स को कवरेज-निर्देशित फ़ज़िंग के लिए फीडबैक के रूप में उपयोग करना है। इसलिए, GDB का उपयोग एक सामान्य इंटरफ़ेस के रूप में किया जाता है ताकि व्यापक प्रयोज्यता सक्षम हो सके। फर्मवेयर के बाइनरी विश्लेषण के लिए, Ghidra का उपयोग किया जाता है। कोड में विधि का मूल्यांकन करने के लिए एक बेंचमार्क सेटअप शामिल है। इसके अतिरिक्त, उदाहरण फर्मवेयर फ़ाइलें शामिल हैं।
GDBFuzz एम्बेडेड सिस्टम के लिए कवरेज-निर्देशित फ़ज़िंग को सक्षम करता है, लेकिन - मूल्यांकन उद्देश्यों के लिए - मनमाने उपयोगकर्ता अनुप्रयोगों को भी फ़ज़ कर सकता है। माइक्रोकंट्रोलर्स पर फ़ज़िंग के लिए हम GDBFuzz की स्थानीय स्थापना की सलाह देते हैं ताकि परीक्षण के तहत डिवाइस को बिना किसी दोष के फ़ज़ डेटा भेज सकें।
GDBFuzz का परीक्षण Ubuntu 20.04 LTS और Raspberry Pi OS 32-bit पर किया गया है। पूर्वापेक्षाएँ java और python3 हैं। पहले, एक नया वर्चुअल वातावरण बनाएं और सभी निर्भरताएँ स्थापित करें।
virtualenv .venv
source .venv/bin/activate
make
chmod a+x ./src/GDBFuzz/main.py
GDBFuzz निम्नलिखित कुंजियों के साथ एक कॉन्फ़िग फ़ाइल से सेटिंग्स पढ़ता है।
[SUT]
# SUT की बाइनरी फ़ाइल का पथ।
# यह उदाहरण के लिए, एक .elf फ़ाइल या .bin फ़ाइल हो सकता है।
binary_file_path = <path>
# CFG के रूट नोड का पता।
# ब्रेकपॉइंट्स इस CFG के नोड्स पर रखे जाते हैं।
# जैसे 'LLVMFuzzerTestOneInput' या 'main'
entrypoint = <entrypoint>
# इनपुट की संख्या जो ब्रेकपॉइंट हिट किए बिना निष्पादित होनी चाहिए जब तक
# ब्रेकपॉइंट रोटेट न हों।
until_rotate_breakpoints = <number>
# किसी भी समय पर रखे जा सकने वाले ब्रेकपॉइंट की अधिकतम संख्या।
max_breakpoints = <number>
# वे फ़ंक्शन जिन्हें अनदेखा किया जाना चाहिए (ब्लैकलिस्ट)।
# ignore_functions फ़ंक्शन नामों की स्पेस-सेपरेटेड सूची है जैसे 'malloc free'।
ignore_functions = <space separated list>
# {Hardware, QEMU, SUTRunsOnHost} में से एक
# Hardware: एक बाहरी घटक gdb सर्वर शुरू करता है और GDBFuzz इस gdb सर्वर से कनेक्ट हो सकता है।
# QEMU: GDBFuzz QEMU शुरू करता है। QEMU binary_file_path को एम्युलेट करता है और gdbserver शुरू करता है।
# SUTRunsOnHost: GDBFuzz लक्ष्य प्रोग्राम को GDB के भीतर शुरू करता है।
target_mode = <mode>
# इसे False पर सेट करें यदि आप ghidra शुरू करना, SUT का विश्लेषण करना,
# और ghidra ब्रिज सर्वर को मैन्युअल रूप से शुरू करना चाहते हैं।
start_ghidra = True
# सॉफ़्टवेयर ब्रेकपॉइंट (त्रुटि हैंडलिंग कोड के लिए) के पतों की स्पेस-सेपरेटेड सूची।
# इनका निष्पादन एक क्रैश माना जाता है।
# उदाहरण: software_breakpoint_addresses = 0x123 0x432
software_breakpoint_addresses =
# क्या सभी ट्रिगर किए गए सॉफ़्टवेयर ब्रेकपॉइंट को क्रैश माना जाए
consider_sw_breakpoint_as_error = False
[SUTConnection]
# फ़ाइल 'SUT_connection_path' में वर्ग 'SUT_connection_class' यह कार्यान्वित करता है कि
# SUT को इनपुट कैसे भेजे जाते हैं।
# इनपुट उदाहरण के लिए, Wi-Fi, सीरियल, ब्लूटूथ, ... के माध्यम से भेजे जा सकते हैं।
# इस वर्ग को ./connections/SUTConnection.py से इनहेरिट करना चाहिए।
# अधिक जानकारी के लिए ./connections/SUTConnection.py देखें।
SUT_connection_file = FIFOConnection.py
[GDB]
path_to_gdb = gdb-multiarch
# address:port प्रारूप में लिखा गया
gdb_server_address = localhost:4242
[Fuzzer]
# बाइट्स में
maximum_input_length = 100000
# सेकंड में
single_run_timeout = 20
# सेकंड में
total_runtime = 3600
# वैकल्पिक
# एक निर्देशिका का पथ जहाँ प्रत्येक फ़ाइल में एक सीड होता है। यदि आप
# सीड का उपयोग नहीं करना चाहते हैं, तो मान खाली छोड़ दें।
seeds_directory =
[BreakpointStrategy]
# बुनियादी ब्लॉक चुनने की रणनीतियाँ 'src/GDBFuzz/breakpoint_strategies/' में स्थित हैं।
# पेपर के लिए हम निम्नलिखित रणनीतियों का उपयोग करते हैं
# 'RandomBasicBlockStrategy.py' - यादृच्छिक रूप से अप्राप्त बुनियादी ब्लॉक चुनना
# 'RandomBasicBlockNoDomStrategy.py' - पिछले जैसा, लेकिन ट्रांज़िटिवली रीच किए गए नोड्स को प्राप्त करने के लिए डोमिनेंस संबंधों का उपयोग नहीं करता।
# 'RandomBasicBlockNoCorpusStrategy.py' - पहले जैसा, लेकिन इनपुट कॉर्पस को बढ़ने से रोकता है और इसलिए कवरेज माप के साथ ब्लैकबॉक्स फ़ज़िंग की तरह व्यवहार करता है।
# 'BlackboxStrategy.py' - कोई ब्रेकपॉइंट नहीं सेट करता
breakpoint_strategy_file = RandomBasicBlockStrategy.py
[Dependencies]
path_to_qemu = dependencies/qemu/build/x86_64-linux-user/qemu-x86_64
path_to_ghidra = dependencies/ghidra
[LogsAndVisualizations]
# {DEBUG, INFO, WARNING, ERROR, CRITICAL} में से एक
loglevel = INFO
# उस निर्देशिका का पथ जहाँ आउटपुट फ़ाइलें (जैसे ग्राफ़, लॉगफ़ाइलें) संग्रहीत की जाती हैं।
output_directory = ./output
# यदि True पर सेट किया जाता है, तो एक MQTT क्लाइंट UI तत्व (जैसे ग्राफ़) भेजता है
enable_UI = False
एक उदाहरण कॉन्फ़िग फ़ाइल ./example_programs/ में स्थित है, साथ ही एक उदाहरण प्रोग्राम जो benchmark/benchSUTs/GDBFuzz_wrapper/common/ में हमारे फ़ज़िंग हार्नेस का उपयोग करके संकलित किया गया था। निम्नलिखित कमांड के साथ एक घंटे के लिए फ़ज़िंग शुरू करें।
chmod a+x ./example_programs/json-2017-02-12
./src/GDBFuzz/main.py --config ./example_programs/fuzz_json.cfg
हम पहले Ghidra से बाइनरी निष्पादन योग्य का विश्लेषण करने का आउटपुट देखते हैं और फिर जब ब्रेकपॉइंट स्थानांतरित या हिट होते हैं तो संदेश देखते हैं।
कॉन्फ़िग फ़ाइल में निर्दिष्ट output_directory के आधार पर, अब निम्नलिखित संरचना के साथ एक फ़ोल्डर trial-0 होना चाहिए
.
├── corpus # एक फ़ोल्डर जिसमें इनपुट कॉर्पस है।
├── crashes # एक फ़ोल्डर जिसमें क्रैश करने वाले इनपुट हैं - यदि कोई हों।
├── cfg # एड्जेसेंसी सूची के रूप में कंट्रोल फ़्लो ग्राफ़।
├── fuzzer_stats # फ़ज़िंग अभियान के आँकड़े।
├── plot_data # तालिका दिखाती है कि फ़ज़िंग अभियान में किस सापेक्ष समय पर कौन सा बुनियादी ब्लॉक पहुँचा गया था।
├── reverse_cfg # रिवर्स कंट्रोल फ़्लो ग्राफ़।
कॉन्फ़िग फ़ाइल में start_ghidra = False सेट करके, GDBFuzz GUI मोड में चल रहे Ghidra इंस्टेंस से जुड़ता है। इसलिए, ghidra_bridge प्लगइन को स्क्रिप्ट मैनेजर से मैन्युअल रूप से शुरू करने की आवश्यकता है। फ़ज़िंग के दौरान, पहुँचे गए प्रोग्राम ब्लॉक हरे रंग में हाइलाइट किए जाते हैं।