
एक स्वचालित अनपैकर और लॉगर जो DotNet Framework को लक्षित करने वाली फ़ाइलों के लिए है।
DotNet फ्रेमवर्क लक्षित फ़ाइलों के लिए एक स्वचालित अनपैकर और लॉगर! इस उपकरण का अनावरण Black Hat USA 2022 में किया गया था। Black Hat Asia 2023 में, DotDumperGUI और DotDumperNative को DotDumper के संस्करण 1.1-stable के साथ प्रकाशित किया गया। ये तीनों उपकरण एक साथ उपयोग किए जाने के लिए हैं, जहाँ DotDumper 1.1-stable को DotDumperNative की DLLs की आवश्यकता होती है, जबकि DotDumperGUI एक ग्राफिकल यूज़र-इंटरफ़ेस के रूप में है जो DotDumper रन से JSON आउटपुट को खोलने और फ़िल्टर करने के लिए है।
किसी भी फ़ाइल का स्वचालित रूप से विश्वसनीय तरीके से पता लगाना और वर्गीकरण करना अक्सर मैलवेयर विश्लेषण की पवित्र कलश (holy grail) माना जाता है। वहाँ पहुँचने के लिए कई परीक्षण और कठिनाइयाँ हैं, यही कारण है कि ऐसी प्रणाली के निर्माण को उच्च सम्मान दिया जाता है। जब DotNet लक्षित बाइनरी की बात आती है, तो हमारा नया ओपन-सोर्स उपकरण DotDumper रास्ते में कई महत्वपूर्ण चरणों में सहायता करने का लक्ष्य रखता है: (इन-मेमोरी) गतिविधि लॉग करना, दिलचस्प मेमोरी सेगमेंट डंप करना, और दिए गए नमूने से विशेषताएँ निकालना।
संक्षेप में, मैन्युअल अनपैकिंग एक कठिन प्रक्रिया है जो विश्लेषकों के लिए असमान समय खर्च करती है। अस्पष्ट बाइनरी (obfuscated binaries) उस समय को और बढ़ा देती हैं जो एक विश्लेषक को किसी फ़ाइल को अनपैक करने में लगाना पड़ता है। जब इसे स्केल किया जाता है, तो संगठनों को कई विश्लेषकों की आवश्यकता होती है जो हर दिन मैलवेयर का विश्लेषण करते हैं, संभवतः एक स्केलेबल सैंडबॉक्स के साथ। खोया हुआ मूल्यवान समय नए खतरों को उजागर करने के लिए दिलचस्प अभियानों या नमूनों में गहराई से जाने में उपयोग किया जा सकता था, न कि व्यापक रूप से फैले सामान्य मैलवेयर के बजाय। आखिरकार, विश्लेषक घास के ढेर में कुछ सुइयों की तलाश करते हैं।
तो, DotDumper क्या अंतर लाता है? DotDumper के माध्यम से एक DotNet आधारित मैलवेयर नमूना चलाने से तीन प्रारूपों (मानव-पठनीय सादा पाठ, JSON, और XML) में महत्वपूर्ण, प्रासंगिक और सामान्य फ़ंक्शन कॉल की लॉग फ़ाइलें मिलती हैं, साथ ही उपयोगी इन-मेमोरी सेगमेंट की प्रतियां भी मिलती हैं। इस प्रकार, एक विश्लेषक फ़ंक्शन कॉल लॉग को स्किम कर सकता है। इसके अतिरिक्त, डंप की गई फ़ाइलों को वर्गीकृत करने के लिए स्कैन किया जा सकता है, जिससे मैलवेयर नमूने और उसमें निहित डेटा के बारे में अतिरिक्त जानकारी मिलती है। इससे ट्रायेज और घटना प्रतिक्रिया प्रक्रियाओं के लिए महत्वपूर्ण समय कम होता है, और SOC विश्लेषक और शोधकर्ता का समय अधिक परिष्कृत विश्लेषण आवश्यकताओं के लिए मुक्त होता है।
प्रासंगिक फ़ंक्शन कॉल और उनके परिणामों को लॉग और डंप करने के लिए, DotDumper रिफ्लेक्शन और प्रबंधित हुक के मिश्रण का उपयोग करता है, जो सभी शुद्ध C# में लिखे गए हैं। नीचे, प्रमुख विशेषताओं पर प्रकाश डाला और विस्तार से बताया जाएगा, साथ ही एक पैक किए गए AgentTesla स्टीलर नमूने के DotDumper परिणामों के अंश दिए जाएंगे, जिनके हैश नीचे दिए गए हैं।
| हैश प्रकार | हैश मान |
|---|---|
| SHA-256 | b7512e6b8e9517024afdecc9e97121319e7dad2539eb21a79428257401e5558d |
| SHA-1 | c10e48ee1f802f730f41f3d11ae9d7bcc649080c |
| MD-5 | 23541daadb154f1f59119952e7232d6b |
DotDumper एक कमांड-लाइन इंटरफ़ेस के माध्यम से सुलभ है, जिसमें विभिन्न तर्क हैं। नीचे दी गई छवि सहायता मेनू दिखाती है। ध्यान दें कि सभी तर्कों पर चर्चा नहीं की जाएगी, बल्कि केवल सबसे अधिक उपयोग किए जाने वाले तर्कों पर चर्चा की जाएगी।

किसी दिए गए नमूने को चलाने के लिए न्यूनतम आवश्यकता " -file " तर्क प्रदान करना है, साथ ही एक फ़ाइल नाम या फ़ाइल पथ। यदि पूरा पथ दिया गया है, तो इसका उपयोग किया जाता है। यदि फ़ाइल नाम दिया गया है, तो वर्तमान कार्यशील निर्देशिका के साथ-साथ DotDumper के निष्पादन योग्य स्थान के फ़ोल्डर की जाँच की जाती है।
जब तक कोई निर्देशिका नाम प्रदान नहीं किया जाता, तब तक " -log " फ़ोल्डर नाम नमूने के फ़ाइल नाम के बराबर सेट किया जाता है (यदि कोई एक्सटेंशन है तो उसके बिना)। फ़ोल्डर उसी फ़ोल्डर में स्थित होता है जहाँ DotDumper रहता है, जहाँ लॉग और डंप की गई फ़ाइलें सहेजी जाएंगी।
लाइब्रेरी या बाइनरी में वैकल्पिक प्रवेश बिंदु के मामले में, किसी को " -overrideEntry true " का उपयोग करके प्रवेश बिंदु को ओवरराइड करना होगा। इसके अतिरिक्त, किसी को पूरी तरह से योग्य क्लास प्रदान करनी होगी, जिसमें नाम स्थान शामिल है, " -fqcn My.NameSpace.MyClass " का उपयोग करके। यह DotDumper को बताता है कि किस क्लास का चयन करना है, जहाँ से प्रदान किया गया फ़ंक्शन नाम (" -functionName MyFunction " का उपयोग करके) प्राप्त किया जाता है।
यदि चयनित फ़ंक्शन को तर्कों की आवश्यकता है, तो किसी को " -argc " का उपयोग करके तर्कों की संख्या और आवश्यक तर्कों की संख्या प्रदान करनी होगी। तर्क प्रकार और मान " string|myValue int|9 " के रूप में प्रदान किए जाने हैं। ध्यान दें कि जब मानों में स्पेस का उपयोग किया जाता है, तो कमांड-लाइन इंटरफ़ेस पर तर्क को उद्धरणों के बीच संलग्न करने की आवश्यकता होती है ताकि यह सुनिश्चित हो सके कि इसे एकल तर्क के रूप में पारित किया गया है।
" -raceTime " या " -deprecated " जैसे अन्य कम उपयोग किए जाने वाले विकल्प अपनी डिफ़ॉल्ट सेटिंग्स में सुरक्षित हैं, लेकिन DotNet फ्रेमवर्क में बदलावों के कारण भविष्य में ट्वीकिंग की आवश्यकता हो सकती है। वे वर्तमान में कमांड-लाइन इंटरफ़ेस में उजागर होते हैं ताकि यदि आवश्यक हो, तो परिवर्तन आसानी से किए जा सकें, भले ही कोई DotDumper के पुराने संस्करण का उपयोग कर रहा हो।
लॉगिंग और डंपिंग DotDumper की दो मुख्य विशेषताएं हैं। विश्लेषण में लगने वाले समय को कम करने के लिए, लॉगिंग को विश्लेषक को संदर्भ प्रदान करना चाहिए। यह विश्लेषक को प्रत्येक लॉग किए गए फ़ंक्शन कॉल के लिए निम्नलिखित जानकारी प्रदान करके किया जाता है:
ध्यान दें कि प्रत्येक डंप की गई फ़ाइल के लिए, फ़ाइल का नाम फ़ाइल के SHA-256 हैश के बराबर होता है।
उपरोक्त को स्पष्ट करने के लिए, लॉग का एक अंश नीचे दिया गया है। अंश उपरोक्त AgentTesla नमूने का विवरण दिखाता है, जहाँ यह DotNet के Assembly.Load फ़ंक्शन का उपयोग करके दूसरे चरण को लोड करता है।
![इंटरसेप्ट किए गए Assembly.Load(byte[] rawAssembly) फ़ंक्शन कॉल का लॉग](images/assembly_load.png)
पहले, स्थानीय सिस्टम समय दिया जाता है, साथ ही मूल फ़ंक्शन के वापसी प्रकार, नाम और तर्क दिए जाते हैं। दूसरे, स्टैक ट्रेस दिया जाता है, जहाँ यह दिखाता है कि नमूने का मुख्य फ़ंक्शन एक कंस्ट्रक्टर की ओर जाता है, घटकों को आरंभ करता है, और दो कस्टम फ़ंक्शन कॉल करता है। Assembly.Load फ़ंक्शन को "NavigationLib.TaskEightBestOil.GGGGGGGGGGGGGGGGGGGG(String str)" के अंदर से कॉल किया गया था। यह विश्लेषक के लिए संदर्भ प्रदान करता है ताकि यदि रुचि हो तो इस कॉल के आसपास के कोड को ढूंढ सके।
फिर, असेम्बली कॉल ऑर्डर के बारे में जानकारी दी जाती है। जितने अधिक चरण लोड होते हैं, यह देखना उतना ही जटिल हो जाता है कि किस चरण के माध्यम से कॉल आया। आमतौर पर, एक चरण अगले को लोड करता है, लेकिन कुछ मामलों में बाद के चरण पिछले चरणों का गैर-रैखिक क्रम में उपयोग करते हैं। इसके अतिरिक्त, उत्पत्ति असेम्बली के बारे में जानकारी दी जाती है ताकि विश्लेषक के लिए डेटा और समृद्ध हो सके।
इसके बाद, मूल हैश दिया जाता है। एक चरण का मूल पिछला चरण है, जो इस उदाहरण में अभी तक मौजूद नहीं है। नए लोड किए गए चरण का यह चरण उसका मूल होगा। यह विश्लेषक को घटनाओं को अधिक आसानी से सहसंबंधित करने की अनुमति देता है।
अंत में, फ़ंक्शन के वापसी प्रकार और मान को संग्रहीत किया जाता है, साथ ही हुक किए गए फ़ंक्शन को पारित किए गए प्रत्येक तर्क के प्रकार, नाम और मान को संग्रहीत किया जाता है। यदि कोई चर आकार में 100 बाइट्स से बड़ा है, तो इसे डिस्क पर संग्रहीत किया जाता है। लॉग में एक संदर्भ डाला जाता है जो फ़ाइल को संदर्भित करता है, न कि मान दिखाने के लिए। थ्रेशोल्ड लॉग के प्रिंटिंग में रुकावट से बचने के लिए सेट किया गया है, क्योंकि कुछ एरे आकार में हजारों इंडेक्स के होते हैं।
Microsoft के दस्तावेज़ीकरण के अनुसार, रिफ्लेक्शन को सबसे अच्छा सारांशित किया गया है "[...] ऐसे ऑब्जेक्ट प्रदान करता है जो असेम्बली, मॉड्यूल और प्रकारों को समाहित करते हैं"। संक्षेप में, यह मैलवेयर नमूने से DotNet वर्गों और फ़ंक्शनों के गतिशील निर्माण और आह्वान की अनुमति देता है। DotDumper में एक रिफ्लेक्टिव लोडर है जो एक विश्लेषक को निष्पादन योग्य और लाइब्रेरी दोनों को लोड और विश्लेषण करने की अनुमति देता है, जब तक वे DotNet फ्रेमवर्क आधारित हैं।
लोडर का उपयोग करने के लिए, किसी को कमांड-लाइन इंटरफ़ेस में प्रवेश बिंदु को ओवरराइट करना होगा, किसी दिए गए फ़ाइल के भीतर क्लास (इसमें मौजूद नाम स्थान सहित) और फ़ंक्शन नाम निर्दिष्ट करना होगा। वैकल्पिक रूप से, कोई निर्दिष्ट फ़ंक्शन को तर्क प्रदान कर सकता है, सभी मूल प्रकारों और उनके एरे के लिए। मूल प्रकारों के उदाहरण int, string, char और एरे जैसे int[], string[], और char[] हैं। सभी तर्क कमांड-लाइन इंटरफ़ेस के माध्यम से प्रदान किए जाने हैं, जहाँ प्रकार और मान दोनों निर्दिष्ट किए जाने हैं।
प्रवेश बिंदु को ओवरराइड नहीं करने के परिणामस्वरूप डिफ़ॉल्ट प्रवेश बिंदु का उपयोग किया जाता है। डिफ़ॉल्ट रूप से, नमूने के मुख्य फ़ंक्शन की ओर एक खाली स्ट्रिंग एरे पारित किया जाता है, जैसे कि नमूना बिना तर्कों के निष्पादित किया गया हो।
इसके अतिरिक्त, रिफ्लेक्शन का उपयोग अक्सर लोडरों द्वारा अगले चरण में किसी दिए गए वर्ग में किसी दिए गए फ़ंक्शन को लागू करने के लिए किया जाता है। कभी-कभी, तर्क भी साथ पारित किए जाते हैं, जिनका उपयोग बाद में किसी संसाधन को डिक्रिप्ट करने के लिए किया जाता है। उपरोक्त AgentTesla नमूने में, यह सटीक परिदृश्य सामने आता है। DotDumper के इनवोक से संबंधित हुक इन घटनाओं को लॉग करते हैं, जैसा कि नीचे देखा जा सकता है।

पहली पंक्ति में फ़ंक्शन नाम DotNet फ्रेमवर्क का आंतरिक फ़ंक्शन नहीं है, बल्कि दूसरे चरण में एक विशिष्ट फ़ंक्शन का कॉल है। फ़ंक्शन हस्ताक्षर में तीन तर्कों के प्रकार और नाम सूचीबद्ध हैं। उनके मान फ़ंक्शन तर्क जानकारी अनुभाग में पाए जा सकते हैं। यह एक विश्लेषक को दूसरे चरण को एक कस्टम लोडर में दिए गए मानों के साथ लोड करने की अनुमति देगा, या पहले डंप किए गए चरण को लोड करके और तर्क प्रदान करके DotDumper का उपयोग करके भी ऐसा कर सकता है।
प्रबंधित हुक में जाने से पहले, किसी को यह समझने की आवश्यकता है कि हुक कैसे काम करते हैं। यहाँ दो मुख्य चर हैं: लक्ष्य फ़ंक्शन और एक नियंत्रित फ़ंक्शन जिसे हुक कहा जाता है। सीधे शब्दों में कहें, लक्ष्य फ़ंक्शन (जैसे Assembly.Load) पर मेमोरी को बदल दिया जाता है ताकि वह हुक पर कूद जाए। इस प्रकार, प्रोग्राम के निष्पादन प्रवाह को मोड़ दिया जाता है। हुक तब मनमानी क्रियाएं कर सकता है, वैकल्पिक रूप से मूल फ़ंक्शन को कॉल कर सकता है, जिसके बाद यदि आवश्यक हो तो वापसी मान के साथ निष्पादन को कॉलर को वापस कर देता है। नीचे दिया गया आरेख इस प्रक्रिया को दर्शाता है।

यह जानना कि हुक क्या हैं, यह समझने के लिए आवश्यक है कि प्रबंधित हुक क्या हैं। प्रबंधित कोड एक आभासी और प्रबंधित वातावरण में निष्पादित होता है, जैसे DotNet रनटाइम या जावा का वर्चुअल मशीन। जहाँ प्रबंधित फ़ंक्शन रहता है उसका मेमोरी पता प्राप्त करना C जैसी अप्रबंधित भाषा से भिन्न होता है। दोनों फ़ंक्शनों के लिए सही मेमोरी पते प्राप्त होने के बाद, असुरक्षित C# का उपयोग करके सीधे मेमोरी तक पहुँचकर, DotNet की इंटरऑपरेबिलिटी सेवा के साथ मूल विंडोज API कार्यक्षमता को कॉल करके हुक सेट किया जा सकता है।
DotDumper v1.1-stable के बाद से, DotDumper अप्रबंधित (या यदि आप चाहें तो मूल) फ़ंक्शन को भी हुक कर सकता है। फ़ंक्शन रीडायरेक्शन प्रबंधित और अप्रबंधित फ़ंक्शनों से और उनके लिए कोई भी संयोजन हो सकता है, एक महत्वपूर्ण चेतावनी के साथ। कोई भी अप्रबंधित फ़ंक्शन जो प्रबंधित हुक का उपयोग करता है, स्टैक के मानों को ठीक से पढ़ने में सक्षम नहीं होगा। इस प्रकार, एक मूल घटक की आवश्यकता होती है (जिसे DotDumperNative नाम दिया गया है)। यह घटक स्वयं DotDumper के साथ एक नामित पाइप के माध्यम से संचार करता है, इस प्रकार इसकी केंद्रीकृत लॉगिंग प्रणाली का उपयोग करता है, जबकि स्टैक पर पाए जाने वाले फ़ंक्शन तर्कों तक पहुँच के साथ अप्रबंधित कॉल को इंटरसेप्ट करता है।
चूंकि DotDumper बिना किसी बाहरी निर्भरता के शुद्ध C# में लिखा गया है, कोई भी Visual Studio का उपयोग करके फ्रेमवर्क को आसानी से विस्तारित कर सकता है। कोड इस ब्लॉग, GitHub पर, और कक्षाओं, फ़ंक्शनों और स्रोत कोड में इन-लाइन में प्रलेखित है। यह, स्पष्ट नामकरण योजना के साथ, किसी को भी उपकरण को अपनी इच्छानुसार संशोधित करने की अनुमति देता है, जिससे उपकरण को समझने में लगने वाले समय और प्रयास को कम किया जा सकता है। इसके बजाय, यह डेवलपर्स और विश्लेषकों को समान रूप से अपने प्रयासों को उपकरण के सुधार पर केंद्रित करने की अनुमति देता है।
जबकि सैंडबॉक्स टाइमआउट समर्थन सुविधा को बदला या संशोधित नहीं किया गया है, यह पहले प्रलेखित नहीं था। चूंकि DotDumper दी गई फ़ाइल को निष्पादित करता है, इसका निष्पादन तब तक जारी रहेगा जब तक नमूना समाप्त नहीं होता। मैलवेयर अक्सर "प्रतीक्षा" स्थिति में प्रवेश करता है, जहाँ पुनः सक्रिय होने से पहले एक निश्चित शर्त पूरी होनी चाहिए, या मैलवेयर एक अलग प्रक्रिया में निष्पादन जारी रखता है (प्रक्रिया इंजेक्शन की सहायता से)। उदाहरण के लिए, एक खोखली प्रक्रिया में नव निर्मित थ्रेड समाप्त होने के बाद ही वापस आता है।
रुकावट से बचने के लिए, DotDumper में एक स्थिरता हैंडलर (stagnation handler) है। हर बार जब किसी हुक के परिणाम लॉग किए जाते हैं, एक काउंटर बढ़ाया जाता है। यदि यह काउंटर लगातार तीन 20-सेकंड के अंतराल के बाद अपरिवर्तित रहता है, तो DotDumper मानता है कि एक स्थिर स्थिति का सामना करना पड़ा है। उस स्थिति में, सिस्टम का समय 30-12-2200 12:00 पर सेट किया जाता है ताकि सैंडबॉक्स को टाइम आउट करने के लिए मजबूर किया जा सके, जिसके बाद यह लॉगर के माध्यम से विश्लेषक को सूचित करता है और स्वयं को समाप्त कर देता है। सैंडबॉक्स टाइमआउट तब होता है जब वर्तमान तिथि से नव निर्धारित तिथि तक का बीता हुआ समय सामान्य 5 या 10 मिनट से अधिक हो जाता है। भले ही सैंडबॉक्स रनटाइम घंटों या दिनों पर सेट हो, यह पार हो जाता है।
विश्लेषण को छोटा करने का कारण समय और संसाधनों को बचाना है, क्योंकि 10 मिनट के टाइमआउट वाला सबमिशन चलने में केवल 2 मिनट ले सकता है। इस प्रकार, कोई स्थिरता हैंडलर के साथ समान समय अवधि में कई नमूने चला सकता है। स्थिरता हैंडलर के तर्क का एक अवलोकन नीचे दिखाया गया है।

DotDumper के लक्ष्य और विशेषताओं के स्पष्ट होने के साथ, ऐसा लग सकता है कि ILSpy, dnSpyEx, de4dot, या pe-sieve जैसे ज्ञात सार्वजनिक रूप से उपलब्ध उपकरणों के साथ ओवरलैप है। ध्यान दें कि यह घोषित करने का कोई इरादा नहीं है कि एक उपकरण दूसरे से बेहतर है, बल्कि उपकरण कैसे भिन्न हैं।
DotDumper का लक्ष्य DotNet लक्षित नमूनों से महत्वपूर्ण, प्रासंगिक और सामान्य फ़ंक्शन कॉल को लॉग और डंप करना है। ILSpy एक DotNet डिसअसेंबलर और डीकंपाइलर है, लेकिन फ़ाइल के निष्पादन की अनुमति नहीं देता है। dnSpyEx (और इसके पूर्ववर्ती dnSpy) डिसअसेंबलर और डीकंपाइलर घटक के रूप में ILSpy का उपयोग करते हैं, जबकि एक डीबगर जोड़ते हैं। यह किसी को मैन्युअल रूप से मेमोरी का निरीक्षण और हेरफेर करने की अनुमति देता है। de4dot का उपयोग केवल DotNet बाइनरी को डीऑबफसकेट करने के लिए किया जाता है, जिससे मानव आँखों के लिए कोड की पठनीयता में सुधार होता है। इस तुलना में अंतिम उपकरण, pe-sieve, चल रही प्रक्रियाओं से मैलवेयर का पता लगाने और डंप करने के लिए है, जो उपयोग की गई प्रोग्रामिंग भाषा की परवाह नहीं करता है। नीचे दी गई तालिका उपरोक्त उपकरणों का एक ग्राफिकल अवलोकन प्रदान करती है।

DotDumper निरंतर समीक्षा और विकास के अधीन है, जो सभी रुचि के दो मुख्य क्षेत्रों पर केंद्रित है: बग फिक्सिंग और नई सुविधाओं का जोड़। विकास के दौरान, कोड का परीक्षण किया गया था, लेकिन DotNet फ्रेमवर्क के फ़ंक्शन में हुक के इंजेक्शन के कारण जो परिवर्तन के अधीन हो सकते हैं, यह बहुत संभव है कि कोड में बग हों। जो कोई भी बग का सामना करता है, उसे GitHub रिपॉजिटरी पर एक मुद्दा खोलने का आग्रह किया जाता है, जिसे फिर देखा जाएगा। नई सुविधाओं का सुझाव भी GitHub रिपॉजिटरी के माध्यम से संभव है। उन लोगों के लिए जिनके पास GitHub खाता है, या जो सार्वजनिक रूप से बातचीत नहीं करना चाहते हैं, बेझिझक मुझे मेरे Twitter पर एक निजी संदेश भेजें।
कहने की जरूरत नहीं है, यदि आपने किसी विश्लेषण के दौरान DotDumper का उपयोग किया है, या रचनात्मक तरीके से इसका उपयोग किया है, तो सार्वजनिक या निजी रूप से संपर्क करने में संकोच न करें! एक घर-निर्मित उपकरण के उपयोग के बारे में सुनने जैसा कुछ नहीं है!
DotDumper के लिए और अधिक स्टोर में है, और एक बार उपलब्ध होने पर समुदाय को एक अपडेट भेजा जाएगा!