
एक कवरेज-निर्देशित फ़ज़र जो शुद्ध Ruby कोड और Ruby C एक्सटेंशन के लिए है
शुद्ध Ruby कोड और Ruby C एक्सटेंशन के लिए एक कवरेज-निर्देशित फज़र।
Ruzzy, Google के Atheris (एक Python फज़र) से बहुत प्रभावित है। Ruzzy अपने कवरेज इंस्ट्रुमेंटेशन और फ़ज़िंग इंजन के लिए libFuzzer (या LibAFL) का उपयोग करता है। Ruzzy, C एक्सटेंशन की फ़ज़िंग करते समय AddressSanitizer और UndefinedBehaviorSanitizer का भी समर्थन करता है। यदि आप Ruzzy के पीछे की प्रेरणा के बारे में अधिक जानना चाहते हैं, तो हमारा पेपर देखें: Design and Implementation of a Coverage-Guided Ruby Fuzzer।
विषय सूची:
Ruzzy Linux (x86-64, AArch64/ARM64) और macOS (Apple Silicon) को समर्थन करता है। Windows पर, आप Dockerfile बना सकते हैं और/या विकास वातावरण का उपयोग कर सकते हैं। Ruzzy को clang के एक हालिया संस्करण (परीक्षण 14.0.0 तक किया गया) की आवश्यकता है, अधिमानतः नवीनतम रिलीज़। macOS-विशिष्ट सेटअप के लिए, macOS उपयोगकर्ताओं के लिए नोट्स देखें।
निम्नलिखित कमांड से Ruzzy स्थापित करें:
MAKE="make --environment-overrides V=1" \
CC="/path/to/clang" \
CXX="/path/to/clang++" \
LDSHARED="/path/to/clang -shared" \
LDSHAREDXX="/path/to/clang++ -shared" \
gem install ruzzy
यहाँ बहुत कुछ चल रहा है, तो आइए इसे तोड़कर समझें:
MAKE पर्यावरण चर Ruzzy C एक्सटेंशन को संकलित करते समय make कमांड को ओवरराइड करता है। यह make को एक्सटेंशन संकलित करते समय बाद के पर्यावरण चरों का सम्मान करने का निर्देश देता है।clang बाइनरी का उपयोग कर रहे हैं। यह सुनिश्चित करता है कि हमारे पास नवीनतम clang सुविधाएँ हों, जो उचित फ़ज़िंग के लिए आवश्यक हैं।यदि स्थापित करने में समस्या आती है, तो डीबग आउटपुट प्राप्त करने के लिए निम्नलिखित कमांड चलाएँ:
RUZZY_DEBUG=1 gem install --verbose ruzzy
यदि आपका शुद्ध Ruby फ़ज़िंग लक्ष्य रेगेक्सप का भारी उपयोग करता है, तो regexp_parser स्थापित करें:
gem install regexp_parser
एक बार स्थापित होने के बाद, Ruzzy फ़ज़िंग के दौरान मिलने वाले रेगेक्सप को सैंपल (अर्थात हल) करने के लिए स्वचालित रूप से इस कार्यक्षमता का उपयोग करेगा। यह फ़ज़र को रेगेक्सप शर्तों को पार करने और अतिरिक्त कवरेज को अनलॉक करने की अनुमति देता है।
Ruzzy में यह प्रदर्शित करने के लिए एक टॉय उदाहरण शामिल है कि यह कैसे काम करता है। पहले, निम्नलिखित पर्यावरण चर सेट करें:
export ASAN_OPTIONS="allocator_may_return_null=1:detect_leaks=0:use_sigaltstack=0"
ASAN_OPTIONSफिर निम्नलिखित कमांड से उदाहरण चलाएँ:
LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
ruby -e 'require "ruzzy"; Ruzzy.dummy'
LD_PRELOAD उन्हीं कारणों से आवश्यक है जैसे Atheris में। हालाँकि, ASAN_OPTIONS के विपरीत, आप शायद इसे export नहीं करना चाहेंगे क्योंकि यह अन्य प्रोग्रामों में हस्तक्षेप कर सकता है।
इसे शीघ्र ही निम्नलिखित जैसी क्रैश उत्पन्न करनी चाहिए:
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 2527961537
...
==45==ERROR: AddressSanitizer: heap-use-after-free on address 0x50c0009bab80 at pc 0xffff99ea1b44 bp 0xffffce8a67d0 sp 0xffffce8a67c8
...
SUMMARY: AddressSanitizer: heap-use-after-free /var/lib/gems/3.1.0/gems/ruzzy-0.8.0/ext/dummy/dummy.c:18:24 in _c_dummy_test_one_input
...
==45==ABORTING
MS: 4 EraseBytes-CopyPart-CopyPart-ChangeBit-; base unit: 410e5346bca8ee150ffd507311dd85789f2e171e
0x48,0x49,
HI
artifact_prefix='./'; Test unit written to ./crash-253420c1158bc6382093d409ce2e9cff5806e980
Base64: SEk=
हम देख सकते हैं कि इसने सही ढंग से उस इनपुट ("HI") को खोज लिया जिसने मेमोरी उल्लंघन उत्पन्न किया। अधिक जानकारी के लिए, यह देखने के लिए dummy.c देखें कि यह उल्लंघन क्यों हुआ।
आप निम्नलिखित कमांड से क्रैश केस को फिर से चला सकते हैं:
LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
ruby -e 'require "ruzzy"; Ruzzy.dummy' \
./crash-253420c1158bc6382093d409ce2e9cff5806e980
निम्नलिखित सैनिटाइज़र उपलब्ध हैं:
Ruzzy::ASAN_PATH AddressSanitizer के लिएRuzzy::UBSAN_PATH UndefinedBehaviorSanitizer के लिएआइए एक उदाहरण के रूप में एक छोटी Ruby स्क्रिप्ट को फ़ज़ करें। शुद्ध Ruby कोड की फ़ज़िंग के लिए दो Ruby स्क्रिप्ट की आवश्यकता होती है: एक ट्रेसर स्क्रिप्ट और एक फ़ज़िंग हार्नेस। Ruby इंटरप्रेटर के कार्यान्वयन विवरण के कारण ट्रेसर स्क्रिप्ट आवश्यक है।
पहले, ट्रेसर स्क्रिप्ट, चलिए इसे test_tracer.rb कहते हैं:
# frozen_string_literal: true
require 'ruzzy'
Ruzzy.trace('test_harness.rb')
अगला, फ़ज़िंग हार्नेस, चलिए इसे test_harness.rb कहते हैं:
# frozen_string_literal: true
require 'ruzzy'
def fuzzing_target(input)
if input.length == 4
if input[0] == 'F'
if input[1] == 'U'
if input[2] == 'Z'
if input[3] == 'Z'
raise
end
end
end
end
end
end
test_one_input = lambda do |data|
fuzzing_target(data) # Your fuzzing target would go here
return 0
end
Ruzzy.fuzz(test_one_input)
आप इस फ़ाइल को चला सकते हैं और निम्नलिखित कमांड से फ़ज़िंग शुरू कर सकते हैं:
LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
ruby test_tracer.rb
इसे शीघ्र ही निम्नलिखित जैसी क्रैश उत्पन्न करनी चाहिए: