
दोष-इंजेक्शन-आधारित फ़ज़र जो जनरेटर प्रोग्रामों में उत्परिवर्तन करके लक्ष्यों के लिए लगभग-मान्य इनपुट उत्पन्न करता है, जिससे जटिल प्रारूपों और क्रिप्टो-संरक्षित डेटा का व्याकरण अनुमानों के बिना फ़ज़िंग संभव होता है।
Fuzztruction एक शैक्षणिक प्रोटोटाइप है जो एक फ़ज़र है जो सीधे इनपुट को म्यूटेट नहीं करता (जैसा कि अधिकांश फ़ज़र करते हैं), बल्कि इसके बजाय एक तथाकथित जनरेटर एप्लिकेशन का उपयोग करता है ताकि हमारे फ़ज़िंग लक्ष्य के लिए एक इनपुट तैयार किया जा सके। चूंकि डेटा उत्पन्न करने वाले प्रोग्राम आमतौर पर सही प्रतिनिधित्व उत्पन्न करते हैं, हमारा फ़ज़र जनरेटर प्रोग्राम में फ़ॉल्ट इंजेक्ट करके म्यूटेट करता है, ताकि उत्पादित डेटा लगभग मान्य हो। आदर्श रूप से, उत्पादित डेटा हमारे फ़ज़िंग लक्ष्य, जिसे उपभोक्ता कहा जाता है, में पार्सिंग चरणों को पार करता है, लेकिन गहरी प्रोग्राम लॉजिक में अप्रत्याशित व्यवहार को ट्रिगर करता है। यह एन्क्रिप्शन या संदेश अखंडता कोड जैसी क्रिप्टोग्राफी प्रिमिटिव का उपयोग करने वाले लक्ष्यों को भी फ़ज़ करने की अनुमति देता है। हमारे दृष्टिकोण का मुख्य लाभ यह है कि यह भारी प्रोग्राम विश्लेषण तकनीकों, व्याकरण अनुमानों या मानवीय हस्तक्षेप की आवश्यकता के बिना जटिल डेटा उत्पन्न करता है।
अधिक विवरण के लिए, हमारा पेपर देखें। अपने काम को उद्धृत करने के लिए, आप निम्नलिखित BibTeX प्रविष्टि का उपयोग कर सकते हैं:
@inproceedings{bars2023fuzztruction,
title={Fuzztruction: Using Fault Injection-based Fuzzing to Leverage Implicit Domain Knowledge},
booktitle = {32st USENIX Security Symposium (USENIX Security 23)},
publisher = {USENIX Association},
year={2023},
author={Bars, Nils and Schloegel, Moritz and Scharnowski, Tobias and Schiller, Nico and Holz, Thorsten},
}
पेपर से प्रयोगों को पुन: प्रस्तुत करने के निर्देशों के लिए, कृपया इस दस्तावेज़ को पढ़ने के बाद fuzztruction-experiments सबमॉड्यूल दस्तावेज़ीकरण पढ़ें।
संगतता: जबकि हम यह सुनिश्चित करने का प्रयास करते हैं कि हमारा प्रोटोटाइप जितना संभव हो प्लेटफ़ॉर्म स्वतंत्र है, हम सभी प्लेटफ़ॉर्म पर इसका परीक्षण करने में सक्षम नहीं हैं। इस प्रकार, यदि आपको समस्याएँ आती हैं, तो कृपया Ubuntu 22.04.1 का उपयोग करें, जिसका उपयोग विकास के दौरान होस्ट सिस्टम के रूप में किया गया था।
# Clone the repository
git clone --recurse-submodules https://github.com/fuzztruction/fuzztruction.git
# Option 1: Get a pre-built version of our runtime environment.
# To ease reproduction of experiments in our paper, we recommend using our
# pre-built environment to avoid incompatibilities (~30 GB of data will be
# donwloaded)
# Do NOT use this if you don't want to reproduce our results but instead fuzz
# own targets (use the next command instead).
./env/pull-prebuilt.sh
# Option 2: Build the runtime environment for Fuzztruction from scratch.
# Do NOT run this if you executed pull-prebuilt.sh
./env/build.sh
# Spawn a container based on the image built/pulled before.
# To spawn a container using the prebuilt image (if pulled above),
# you need to set USE_PREBUILT to 1, e.g., `USE_PREBUILT=1 ./env/start.sh`
./env/start.sh
# Calling this script again will spawn a shell inside the container.
# (can be called multiple times to spawn multiple shells within the same
# container).
./env/start.sh
# Runninge start.sh the second time will automatically build the fuzzer.
# See `Fuzzing a Target using Fuzztruction` below for further instructions.
Fuzztruction में निम्नलिखित मुख्य घटक शामिल हैं:
शेड्यूलर जनरेटर और उपभोक्ता के बीच अंत:क्रिया का समन्वय करता है। यह फ़ज़िंग अभियान को नियंत्रित करता है, और इसका मुख्य कार्य फ़ज़िंग लूप को व्यवस्थित करना है। इसके अलावा, यह कतार प्रविष्टियों वाली एक कतार भी बनाए रखता है। प्रत्येक प्रविष्टि में जनरेटर को दिया गया बीज इनपुट (यदि कोई हो) और जनरेटर पर लागू सभी म्यूटेशन शामिल होते हैं। ऐसी प्रत्येक कतार प्रविष्टि एक एकल परीक्षण मामले का प्रतिनिधित्व करती है। पारंपरिक फ़ज़िंग में, ऐसा परीक्षण मामला एक फ़ाइल के रूप में दर्शाया जाएगा। शेड्यूलर का कार्यान्वयन scheduler निर्देशिका में स्थित है।
जनरेटर को फ़ज़िंग लक्ष्य, उपभोक्ता के लिए अनुरूप इनपुट उत्पन्न करने के लिए एक बीज जनरेटर माना जा सकता है। जबकि सामान्य फ़ज़िंग दृष्टिकोण बिट-स्तरीय म्यूटेशन के माध्यम से इनपुट को सीधे म्यूटेट करते हैं, हम जनरेटर प्रोग्राम में फॉल्ट इंजेक्ट करके अप्रत्यक्ष रूप से इनपुट को म्यूटेट करते हैं। अधिक सटीक रूप से, हम उन डेटा संचालनों की पहचान करते हैं और उन्हें म्यूटेट करते हैं जिनका उपयोग जनरेटर अपना आउटपुट उत्पन्न करने के लिए करता है। अपने दृष्टिकोण को सुगम बनाने के लिए, हमें एक ऐसे प्रोग्राम की आवश्यकता है जो ऐसे आउटपुट उत्पन्न करता है जो फ़ज़िंग लक्ष्य द्वारा अपेक्षित इनपुट प्रारूप से मेल खाते हैं।
जनरेटर का कार्यान्वयन generator निर्देशिका में पाया जा सकता है। इसमें दो घटक शामिल हैं, जिन्हें निम्नलिखित में समझाया गया है।
कंपाइलर पास (generator/pass) तथाकथित पैच पॉइंट का उपयोग करके लक्ष्य को इंस्ट्रूमेंट करता है। चूंकि इस सुविधा का वर्तमान कार्यान्वयन (LLVM12 और उससे नीचे पर परीक्षण) अस्थिर है, हम इसे अपने दृष्टिकोण के लिए सक्षम करने के लिए LLVM को पैच करते हैं। पैच llvm रिपॉजिटरी (यहाँ सबमॉड्यूल के रूप में शामिल) में पाए जा सकते हैं। कृपया ध्यान दें कि पैच प्रायोगिक हैं और उत्पादन में उपयोग के लिए अभिप्रेत नहीं हैं।
पैच पॉइंट के स्थान संकलित बाइनरी के अंदर एक अलग अनुभाग में रिकॉर्ड किए जाते हैं। इस अनुभाग को पार्स करने से संबंधित कोड lib/llvm-stackmap-rs पर पाया जा सकता है, जिसे हमने crates.io पर भी प्रकाशित किया है।
फ़ज़िंग के दौरान, शेड्यूलर पैच पॉइंट के सेट से एक लक्ष्य चुनता है और अपने निर्णय को एजेंट (नीचे वर्णित) को भेजता है जो दिए गए पैच पॉइंट के लिए वांछित म्यूटेशन लागू करने के लिए जिम्मेदार होता है।
एजेंट, जो generator/agent में कार्यान्वित है, कस्टम कंपाइलर पास के साथ संकलित जनरेटर एप्लिकेशन के संदर्भ में चलता है। इसके मुख्य कार्य फोर्कसर्वर का कार्यान्वयन और शेड्यूलर के साथ संचार करना हैं। शेड्यूलर से साझा मेमोरी और संदेश कतार के माध्यम से भेजे गए निर्देश के आधार पर, एजेंट जनरेटर को म्यूटेट करने के लिए JIT इंजन का उपयोग करता है।
जनरेटर का समकक्ष उपभोक्ता है: यह वह लक्ष्य है जिसे हम फ़ज़ कर रहे हैं जो जनरेटर द्वारा उत्पन्न इनपुट का उपभोग करता है। Fuzztruction के लिए, उपभोक्ता एप्लिकेशन को AFL++ के कंपाइलर पास के साथ संकलित करना पर्याप्त है, जिसका उपयोग हम कवरेज फीडबैक रिकॉर्ड करने के लिए करते हैं। यह फीडबैक जनरेटर के हमारे म्यूटेशन का मार्गदर्शन करता है।
Fuzztruction का उपयोग करने से पहले, डॉकर इमेज के रूप में आने वाले रनटाइम पर्यावरण की आवश्यकता होती है। यह इमेज इसे स्थानीय रूप से बनाकर या पूर्व-निर्मित संस्करण खींचकर प्राप्त किया जा सकता है। दोनों तरीके निम्नलिखित में वर्णित हैं। रनटाइम पर्यावरण तैयार करने से पहले, इस रिपॉजिटरी और सभी उप-रिपॉजिटरी को क्लोन किया जाना चाहिए:
git clone --recurse-submodules https://github.com/fuzztruction/fuzztruction.git
Fuzztruction रनटाइम पर्यावरण को env/build.sh निष्पादित करके बनाया जा सकता है। यह Fuzztruction के लिए एक पूर्ण रनटाइम पर्यावरण वाली डॉकर इमेज स्थानीय रूप से बनाता है। डिफ़ॉल्ट रूप से, हमारे पैच किए गए LLVM संस्करण के पूर्व-निर्मित संस्करण का उपयोग किया जाता है और Docker Hub से खींचा जाता है। यदि आप स्थानीय रूप से निर्मित LLVM संस्करण का उपयोग करना चाहते हैं, तो llvm निर्देशिका देखें।
अधिकांश मामलों में, पूर्व-निर्मित पर्यावरण का उपयोग करने का कोई विशेष कारण नहीं है—सिवाय इसके कि यदि आप पेपर में किए गए सटीक प्रयोगों को पुन: प्रस्तुत करना चाहते हैं। पूर्व-निर्मित इमेज पूर्व-निर्मित मूल्यांकन लक्ष्यों और सभी निर्भरताओं सहित सब कुछ प्रदान करती है। इमेज को env/pull-prebuilt.sh निष्पादित करके प्राप्त किया जा सकता है।
निम्नलिखित अनुभाग दस्तावेज़ित करता है कि स्थानीय रूप से निर्मित इमेज या पूर्व-निर्मित इमेज पर आधारित रनटाइम पर्यावरण कैसे उत्पन्न करें। पेपर के प्रयोगों के पुनरुत्पादन के विवरण fuzztruction-experiments सबमॉड्यूल में पाए जा सकते हैं।
रनटाइम पर्यावरण के पूर्व-निर्मित संस्करण को बनाने या खींचने के बाद, फ़ज़र उपयोग के लिए तैयार है। फ़ज़र्स पर्यावरण जीवनचक्र का प्रबंधन env फ़ोल्डर में स्थित स्क्रिप्ट के एक सेट द्वारा किया जाता है।
start.sh का उपयोग करके, कंटेनर में किसी भी संख्या में शेल उत्पन्न किए जा सकते हैं। Visual Studio Code के कंटेनर एक्सटेंशन का उपयोग करके आप डॉकर कंटेनर के अंदर सुविधाजनक रूप से काम कर सकते हैं।
डेटा विनिमय की सुविधा के लिए कई फ़ाइलें/फ़ोल्डर होस्ट से कंटेनर में माउंट किए जाते हैं। रनटाइम पर्यावरण के विवरण अगले भाग में प्रदान किए गए हैं।
यह भाग Fuzztruction के साथ प्रदान किए गए रनटाइम पर्यावरण (डॉकर कंटेनर) का विवरण देता है। कंटेनर में उपयोगकर्ता का नाम user है और डिफ़ॉल्ट रूप से पासवर्ड रहित sudo पहुंच है।
अनुमतियाँ: डॉकर इमेज का उपयोगकर्ता
userहै और उसकी उपयोगकर्ता आईडी (UID) वही है जिसने शुरू में इमेज बनाई थी। इस प्रकार, होस्ट से माउंट को कंटेनर के अंदर एक्सेस किया जा सकता है। हालांकि, पूर्व-निर्मित इमेज का उपयोग करने के मामले में, ऐसा नहीं हो सकता है क्योंकि इमेज किसी अन्य मशीन पर बनाई गई थी। होस्ट के साथ डेटा का आदान-प्रदान करते समय इस पर विचार किया जाना चाहिए।
कंटेनर के अंदर, निम्नलिखित पथ होस्ट से (बाइंड) माउंट किए गए हैं:
डॉकर रनटाइम पर्यावरण बनाने और एक कंटेनर उत्पन्न करने के बाद, Fuzztruction बाइनरी को स्वयं बनाया जाना चाहिए। ./env/start.sh का उपयोग करके कंटेनर के अंदर एक शेल उत्पन्न करने के बाद, निर्माण प्रक्रिया स्वचालित रूप से ट्रिगर हो जाती है। इस प्रकार, अगले भाग के चरण मुख्य रूप से उन लोगों के लिए हैं जो कोड में संशोधन लागू करने के बाद Fuzztruction को पुनर्निर्माण करना चाहते हैं।
Fuzztruction बनाने के लिए, /home/user/fuzztruction में cargo build कॉल करना पर्याप्त है। यह घटक भाग में वर्णित सभी घटकों का निर्माण करेगा। सबसे दिलचस्प निर्माण कलाकृतियाँ निम्नलिखित हैं:
हम Fuzztruction की क्षमताओं को प्रदर्शित करने के लिए libpng को एक उदाहरण के रूप में उपयोग करेंगे। चूँकि libpng अपेक्षाकृत छोटा है और इसकी कोई बाहरी निर्भरता नहीं है, निम्नलिखित चरणों के लिए पूर्व-निर्मित इमेज का उपयोग करना आवश्यक नहीं है। हालांकि, विशेष रूप से मोबाइल CPUs पर, टक्कर-मुक्त कवरेज मैप एन्कोडिंग सुविधा और तुलना विभाजन के कारण AFL++ बाइनरी के निर्माण में कई घंटे लग सकते हैं।
पूर्व-निर्मित: यदि पूर्व-निर्मित संस्करण का उपयोग किया जाता है, तो निर्माण करना आवश्यक नहीं है और इस चरण को छोड़ा जा सकता है।
fuzztruction-experiments/comparison-with-state-of-the-art/binaries/ निर्देशिका में जाएँ और ./build.sh libpng निष्पादित करें। यह स्रोत खींचेगा और libpng/config.sh में परिभाषित चरणों के अनुसार निर्माण शुरू करेगा।
निम्नलिखित कमांड का उपयोग करें
sudo ./target/debug/fuzztruction fuzztruction-experiments/comparison-with-state-of-the-art/configurations/pngtopng_pngtopng/pngtopng-pngtopng.yml --purge --show-output benchmark -i 100
यह परीक्षण करने की अनुमति देता है कि लक्ष्य काम करता है या नहीं। प्रत्येक लक्ष्य को YAML कॉन्फ़िगरेशन फ़ाइल का उपयोग करके परिभाषित किया गया है। फ़ाइलें configurations निर्देशिका में स्थित हैं और अपना स्वयं का कॉन्फ़िग बनाने के लिए एक अच्छा प्रारंभिक बिंदु हैं। pngtopng-pngtopng.yml फ़ाइल व्यापक रूप से दस्तावेज़ित है।
यदि फ़ज़र त्रुटि के साथ समाप्त होता है, तो आपकी डिबगिंग प्रयासों में सहायता के कई तरीके हैं।
fuzztruction को --show-output पास करने से आप जनरेटर और उपभोक्ता के stdout/stderr का निरीक्षण कर सकते हैं यदि वे एक-दूसरे से डेटा पास करने या पढ़ने के लिए उपयोग नहीं किए जाते हैं।YAML कॉन्फ़िग में sink के env अनुभाग में AFL_DEBUG सेट करने से उपभोक्ता के संबंध में अधिक विस्तृत आउटपुट मिल सकता है।LD_PRELOAD का उपयोग करने के मामले में, प्रदान किए गए पथों की दोबारा जाँच करें।फ़ज़िंग प्रक्रिया शुरू करने के लिए, निम्नलिखित कमांड निष्पादित करना पर्याप्त है:
sudo ./target/debug/fuzztruction ./fuzztruction-experiments/comparison-with-state-of-the-art/configurations/pngtopng_pngtopng/pngtopng-pngtopng.yml fuzz -j 10 -t 10m
यह 10 कोर पर एक फ़ज़िंग रन शुरू करेगा, जिसमें 10 मिनट का टाइमआउट होगा। फ़ज़र द्वारा उत्पादित आउटपुट लक्ष्य के कॉन्फ़िग फ़ाइल में work-directory विशेषता द्वारा परिभाषित निर्देशिका में संग्रहीत किया जाता है। pngtopng के मामले में, डिफ़ॉल्ट स्थान /tmp/pngtopng-pngtopng है।
यदि कार्यशील निर्देशिका पहले से मौजूद है, तो इसे फिर से चलाने की अनुमति देने के लिए fuzztruction के तर्क के रूप में --purge पास किया जाना चाहिए। फ़्लैग को उपकमांड से पहले, यानी fuzz या benchmark से पहले पास किया जाना चाहिए।
Fuzztruction के साथ AFL++ चलाने के लिए, aflpp उपकमांड का उपयोग AFL++ वर्कर्स को उत्पन्न करने के लिए किया जा सकता है जो रनटाइम के दौरान Fuzztruction द्वारा पाए गए इनपुट के साथ पुनः सीड किए जाते हैं। यह मानते हुए कि Fuzztruction को उपरोक्त कमांड का उपयोग करके निष्पादित किया गया था, यह निष्पादित करना पर्याप्त है
sudo ./target/debug/fuzztruction ./fuzztruction-experiments/comparison-with-state-of-the-art/configurations/pngtopng_pngtopng/pngtopng-pngtopng.yml aflpp -j 10 -t 10m
10 मिनट के बाद समाप्त होने वाली 10 AFL++ प्रक्रियाओं को उत्पन्न करने के लिए। Fuzztruction और AFL++ द्वारा पाए गए इनपुट समय-समय पर कार्यशील निर्देशिका में interesting फ़ोल्डर में सिंक होते हैं। यदि AFL++ को उसी .yml कॉन्फ़िगरेशन फ़ाइल के आधार पर स्वतंत्र रूप से निष्पादित किया जाना चाहिए, तो --suffix तर्क का उपयोग उत्पन्न फ़ज़र की कार्यशील निर्देशिका में एक प्रत्यय जोड़ने के लिए किया जा सकता है।
फ़ज़िंग रन समाप्त होने के बाद, tracer उपकमांड आपको फ़ज़िंग के दौरान पाए गए सभी दिलचस्प इनपुट के लिए कवर किए गए बुनियादी ब्लॉकों की एक सूची प्राप्त करने की अनुमति देता है। ये ट्रेस कार्यशील निर्देशिका में स्थित traces उपनिर्देशिका में संग्रहीत होते हैं। प्रत्येक ट्रेस में निष्पादन के दौरान अभ्यास किए गए सभी बुनियादी ब्लॉकों के पतों का एक zlib संपीड़ित JSON ऑब्जेक्ट होता है (निष्पादन क्रम में)। इसके अलावा, पतों को उनके वास्तविक ELF फ़ाइल से मैप करने के लिए मेटाडेटा प्रदान किया जाता है।
./target/debug/coverage पर स्थित coverage टूल का उपयोग एकत्रित डेटा को और अधिक संसाधित करने के लिए किया जा सकता है। आपको इसे Fuzztruction द्वारा बनाई गई कार्यशील निर्देशिकाओं वाली शीर्ष-स्तरीय निर्देशिका (जैसे, पिछले उदाहरण के मामले में /tmp) पास करनी होगी। ./target/debug/coverage /tmp निष्पादित करने से एक .csv फ़ाइल उत्पन्न होगी जो समय को कवर किए गए बुनियादी ब्लॉकों की संख्या से मैप करती है, और एक .json फ़ाइल जो टाइमस्टैम्प को पाए गए बुनियादी ब्लॉक पतों के सेट से मैप करती है। दोनों फ़ाइलें विशिष्ट फ़ज़िंग रन की कार्यशील निर्देशिका में स्थित हैं।
| स्क्रिप्ट | विवरण |
|---|
./env/start.sh | एक नया कंटेनर उत्पन्न करें या पहले से चल रहे कंटेनर में एक शेल उत्पन्न करें। पूर्व-निर्मित: USE_PREBUILT=1 निर्यात करने से पूर्व-निर्मित पर्यावरण पर आधारित कंटेनर उत्पन्न होता है। पूर्व-निर्मित से स्थानीय निर्माण या इसके विपरीत स्विच करने के लिए, पहले stop.sh निष्पादित किया जाना चाहिए। |
./env/stop.sh | यह कंटेनर को रोकता है। इमेज को पुनर्निर्माण के बाद इसे कॉल करना याद रखें। |
| कंटेनर पथ | होस्ट पथ | नोट |
|---|
/home/user/fuzztruction | ./ | पूर्व-निर्मित: यह फ़ोल्डर पूर्व-निर्मित इमेज का उपयोग करने की स्थिति में इमेज का हिस्सा है। इस प्रकार, परिवर्तन होस्ट पर प्रतिबिंबित नहीं होते हैं। |
/home/user/shared | ./ | होस्ट के साथ डेटा विनिमय करने के लिए उपयोग किया जाता है। |
/home/user/.zshrc | ./data/zshrc | - |
/home/user/.zsh_history | ./data/zsh_history | - |
/home/user/.bash_history | ./data/bash_history | - |
/home/user/.config/nvim/init.vim | ./data/init.vim | - |
/home/user/.config/Code | ./data/vscode-data | कंटेनर पुनरारंभ के बीच Visual Studio Code कॉन्फ़िग को बनाए रखने के लिए उपयोग किया जाता है। |
/ssh-agent | $SSH_AUTH_SOCK | यदि यह होस्ट पर चलता है तो कंटेनर के अंदर SSH-एजेंट का उपयोग करने की अनुमति देता है। |
/home/user/.gitconfig | /home/$USER/.gitconfig | होस्ट से gitconfig का उपयोग करें, यदि कोई कॉन्फ़िग है। |
/ccache | ./data/ccache | कंटेनर पुनरारंभ के बीच ccache कैश को बनाए रखने के लिए उपयोग किया जाता है। |
| कलाकृतियाँ | विवरण |
|---|
./generator/pass/fuzztruction-source-llvm-pass.so | LLVM पास का उपयोग जनरेटर एप्लिकेशन में पैच पॉइंट सम्मिलित करने के लिए किया जाता है। नोट: पास का स्थान /etc/ld.so.conf.d/fuzztruction.conf में रिकॉर्ड किया गया है; इस प्रकार, कंपाइलर संकलन के दौरान पास ढूंढने में सक्षम होते हैं। यदि आपको पास न मिलने के कारण समस्या होती है, तो कृपया sudo ldconfig चलाएँ और ताज़ा शेल का उपयोग करके पुनः प्रयास करें। |
./generator/pass/fuzztruction-source-clang-fast | जनरेटर एप्लिकेशन को संकलित करने के लिए एक कंपाइलर रैपर। यह रैपर हमारे कस्टम कंपाइलर पास का उपयोग करता है, लक्ष्यों को एजेंट से लिंक करता है, और जनरेटर के मेन में एजेंट के init विधि में एक कॉल इंजेक्ट करता है। |
./target/debug/libgenerator_agent.so | एजेंट जो जनरेटर एप्लिकेशन में इंजेक्ट किया जाता है। |
./target/debug/fuzztruction | वास्तविक फ़ज़र का प्रतिनिधित्व करने वाला fuzztruction बाइनरी। |