
फ्रीडा-आधारित इन-प्रोसेस फ़ज़िंग सूट, AFL++ प्रॉक्सी, स्टैंडअलोन सक्रिय/निष्क्रिय मोड, और विभिन्न प्लेटफार्मों पर उच्च-प्रदर्शन कवरेज-निर्देशित कमज़ोरी खोज के लिए साझा मेमोरी संचार।
fpicker एक Frida-आधारित फज़िंग सूट है जो इन-प्रोसेस फज़िंग के लिए विभिन्न प्रकार के फज़िंग मोड प्रदान करता है, जैसे कि AFL++ मोड या पैसिव ट्रेसिंग मोड। यह Frida द्वारा समर्थित सभी प्लेटफार्मों पर चलना चाहिए।
fpicker के पीछे कुछ पृष्ठभूमि जानकारी और विचार एक ब्लॉगपोस्ट में पाए जा सकते हैं जो मैंने लिखा था।
Fpicker पिछले प्रयासों पर आधारित है ToothPicker, जो मेरी मास्टर थीसिस के दौरान विकसित किया गया था। अधिकांश fpicker मेरे नियोक्ता (ERNW) पर काम के घंटों के दौरान विकसित किया गया था।
fpicker चलाने के लिए आवश्यक:
frida-core-devkit Frida releases on GitHub पर पाया जाता है।
libfrida-core-ios.a, libfrida-core-macos.a, या libfrida-core-linux.a के रूप में स्टोर करें।frida-core.h) के लिए भी यही बात लागू होती है। उन्हें प्लेटफॉर्म के अनुसार frida-core-linux.h या frida-core-ios.h के रूप में स्टोर करें।update_frida_version.sh चलाएँ।केवल AFL++ मोड में चलाने पर आवश्यक:
CFLAGS="-DUSEMMAP=1" के साथ संकलित करें।CFLAGS="-DUSEMMAP=1 -DTARGET_OS_IOS" के साथ संकलित करें।Fpicker को macOS, iOS या Linux के लिए बनाया जा सकता है। Makefile वर्तमान में केवल macOS पर iOS के लिए बिल्डिंग का समर्थन करता है, लेकिन Linux पर iOS टूलचेन का उपयोग करके fpicker बनाना पूरी तरह से संभव होना चाहिए।
वांछित लक्ष्य के अनुसार चलाएँ:
make fpicker-macos
make fpicker-ios
make fpicker-linux
fpicker बनाने के लिए।
एक बार fpicker बन जाने के बाद, अगला कदम फज़िंग हार्नेस बनाना है:
विभिन्न नमूना फज़िंग मामलों के लिए examples फ़ोल्डर देखें। सामान्य दृष्टिकोण इस प्रकार है:
examples/test/test.js) (हार्नेस के बारे में अधिक जानकारी के लिए यहाँ देखें)frida-compile test.js -o harness.jsअब fpicker फज़िंग शुरू कर सकता है। सटीक कमांड कॉन्फ़िगरेशन और सेटअप पर अत्यधिक निर्भर करता है। निम्नलिखित में, कुछ उदाहरण मामले दिए गए हैं। ये ज्यादातर examples फ़ोल्डर में दिए गए उदाहरणों के अनुरूप हैं।
afl-fuzz -i examples/test-network/in -o ./examples/test-network/out -- \\
./fpicker --fuzzer-mode afl -e attach -p test-network -f ./examples/test-network/harness.js
./fpicker --fuzzer-mode standalone -e attach -p server-process -f harness.js --input-mode cmd \\
--command "./client-send @@" -i indir -o outdir
./fpicker --fuzzer-mode active --communication-mode shm -e attach -p server-process -f harness.js \\
-i indir -o outdir --standalone-mutator cmd --mutator-command "radamsa"
./fpicker --fuzzer-mode passive --communication-mode send -e attach -p server-process -o outdir -f harness.js
./fpicker --fuzzer-mode active -e attach -p test -D remote -o examples/test/out/ -i examples/test/in/ \\
-f fuzzer-agent.js --standalone-mutator cmd --mutator-command "radamsa"
प्रत्येक लक्ष्य के लिए अपने स्वयं के फज़िंग हार्नेस की आवश्यकता होती है। इस हार्नेस का सबसे महत्वपूर्ण हिस्सा Frida के Stalker के प्रवेश फ़ंक्शन को परिभाषित करना है, जो प्रभावी रूप से यह निर्धारित करता है कि इंस्ट्रुमेंटेशन किस बिंदु पर डाला जाता है। in-process मोड में यह सरल है। फ़ंक्शन आमतौर पर वह होता है जो प्रत्येक फज़िंग पुनरावृत्ति पर कॉल किया जाता है। हालांकि, यह एक अलग भी हो सकता है।
एक न्यूनतम हार्नेस कार्यान्वयन (command मोड में) इस प्रकार हो सकता है:
// Import the fuzzer base class
const Fuzzer = require("harness/fuzzer.js");
// The custom fuzzer needs to subclass the Fuzzer class to work properly
class TestFuzzer extends Fuzzer.Fuzzer {
constructor() {
// The constructor needs to specify the address of the targeted function and a NativeFunction
// object that can later be called by the fuzzer.
const FUZZ_FUNCTION_ADDR = Module.getExportByName(null, "FUZZ_FUNCTION");
const FUZZ_FUNCTION = new NativeFunction(
FUZZ_FUNCTION_ADDR,
"void", ["pointer", "int64"], {
});
super("test", FUZZ_FUNCTION_ADDR, FUZZ_FUNCTION);
}
}
const f = new TestFuzzer();
exports.fuzzer = f;
यह हार्नेस इंस्ट्रुमेंटेशन को FUZZ_FUNCTION फ़ंक्शन का अनुसरण करने के लिए कॉन्फ़िगर करता है। इंस्ट्रुमेंटेशन तब शुरू होगा जब यह फ़ंक्शन प्रवेश करेगा और फ़ंक्शन के वापस लौटने पर रुक जाएगा। इस फ़ंक्शन को सावधानी से चुना जाना चाहिए क्योंकि यह महंगा है और प्रक्रिया के अधिक (संभावित रूप से महत्वहीन) भागों को इंस्ट्रुमेंट किया जाता है, फज़र उतना ही धीमा हो जाता है। बेशक, यह गति और इच्छित कवरेज के बीच एक विचार है। इसके अतिरिक्त, फज़र वर्तमान में केवल उन फ़ंक्शनों का समर्थन करता है जो एक फज़िंग पुनरावृत्ति के दौरान केवल एक बार प्रवेश करते हैं, अर्थात, फ़ंक्शन को एक फज़ केस के दौरान एक से अधिक बार कॉल नहीं किया जाना चाहिए, अन्यथा कवरेज जानकारी अविश्वसनीय हो सकती है।
जब in-process मोड का उपयोग किया जाता है, तो फज़र स्क्रिप्ट में एक और फ़ंक्शन की आवश्यकता होती है। fuzz विधि। यह प्रत्येक पुनरावृत्ति पर कॉल किया जाएगा। इसे दो पैरामीटर दिए जाएंगे, एक बफर के लिए पॉइंटर और बफर की लंबाई। हमारा उदाहरण लक्ष्य फ़ंक्शन दो पैरामीटर लेता है, एक बफर के लिए पॉइंटर और इसकी लंबाई। इस प्रकार, हम बस fuzz विधि में प्राप्त पैरामीटर पास कर सकते हैं।
fuzz(payload, len) {
this.target_function(payload, parseInt(len));
}
passive मोड में, एक कॉलबैक निर्दिष्ट करने की आवश्यकता होती है जो आवश्यक डेटा को प्रोसेस करता है। फज़र एक पेलोड बफर और इसकी लंबाई प्राप्त करने की अपेक्षा करता है। जिस लक्ष्य फ़ंक्शन को फज़ किया जा रहा है, उसके आधार पर, इस डेटा को निकालने की आवश्यकता होती है। निम्नलिखित उदाहरण में, हमारे पास फिर से एक फ़ंक्शन है जिसके दो पैरामीटर हैं: एक बफर के लिए पॉइंटर और इसकी लंबाई। args पैरामीटर में लक्ष्य फ़ंक्शन को प्राप्त होने वाले सभी संभावित पैरामीटर होते हैं, इसलिए लंबाई पैरामीटर (जो हमारे मामले में दूसरा है) को args[1] से एक्सेस किया जा सकता है। फिर हम बफर को Uint8Array के रूप में पढ़ते हैं और sendPassiveCorpus विधि का उपयोग करके इसे वापस फज़र को भेजते हैं।
passiveCallback(args) {
const len = args[1];
const data = new Uint8Array(Memory.readByteArray(args[0], parseInt(len)));
// this encodes the data and sends it back to the fuzzer
this.sendPassiveCorpus(data, len);
}
यदि लक्ष्य को फज़र शुरू होने से पहले किसी प्रकार की तैयारी की आवश्यकता होती है, तो fpicker एक prepare विधि प्रदान करता है जो फज़र के आरंभीकरण के दौरान कॉल की जाती है। तैयारी राज्य की स्थापना हो सकती है, उदाहरण के लिए, किसी ऑब्जेक्ट को इंस्टैंशिएट करके। ऐसा तैयारी फ़ंक्शन निम्नलिखित जैसा दिख सकता है:
prepare() {
// the object can be attached to the fuzzer instance so that it can be used within the
// fuzz() method later on.
this.required_object = call_native_function_that_creates_object();
}
pficker बड़ी संख्या में मोड और कॉन्फ़िगरेशन प्रदान करता है जिन्हें निम्नलिखित में समझाया गया है। इनमें से अधिकांश मोड को विभिन्न तरीकों से जोड़ा जा सकता है। इस अनुभाग के अंत में एक तालिका है जो दिखाती है कि कौन से विकल्प जोड़े जा सकते हैं और उनकी कार्यान्वयन स्थिति क्या है।
Fpicker के तीन अलग-अलग फज़िंग मोड हैं: AFL++ मोड, स्टैंडअलोन एक्टिव मोड और स्टैंडअलोन पैसिव मोड:
AFL++ मोड: AFL++ मोड में, fpicker AFL++ और लक्ष्य प्रक्रिया के बीच एक प्रॉक्सी के रूप में कार्य करता है। Frida की इंस्ट्रुमेंटेशन क्षमताओं का उपयोग करके, AFL का कवरेज बिटमैप भरा जाता है जबकि लक्ष्य को AFL++ द्वारा उत्पन्न इनपुट डेटा के साथ फज़ किया जाता है।
स्टैंडअलोन एक्टिव मोड: स्टैंडअलोन एक्टिव मोड में, फज़र एक पुनरावृत्ति के दौरान निष्पादित बुनियादी ब्लॉकों के रूप में कवरेज एकत्र करने के लिए Frida के Stalker कॉल सारांश का उपयोग करता है। यह कोई नई बात नहीं है और पहले विभिन्न रूपों में लागू किया गया है। हालांकि, कुछ अन्य फज़र सेटिंग्स के संयोजन में इसके विभिन्न लाभ हो सकते हैं। यह एक अच्छा विकल्प भी है यदि किसी दिए गए वातावरण या मामले में AFL++ लागू या वांछित नहीं है।
स्टैंडअलोन पैसिव मोड: पैसिव मोड एक फज़र से अधिक एक ट्रेसर है। मूल रूप से, यह स्टैंडअलोन एक्टिव मोड के समान ही करता है। हालांकि, यह अपने स्वयं के इनपुट नहीं भेजता है। यह सिर्फ एक निश्चित फ़ंक्शन से जुड़ता है और कवरेज एकत्र करता है। एक बार नया कवरेज देखा जाने पर, कवरेज और इनपुट दोनों संग्रहीत किए जाते हैं।
जबकि fpicker काफी हद तक एक इन-प्रोसेस फज़र के रूप में डिज़ाइन किया गया है, यह बाहरी कमांड के माध्यम से फज़िंग का भी समर्थन करता है। इसके लिए fpicker दो इनपुट मोड प्रदान करता है।
इनपुट मोड इन-प्रोसेस: इन-प्रोसेस इनपुट मोड में, हार्नेस सीधे लक्ष्य प्रक्रिया में एक निर्दिष्ट फ़ंक्शन को कॉल करता है। फज़र हार्नेस को पेलोड भेजता है और हार्नेस पेलोड को इस प्रकार तैयार करता है कि वह लक्षित फ़ंक्शन को कॉल कर सके।
इनपुट मोड CMD: कमांड इनपुट मोड में, पेलोड को एक बाहरी कमांड पर रीडायरेक्ट किया जाता है। यह तब उपयोगी होता है जब सीधे लक्ष्य फ़ंक्शन को कॉल करते समय पैरामीटर या अन्य स्थिति तैयार करना बहुत जटिल हो। कवरेज संग्रह को अभी भी एक निश्चित फ़ंक्शन से जोड़ा जाना चाहिए। हो सकता है कि कोई क्लाइंट हो जिसे पेलोड प्रदान किया जा सके जो फिर लक्ष्य फ़ंक्शन को ट्रिगर करता है।
संचार मोड यह निर्धारित करता है कि इंजेक्टेड हार्नेस फज़र के साथ कैसे संवाद करता है। यह काफी हद तक लक्ष्य एप्लिकेशन पर निर्भर करता है। Frida इंजेक्टेड एजेंट स्क्रिप्ट से संदेश भेजने और प्राप्त करने के लिए एक API प्रदान करता है। इस प्रकार का संचार काफी महंगा है। कारकों में से एक यह है कि परिवहन किए गए संदेश को JSON में एन्कोड करने की आवश्यकता होती है। इसलिए बाइनरी डेटा भेजना सीधा है। इसलिए, fpicker साझा मेमोरी पर एक दूसरे संचार मोड प्रदान करता है। हालांकि, यह केवल तभी काम करता है जब फज़र और लक्ष्य एप्लिकेशन के बीच साझा मेमोरी स्थापित करना संभव हो, जिसका अर्थ है कि जब लक्ष्य USB के माध्यम से फज़र होस्ट से जुड़ा होता है तो इस मोड का उपयोग नहीं किया जा सकता है। CMD इनपुट मोड में, संचार मोड केवल इस बात को संदर्भित करता है कि कवरेज जानकारी फज़र को वापस कैसे संप्रेषित की जाती है, न कि पेलोड कैसे भेजा जाता है, क्योंकि यह एक बाहरी कमांड को सौंपा जाता है।
संचार मोड Send: Send संचार मोड में, पेलोड Frida के RPC कॉलिंग तंत्र का उपयोग करके भेजा जाता है। यह फज़र को इंजेक्टेड हार्नेस स्क्रिप्ट के भीतर एक JavaScript फ़ंक्शन को निष्पादित करने देता है। हार्नेस के अंदर यह फ़ंक्शन लक्ष्य फ़ंक्शन को कॉल करने के लिए सभी आवश्यक तैयारी कर सकता है। एक बार लक्ष्य फ़ंक्शन से वापस आने के बाद, कवरेज संग्रह बंद हो जाएगा और हार्नेस फज़र को संकेत दे सकता है कि पुनरावृत्ति समाप्त हो गई है। यह Frida की send API का उपयोग करके कवरेज जानकारी वापस फज़र को भेजकर किया जाता है।
संचार मोड SHM: SHM संचार मोड में, फज़र और हार्नेस स्क्रिप्ट साझा मेमोरी और सेमाफोर के माध्यम से संवाद करते हैं। पेलोड भेजने और कवरेज जानकारी प्राप्त करने के लिए साझा मेमोरी में एक बफर का उपयोग किया जाता है। भेजने और प्राप्त करने के बजाय, दो घटक सेमाफोर पर प्रतीक्षा और पोस्ट करने का उपयोग करते हैं। सिस्टम और लक्ष्य के आधार पर, यह काफी प्रदर्शन लाभ लाता है। विशेष रूप से, क्योंकि बाइनरी पेलोड एक बार मेमोरी में लिखा जाता है और इसे एन्कोड और डीकोड करने या अन्य मेमोरी स्थानों पर कॉपी करने की आवश्यकता नहीं होती है। दुर्भाग्य से, यह मोड कभी-कभी AFL++ के साथ चलने पर कम स्थिरता की ओर ले जाता है। अभी तक पता नहीं क्यों।
एक्ज़ीक्यूशन मोड या तो spawn या attach हो सकता है। यह काफी स्पष्ट है। fpicker या तो चल रही प्रक्रिया से जुड़ सकता है या एक प्रक्रिया को स्पॉन कर सकता है। एक बात जो दोनों मोड के बीच एक बड़ा अंतर है, वह यह है कि यदि अटैच किया गया लक्ष्य क्रैश हो जाता है, तो fpicker पुनर्स्थापित करने का प्रयास नहीं करेगा।
स्टैंडअलोन मोड में fpicker तीन अलग-अलग इनपुट म्यूटेशन रणनीतियाँ प्रदान करता है। अच्छी तरह से कहा जाए तो, इनपुट म्यूटेशन में निश्चित रूप से सुधार की बहुत गुंजाइश है।
स्टैंडअलोन म्यूटेटर NULL: यह म्यूटेटर पेलोड को म्यूटेट नहीं करता है और सिर्फ उसी पेलोड की एक प्रति लौटाता है। ज्यादातर परीक्षण उद्देश्यों के लिए। अन्यथा वास्तव में उपयोगी नहीं है।
स्टैंडअलोन म्यूटेटर Rand: एक बहुत ही खराब यादृच्छिक म्यूटेटर। यह केवल मूल पेलोड में यादृच्छिक स्थानों पर मानों को यादृच्छिक रूप से बदलता है। यह पेलोड की लंबाई नहीं बदलता है।
स्टैंडअलोन म्यूटेटर कस्टम: यह म्यूटेटर पेलोड को म्यूटेट करने के लिए एक बाहरी कमांड को कॉल कर सकता है। यह पेलोड को stdin में लिखता है और म्यूटेटेड पेलोड को stdout से प्राप्त करता है। इसके उथले कार्यान्वयन के कारण इसका प्रदर्शन पर काफी प्रभाव पड़ता है।
-D usb डिवाइस विकल्प का उपयोग करके, Frida पहले स्थानीय USB उपकरण का चयन करेगा, जैसे कि iPhone या Android फ़ोन।
-D remote विकल्प के साथ नेटवर्क उपकरण पर चल रही प्रक्रिया को फज़ करना संभव है। इसके लिए, रिमोट उपकरण पर frida-server चल रहा होना चाहिए। एक नमूना कॉन्फ़िगरेशन के रूप में, रिमोट उपकरण पर frida-server के डिफ़ॉल्ट लिसनिंग पोर्ट 27042 को स्थानीय क्लाइंट पर एक सॉकेट से बांधने के लिए SSH का उपयोग पोर्ट फ़ॉरवर्डिंग के साथ करें।
ssh -N [email protected] -L 127.0.0.1:27042:127.0.0.1:27042
iPhone पर, USB कनेक्शन से पोर्ट को फ़ॉरवर्ड करने के लिए iproxy का भी उपयोग किया जा सकता है। यह विशेष रूप से उपयोगी हो सकता है यदि Frida को Frida गैजेट के साथ एक नॉन-जेलब्रेकन उपकरण पर एक गैर-मानक पोर्ट पर चलाया जा रहा हो। Frida गैजेट के साथ काम करते समय, उपलब्ध एकमात्र प्रक्रिया का नाम Gadget होगा, चाहे लक्ष्य ऐप का नाम कुछ भी हो।
iproxy 27042 27042
फिर रिमोट उपकरण पर प्रक्रियाओं को सूचीबद्ध करके कॉन्फ़िगरेशन को मान्य करने के लिए frida-ps का उपयोग करें:
frida-ps -R