PowerShell स्क्रिप्ट को डी-ऑब्फ़स्केट कैसे करें
अंतिम अपडेट:
PowerShell स्क्रिप्ट को डी-ऑब्फ़स्केट करना यानी हमलावर ने स्क्रिप्ट असल में क्या करती है, यह छिपाने के लिए जो रूपांतरण लगाए थे, उन्हें परत-दर-परत उलटना — और यह सब स्क्रिप्ट को कभी चलाए बिना करना। Base64 की दीवार के रूप में आने वाली कोई संदिग्ध एक-पंक्ति वाली कमांड, या कैरेक्टर कोड और स्ट्रिंग जोड़ने की उलझन, उसके नीचे आमतौर पर बिल्कुल साधारण PowerShell कमांड होती है: एक डाउनलोड, एक डिकोड किया गया पेलोड, एक ऐसी कमांड जो सिर्फ़ मेमोरी में चलती है और कभी डिस्क को नहीं छूती। ऑब्फ़स्केशन चतुराई दिखाने के लिए नहीं है। यह सिग्नेचर स्कैनर से बचने के लिए है, कमांड लाइन को एक नज़र में अपठनीय बनाने के लिए है, और मानवीय विश्लेषक को दिलचस्प हिस्से तक पहुँचने से पहले ही हार मानने पर मजबूर करने के लिए है। यह लेख बताता है कि हर परत क्यों मौजूद है, उसे निष्क्रिय टेक्स्ट के रूप में कैसे हटाएँ, और आपको जो टुकड़े मिलते हैं उनका असल मतलब क्या है। पूरा वर्कफ़्लो PowerShell डी-ऑब्फ़स्केटर में चलाया जा सकता है, जो पूरी तरह आपके ब्राउज़र में परत-दर-परत डिकोड करता है — कुछ भी नहीं चलता, और कुछ भी आपकी मशीन से बाहर नहीं जाता।
हमलावर PowerShell को ऑब्फ़स्केट क्यों करते हैं — और एन्कोड किया हुआ रूप सबसे पहले क्यों हटाना चाहिए
PowerShell हर Windows मशीन में पहले से मौजूद है, यह डिस्क पर फ़ाइल लिखे बिना इंटरनेट से कोड डाउनलोड और चला सकता है, और इसे शुरू करने वाले के अधिकारों के साथ चलता है। यही संयोजन इसे MITRE ATT&CK फ़्रेमवर्क में सबसे ज़्यादा दुरुपयोग किए जाने वाले टूल में से एक बनाता है, जिसे तकनीक T1059.001 के रूप में सूचीबद्ध किया गया है, और यही वजह है कि हमलावर किसी दुर्भावनापूर्ण PowerShell कमांड के साथ सबसे पहले उसे छिपाता है। DownloadString के बाद Invoke-Expression जैसी सादे टेक्स्ट वाली कमांड को पकड़ना बहुत आसान है: कोई भी स्कैनर, कोई भी लॉग जाँच, प्रक्रिया की कमांड लाइन पर नज़र डालने वाला कोई भी विश्लेषक उसे पहचान लेगा। एन्कोड, कम्प्रेस और टुकड़ों में काटे जाने पर वही कमांड ऐसे अक्षरों की स्ट्रिंग बन जाती है जो किसी ज्ञात सिग्नेचर से मेल नहीं खाती और मानवीय पाठक के लिए कोई मतलब नहीं रखती।
यही वजह है कि एन्कोड किया हुआ रूप सबसे पहले हटाना चाहिए, बाकी सब से पहले। जब तक आप उसे डिकोड नहीं करते, आप नहीं जानते कि आप किसी इंस्टॉलर को देख रहे हैं, किसी मज़ाक को, या क्रेडेंशियल चुराने वाले टूल को — और उसके बाद का हर फ़ैसला सिर्फ़ अंदाज़ा है। अच्छी खबर यह है कि ऑब्फ़स्केशन लगभग हमेशा स्थिर अनवाइंडिंग से उलटा जा सकता है: पेलोड को चलाने वाली मशीन के लिए डिकोड करने योग्य होना ही चाहिए, इसलिए हर परत का एक नियतात्मक उल्टा रूपांतरण होता है। Base64 डिकोड हो जाता है, gzip खुल जाता है, कैरेक्टर कोड वापस अक्षर बन जाते हैं, जुड़ी हुई स्ट्रिंग जुड़ जाती हैं। यह काम यांत्रिक है, रहस्यमय नहीं, और किसी संदिग्ध स्क्रिप्ट की छँटाई में सबसे ज़्यादा मूल्य वाला एकल कदम है: एक ही डिकोड "अपठनीय ब्लॉब" को एक पठनीय कमांड में बदल देता है जिस पर वास्तव में तर्क किया जा सकता है।
-EncodedCommand और UTF-16LE: बेतुका दिखने वाला Base64 आमतौर पर पठनीय टेक्स्ट क्यों होता है
PowerShell ऑब्फ़स्केशन का सबसे आम रूप जो आपको मिलेगा, वह एक ही स्विच है: powershell.exe -EncodedCommand, जिसके बाद एक लंबी Base64 स्ट्रिंग आती है। यह यादृच्छिक अक्षरों जैसा दिखता है, लेकिन लगभग हमेशा यह सिर्फ़ साधारण स्क्रिप्ट टेक्स्ट होता है, जिसे ऐसे तरीके से एन्कोड किया गया है जो पहली बार देखने पर चौंकाता है। PowerShell का -EncodedCommand अपेक्षा करता है कि Base64 UTF-16LE में डिकोड हो — प्रति अक्षर दो बाइट, हर ASCII अक्षर के बाद एक शून्य बाइट — क्योंकि Windows पर .NET स्ट्रिंग की एन्कोडिंग यही है। इसलिए हानिरहित कमांड Write-Host "hello" का Base64 SQB3AHIAaQB0AGUALQBIAG8AcwB0ACA… से शुरू होता है, और बार-बार आने वाले "A" अक्षर उन सभी शून्य बाइट्स की निशानी हैं।
यह जानने से एन्कोड किए हुए ब्लॉब को पढ़ने का तरीका बदल जाता है। UTF-8 की बेतुकी स्ट्रिंग में डिकोड होने वाला Base64 शायद UTF-8 है ही नहीं: पहले UTF-16LE आज़माएँ, और वह "बेतुकापन" पठनीय PowerShell में बदल जाएगा। बिना -EncodedCommand स्विच वाले नंगे Base64 ब्लॉब पर भी यही लागू होता है — छपने योग्य टेक्स्ट में डिकोड होने वाले वैध Base64 के लंबे टोकन वही तरकीब हैं, बस बिना झंडे के। व्यावहारिक नियम सरल है: जब PowerShell कमांड लाइन में लंबा Base64 टोकन दिखे, तो मान लें कि वह स्क्रिप्ट है जब तक डिकोडिंग उल्टा साबित न कर दे, और उसे चैट विंडो या टर्मिनल में चिपकाकर यह देखने के बजाय कि क्या होता है, किसी ऐसे टूल में निष्क्रिय रूप से — टेक्स्ट के रूप में — डिकोड करें जो उसे कभी चलाता ही नहीं।
परतों की तह: कम्प्रेशन, कैरेक्टर कोड, जोड़ना, -f, बैकटिक
असली पेलोड शायद ही कभी एक परत पर रुकते हैं। -EncodedCommand डिकोड हो जाने के बाद, उसके नीचे का स्क्रिप्ट अक्सर खुद फिर से एन्कोड किया हुआ होता है: एक gzip-कम्प्रेस्ड ब्लॉब जो एक और Base64 स्ट्रिंग में लिपटा है, या [char]68+[char]105 जैसे कैरेक्टर कोड का क्रम जो एक-एक अंक करके कमांड बताता है, या एक स्ट्रिंग जिसे टुकड़ों में काटकर प्लस चिह्नों से वापस जोड़ा गया है, या एक फ़ॉर्मेट स्ट्रिंग जिसमें -f ऑपरेटर रनटाइम पर हिस्से भरता है, या कीवर्ड में छिड़के हुए बैकटिक जिससे Do`wnloadString अब DownloadString की भोली खोज से मेल नहीं खाता। हर परत अलग वजह से मौजूद है। कम्प्रेशन लंबी पेलोड को छोटी एक-पंक्ति वाली कमांड में सिकोड़ देता है और टेक्स्ट खोज को पूरी तरह हरा देता है। कैरेक्टर कोड और जोड़ना यह सुनिश्चित करके सिग्नेचर मिलान को हराते हैं कि संदिग्ध शब्द फ़ाइल में कभी शाब्दिक रूप में न आएँ। -f ऑपरेटर और बैकटिक स्क्रिप्ट को वाक्य-रचना की दृष्टि से वैध रखते हुए साधारण स्ट्रिंग खोज को हराते हैं।
उन सभी के विरुद्ध बचाव एक ही है: एक बार में एक परत खोलें, क्रम से, और जब कुछ और लागू न हो तो रुक जाएँ। Base64 डिकोड करें, फिर जाँचें कि परिणाम कम्प्रेस्ड है या नहीं और उसे खोलें, फिर कैरेक्टर कोड सुलझाएँ, टुकड़े जोड़ें, फ़ॉर्मेट आर्ग्युमेंट डालें, और बैकटिक हटाएँ — हर कदम सादा टेक्स्ट देता है जिस पर अगला कदम काम कर सकता है। एक टूल जो इसे एक दृश्यमान टाइमलाइन के रूप में करता है, हर परत के लिए पहले और बाद वाला एक कार्ड, वह उस टूल से ज़्यादा मूल्यवान है जो चुपचाप अंतिम उत्तर दे देता है, क्योंकि टाइमलाइन खुद ही सबूत है: यह दिखाती है कि कौन-सी परतें मौजूद थीं, और जब अनवाइंडिंग समय से पहले रुक जाती है — "आगे अनवाइंड नहीं किया जा सका" — तो वह एक खोज है, विफलता नहीं। यह बताती है कि पेलोड में कुछ गतिशील, एन्क्रिप्टेड, या रनटाइम पर बनने वाला है जिसे अकेला स्थिर विश्लेषण नहीं पहुँच सकता।
स्क्रिप्ट ब्लॉक लॉगिंग 4104: लंबे स्क्रिप्ट कैसे बाँटे और फिर से जोड़े जाते हैं
डी-ऑब्फ़स्केट किए हुए PowerShell का एक स्रोत है जिसे बिल्कुल डिकोडिंग की ज़रूरत नहीं: मशीन खुद। जब स्क्रिप्ट ब्लॉक लॉगिंग चालू होती है, Windows PowerShell द्वारा प्रोसेस किए गए हर स्क्रिप्ट ब्लॉक की सामग्री को Microsoft-Windows-PowerShell/Operational लॉग में इवेंट 4104 के रूप में दर्ज करता है — और कोड को वैसे ही दर्ज करता है जैसा PowerShell ने देखा, यानी इंजन द्वारा -EncodedCommand और ऑब्फ़स्केशन परतों को पहले ही फैला देने के बाद। Base64 के रूप में आई संदिग्ध एक-पंक्ति वाली कमांड 4104 इवेंट में उस पठनीय स्क्रिप्ट के रूप में दिखती है जिसे उसने असल में चलाया था। इसीलिए यह सुविधा PowerShell लॉगिंग की सबसे मूल्यवान सेटिंग है जिसे कोई रक्षक चालू कर सकता है, और इसीलिए यह डिफ़ॉल्ट रूप से बंद होती है: यह बहुत बोलती है, और लॉग में क्रेडेंशियल व अन्य संवेदनशील डेटा हो सकता है, इसलिए Microsoft डायग्नोस्टिक से आगे किसी भी उपयोग के लिए इसके साथ Protected Event Logging की सलाह देता है।
पेंच यह है कि Windows लंबे स्क्रिप्ट ब्लॉक को कई 4104 इवेंट में बाँट देता है। हर इवेंट में वही ScriptBlockId, एक MessageNumber और एक MessageTotal होता है — जैसे 5 में से भाग 2 — और पूरा स्क्रिप्ट तभी मौजूद होता है जब हिस्सों को उस ID से समूहबद्ध किया जाए, संदेश संख्या के क्रम में लगाया जाए, और जोड़ा जाए। अकेला इवेंट बीच शब्द में खत्म हो सकता है, और सिर्फ़ पहला टुकड़ा पढ़ने वाली खोज पेलोड के अंत में किए जाने वाले काम को चूक जाएगी। इसलिए फिर से जोड़ना एक यांत्रिक कदम है जिसमें सिर्फ़ एक चीज़ जाँचनी होती है: कोई हिस्सा गायब तो नहीं। अगर लॉग कहता है 3 में से 2 और भाग 2 कभी नहीं आया — क्योंकि लॉग घूम गया, या साफ़ कर दिया गया — तो फिर से जुड़ा टेक्स्ट अधूरा है, और उससे निकाला गया कोई भी निष्कर्ष अस्थायी है। वही समूहबद्ध करने का तर्क EVTX व्यूअर भी इस्तेमाल करता है जब वह निर्यात की गई .evtx फ़ाइलों में 4104 इवेंट को चिह्नित करता है; साथी लेख Windows मशीन के बिना .evtx फ़ाइलें पढ़ें भी देखें।
संकेतकों को पढ़ना: डाउनलोड क्रैडल, AMSI बायपास, एक्ज़ीक्यूशन-पॉलिसी बायपास
जब स्क्रिप्ट पठनीय हो जाए, तो अगला कदम उसे दुर्भावनापूर्ण घोषित करना नहीं है — बल्कि उसमें मौजूद संकेतकों को सत्यापित करने योग्य सुरागों के रूप में पढ़ना है। डाउनलोड क्रैडल — DownloadString, DownloadFile, Net.WebClient, Invoke-WebRequest, bitsadmin, certutil जो किसी URL से फ़ाइल खींचते हैं — बताता है कि स्क्रिप्ट कहीं से कोड लाती है, और अगला सवाल है कहाँ से, और क्या वह गंतव्य आपके नेटवर्क में अपेक्षित है। AMSI बायपास — amsiInitFailed, AmsiUtils, या कोड जो एंटीमैलवेयर स्कैन इंटरफ़ेस को पैच करता है — बताता है कि लेखक चाहता था कि स्क्रिप्ट बिना स्कैन हुए चले, जो एक मज़बूत संकेत है लेकिन फ़ैसला नहीं: पेनिट्रेशन टेस्टर और कुछ वैध टूल भी यही करते हैं। एक्ज़ीक्यूशन-पॉलिसी बायपास (-ExecutionPolicy Bypass, -ep bypass) बताता है कि लेखक नहीं चाहता था कि PowerShell की अपनी सुरक्षा स्क्रिप्ट को रोके, जो मैलवेयर में भी आम है और अहस्ताक्षरित स्क्रिप्ट चलाने वाली साधारण ऑटोमेशन में भी।
अनुशासन यह है कि हर संकेतक को सवाल मानें, जवाब नहीं। डाउनलोड क्रैडल के साथ छिपी हुई विंडो (-WindowStyle Hidden) और एन्कोड की हुई कमांड एक ऐसा पैटर्न है जिसे आगे बढ़ाना चाहिए; उनमें से कोई एक अकेला एक ऐसा पैटर्न है जिसे जाँचना चाहिए। सुराग को फ़ैसले में बदलता है संदर्भ: प्रक्रिया किसने शुरू की, उसका पैरेंट क्या था, जिससे संपर्क किया गया URL जाना-पहचाना है या नहीं, क्या वही स्क्रिप्ट दूसरी मशीनों पर भी दिखती है। एक डी-ऑब्फ़स्केटर जो संकेतकों को मिले हुए स्निपेट और "संदर्भ में सत्यापित करें" नोट के साथ सूचीबद्ध करता है, ईमानदार काम कर रहा है; जो पैटर्न की सूची से ही स्क्रिप्ट पर "दुर्भावनापूर्ण" या "साफ़" की मुहर लगा देता है, वह स्थिर विश्लेषण की जानकारी को बढ़ा-चढ़ाकर बता रहा है। और उल्टा भी मायने रखता है: जिस स्क्रिप्ट में कोई संकेतक नहीं मिला, वह सुरक्षित साबित नहीं हुई — हो सकता है वह बस ऐसी तकनीक इस्तेमाल कर रही हो जो सूची में नहीं है, या रनटाइम पर गतिशील रूप से अपनी पेलोड बना रही हो।
सुरक्षित वर्कफ़्लो: चैट में कभी चिपकाएँ नहीं, कभी चलाएँ नहीं, निष्क्रिय रूप से डिकोड करें
किसी संदिग्ध PowerShell स्क्रिप्ट को संभालने का सबसे महत्वपूर्ण नियम है कि आप उसे यह जानने के लिए कभी न चलाएँ कि वह क्या करती है, और AI से पूछने के लिए उसे कभी चैट विंडो में न चिपकाएँ। उसे चलाना यानी पेलोड को चलाना है — यही वह परिणाम है जिससे आप बचना चाहते हैं। चैट में चिपकाने से संभावित रूप से दुर्भावनापूर्ण स्क्रिप्ट किसी तीसरे पक्ष की सेवा को भेजी जाती है, वह आपकी नियंत्रण से बाहर की बातचीत के इतिहास में रह जाती है, और अक्सर वैसे भी मना कर दिया जाता है, क्योंकि AI सिस्टम नियमित रूप से उन स्क्रिप्ट को डी-ऑब्फ़स्केट करने से इनकार करते हैं जो दुर्भावनापूर्ण हो सकती हैं। सुरक्षित वर्कफ़्लो जानबूझकर उबाऊ है: ब्लॉब को ब्राउज़र-स्थानीय डी-ऑब्फ़स्केटर में, या सैंडबॉक्स विश्लेषण मशीन पर कॉपी करें, और डिकोड किए हुए आउटपुट को पढ़ने के लिए निष्क्रिय टेक्स्ट मानें, चलाने के लिए कोड कभी नहीं।
वहाँ से वर्कफ़्लो एक छोटी चेकलिस्ट है। पहला, परत-दर-परत डिकोड करें जब तक टेक्स्ट बदलना बंद न कर दे, और नोट करें कि अनवाइंडिंग कहाँ रुकी। दूसरा, संकेतक पढ़ें और लिखें कि अगर सच हो तो हर एक का क्या मतलब होगा, फिर हर एक को संदर्भ के विरुद्ध जाँचें — पैरेंट प्रक्रिया, गंतव्य URL, वह मशीन जहाँ से वह आया। तीसरा, परिणाम उन लोगों या सिस्टम को सौंपें जो अगले कदम के लिए बने हैं: आपका EDR कंसोल, सैंडबॉक्स में विस्फोट, आपकी इंसिडेंट-रिस्पॉन्स टीम। डी-ऑब्फ़स्केटर का काम पठनीय टेक्स्ट और ईमानदार संकेतकों पर समाप्त होता है; फ़ैसला सैंडबॉक्स और विश्लेषक का है, डिकोडिंग टूल का नहीं। अगर स्क्रिप्ट आपकी प्रबंधित मशीन से आई है, तो जाँचें कि क्या स्क्रिप्ट ब्लॉक लॉगिंग चालू थी — अगर थी, तो 4104 इवेंट इस बात की जमीनी सच्चाई हैं कि क्या चला, और लॉग घूमने से पहले उन्हें इकट्ठा करना सार्थक है।