Skip to content
KitploitKITPLOIT
उपकरणब्लॉग
जमा करें
उपकरणब्लॉग
जमा करें

हैकिंग, पेनटेस्ट और साइबर सुरक्षा उपकरण आपके सुरक्षा शस्त्रागार के लिए!

Kitploit हैकिंग, साइबर सुरक्षा और पेंटेस्टिंग टूल्स की एक निर्देशिका है। कमजोरियों को खोजने, सिस्टम का विश्लेषण करने, परीक्षण को स्वचालित करने और अपनी सुरक्षा को मजबूत करने के लिए नवीनतम प्रोजेक्ट अपडेट खोजें।

··फ़ीड·संपर्क·गोपनीयता·© 2026 Kitploit

टूल निर्देशिका

श्रेणियाँ

सभी श्रेणियाँ देखें
Loading categories
ShellGhost — एक मेमोरी-आधारित बचाव तकनीक जो प्रक्रिया की शुरुआत से अंत तक शेलकोड को अदृश्य बनाती है। | Kitploit
उपकरण/GitHubGitHub/lem0nsec/shellghost
एन्क्रिप्शन/डिक्रिप्शन उपकरणमेमोरी फोरेंसिकशोषणशेलकोडबाइनरी विश्लेषणरेड टीमिंगपेलोड डेवलपमेंट
GitHublem0nsec/shellghost

ShellGhost

एक मेमोरी-आधारित बचाव तकनीक जो प्रक्रिया की शुरुआत से अंत तक शेलकोड को अदृश्य बनाती है।

रिपॉजिटरी देखें
1.2k1402 साल पहलेKitploit द्वारा समीक्षित

सबसे लोकप्रिय

सभी देखें →

हमारे समुदाय द्वारा सबसे अधिक उपयोग किए जाने वाले उपकरण खोजें।

सभी उपकरण खोजें

हमारे उपकरणों का संग्रह ब्राउज़ करें

सभी उपकरण देखें →
साझा करें

ShellGhost

एक मेमोरी-आधारित चोरी तकनीक जो शेलकोड को प्रक्रिया आरंभ से अंत तक अदृश्य बनाती है।


प्रेरणा

मैं इस शेलकोड सेल्फ-इंजेक्शन POC को साझा करना चाहता था ताकि कुछ AV/EDR चोरी अवधारणाओं को प्रदर्शित किया जा सके जो रेड टीमिंग के लिए उपयोगी हो सकती हैं। कुछ हफ्ते पहले ही मैं एक कस्टम इन-मेमोरी चोरी तकनीक लेकर आया जिसे मैंने ShellGhost नाम दिया। यह तकनीक एक ऐसे कोड की आवश्यकता से उत्पन्न हुई है जो प्रक्रिया आरंभ से अंत तक 'अदृश्य' शेलकोड निष्पादित करता है।


थ्रेड निष्पादन प्रवाह को संभालना

ShellGhost वेक्टर्ड अपवाद हैंडलिंग के साथ सॉफ़्टवेयर ब्रेकपॉइंट्स के संयोजन पर निर्भर करता है ताकि चक्रीय रूप से थ्रेड निष्पादन को रोका जा सके, निष्पादित ब्रेकपॉइंट को RC4-एन्क्रिप्टेड शेलकोड निर्देश से बदला जा सके, निर्देश को डिक्रिप्ट किया जा सके और मेमोरी सुरक्षा को RX में पुनर्स्थापित करने के बाद निष्पादन फिर से शुरू किया जा सके। जब बाद में EXCEPTION_BREAKPOINT उठाया जाता है, तो अपवाद हैंडलर पिछले शेलकोड निर्देश को एक नए ब्रेकपॉइंट से बदल देता है ताकि आवंटन कभी भी पूरे शेलकोड को अनएन्क्रिप्टेड अवस्था में प्रकट न करे। यह एक निजी मेमोरी पेज के अंदर होता है जो प्रारंभ में READ/WRITE के रूप में चिह्नित होता है। RW PRV आवंटन होने को PE-Sieve और Moneta जैसे मेमोरी स्कैनर द्वारा 'इंडिकेटर ऑफ कॉम्प्रोमाइज' नहीं माना जाएगा। जब आवंटन RX हो जाता है और पेज स्कैन किया जाता है, तो ब्रेकपॉइंट्स के अलावा कुछ नहीं मिलेगा। ऐसा तब होता है जब शेलकोड वास्तव में निष्पादन के अधीन होता है। निम्नलिखित चित्र दिखाता है कि एक रिवर्स शेल चल रहा है, लेकिन Moneta द्वारा कोई IOC नहीं पाया जाता है (बाइनरी के अहस्ताक्षरित होने के अलावा)।

Pe-Sieve के साथ प्रक्रिया को स्कैन करने का प्रयास करने पर और भी बेहतर परिणाम मिलता है:


शेलकोड मैपिंग

शेलकोड मैपिंग ShellGhost की मुख्य कार्यक्षमता है। यह रणनीति थ्रेड को निर्देशों को रुक-रुक कर निष्पादित करने में सक्षम बनाती है जबकि कभी भी पूरे शेलकोड को मेमोरी में उजागर नहीं करती। यह संभव है क्योंकि थ्रेड द्वारा निष्पादित प्रत्येक एकल शेलकोड निर्देश की स्थिति आवंटित मेमोरी पेज के अंदर एक निश्चित ब्रेकपॉइंट की स्थिति से मेल खाती है। ShellGhost इस स्थिति को थ्रेड RIP से आवंटित मेमोरी पेज के आधार पते तक सापेक्ष वर्चुअल एड्रेस (RVA) की गणना करके और इसे एन्क्रिप्टेड शेलकोड/एन्क्रिप्टेड निर्देशों के आधार पते में जोड़कर हल करता है। प्रतिस्थापित किए जाने वाले ब्रेकपॉइंट्स की संख्या हमेशा समान नहीं होती, बल्कि यह प्रत्येक निर्देश को सही ढंग से उत्पन्न और व्याख्या करने के लिए आवश्यक ओपकोड्स की संख्या (QUOTA) पर निर्भर करती है। उदाहरण के लिए, निर्देश 'POP RBP' '5D' के बराबर है, जिसका अर्थ है कि केवल एक ब्रेकपॉइंट प्रतिस्थापित किया जाएगा। इसके विपरीत, निर्देश 'JMP RAX' के लिए ओपकोड्स 'FF E0' की आवश्यकता होती है, इसलिए दो ब्रेकपॉइंट प्रतिस्थापित किए जाएंगे। इस कारण से मैंने निम्नलिखित C डेटा संरचना बनाई।

root@kitploit:~
typedef struct CRYPT_BYTES_QUOTA {

	DWORD RVA;		// एन्क्रिप्टेड निर्देश का ऑफसेट 
	DWORD quota;	// निर्देश उत्पन्न करने वाले ओपकोड्स की संख्या

} CRYPT_BYTES_QUOTA, * PCRYPT_BYTES_QUOTA;

ब्रेकपॉइंट्स को तुरंत उनके निर्देश समकक्षों से प्रतिस्थापित नहीं किया जाता है। ऐसा इसलिए है क्योंकि निर्देशों को निष्पादित करने से पहले एक डिक्रिप्शन रूटीन से गुज़रना होता है। यह वह जगह है जहाँ DWORD quota काम आता है। ShellGhost अब लोकप्रिय 'SystemFunction032' पर RC4 डिक्रिप्शन करने के लिए निर्भर करता है। XOR के विपरीत, RC4 एक एकल-बाइट एन्क्रिप्शन योजना नहीं है। इसका मतलब है कि शेलकोड को एक साथ एन्क्रिप्ट और डिक्रिप्ट नहीं किया जा सकता है। यह भी एक कारण है कि प्रत्येक निर्देश को अलग से संसाधित किया जाता है। ब्रेकपॉइंट्स के प्रतिस्थापित होने के बाद, SystemFunction032 के लिए आवश्यक बफर लंबाई 'निर्देश कोटा' के बराबर होगी, जो फिर से विशिष्ट निर्देश से बने ओपकोड्स की संख्या को दर्शाती है। उदाहरण के लिए, निम्नलिखित स्निपेट पर विचार करें।

root@kitploit:~

CRYPT_BYTES_QUOTA instruction[200];
instruction[5].quota = 2

USTRING buf = { 0 }; 	// डिक्रिप्ट किए जाने वाले बफर और उसकी लंबाई शामिल होगी
USTRING key = { 0 }; 	// RC4 कुंजी और लंबाई शामिल होगी

buf.Length = 2 		// बफर लंबाई, या डिक्रिप्ट किए जाने वाले निर्देश की लंबाई

हम जानते हैं कि शेलकोड निर्देश संख्या 5 में 2 ओपकोड हैं, इसलिए SystemFunction032 को बफर लंबाई 2 दी जाएगी। यह महत्वपूर्ण है क्योंकि SystemFunction032 के एकल कॉल से पूरे शेलकोड को डिक्रिप्ट करने का प्रयास इसे पूरी तरह से दूषित कर देगा।

शेलकोड मैपिंग कैसे की जाती है?

संकलन से पहले शेलकोड को ShellGhost_mapping.py से मैप करने की आवश्यकता होती है। स्क्रिप्ट प्रत्येक एकल निर्देश को निकालती है और इसे एक छोटे और स्वतंत्र शेलकोड के रूप में मानती है। निर्देशों को एक-एक करके एन्क्रिप्ट किया जाता है और C प्रारूप में एक साथ unsigned char के रूप में मुद्रित किया जाता है। परिणाम C कोड के अंदर हार्डकोड किया जा सकता है। नीचे calc.exe के लिए एन्क्रिप्टेड MSF शेलकोड निर्देशों का एक उदाहरण दिया गया है।

इस शेलकोड में 98 निर्देश हैं, इसलिए 98 CRYPT_BYTES_QUOTA स्ट्रक्ट्स घोषित किए जाते हैं। जब कोड निष्पादित होता है, तो इन स्ट्रक्ट्स को उचित निर्देश RVAs और QUOTAs से भरना होता है। पैरामीटर '-1' मैपिंग स्क्रिप्ट को कोड का वह टुकड़ा प्रिंट करने का निर्देश देता है जो ऐसा करता है।

विनएपीआई पैरामीटर्स को समायोजित करना

Metasploit x64 शेलकोड में आमतौर पर निर्देशों के बीच विनएपीआई स्ट्रिंग पैरामीटर संग्रहीत होते हैं। यानी, एक MSF x64 शेलकोड जो Winexec को कॉल करता है, वह स्टैक पर पहला पैरामीटर स्ट्रिंग रखने के लिए अंत में नलबाइट वाले बाइट्स की एक श्रृंखला को पुश नहीं करता है। बल्कि, RCX रजिस्टर (पहला पैरामीटर) स्वयं शेलकोड के अंदर एक पॉइंटर होता है, जैसा कि निम्नलिखित चित्र में दिखाया गया है।

इसका मतलब है कि जिन ब्रेकपॉइंट्स की स्थिति स्ट्रिंग से संबंधित है, वे कभी हल नहीं होंगे, क्योंकि RIP कभी भी उस स्थिति को स्पर्श नहीं करेगा। वास्तव में, यह कोड वास्तविक शेलकोड निर्देशों को हल करता है जिनसे RIP गुज़रता है, न कि उन पैरामीटर्स को जो कभी निर्देशों की तरह निष्पादित नहीं होंगे। इसे ठीक करने के लिए, मैंने देखा कि MSF शेलकोड हमेशा RAX रजिस्टर के अंदर कॉल किए जाने वाले विनएपीआई का एक पॉइंटर संग्रहीत करता है, फिर स्वयं रजिस्टर पर जंप करता है। इसलिए जब ShellGhost VEH यह पता लगाता है कि हल किया गया ब्रेकपॉइंट 'JMP RAX' है और RCX रजिस्टर में शेलकोड के अंदर एक स्थिति का पॉइंटर है, तो यह RCX द्वारा इंगित चीज़ को भी हल करने का प्रयास करता है। बाद में, आवंटित मेमोरी में निष्पादन वापस नहीं किया जाता है। बल्कि, RAX (विनएपीआई पता) को RIP में कॉपी किया जाता है और थ्रेड निष्पादन विनएपीआई से फिर से शुरू किया जाता है, इस प्रकार 'JMP RAX' को ओवरराइड करके आवंटित मेमोरी को RW रखा जाता है। यह WaitForSingleObject को कॉल करने वाले रिवर्स शेल के लिए आवश्यक है, जो 'JMP RAX' के बाद थ्रेड को सोने का कारण बनेगा, जबकि मेमोरी को तब तक RX छोड़ देगा जब तक शेल जीवित रहे। निम्नलिखित कोड स्निपेट में दो शर्तें हैं जो ShellGhost के लिए RCX रजिस्टर को समायोजित करने के लिए पूरी होनी चाहिए जब इसमें विनएपीआई पैरामीटर स्ट्रिंग हो और MSF शेलकोड को फ़ंक्शन कॉल (यहाँ उदाहरण में WinExec) सही ढंग से जारी करने की अनुमति दे।

root@kitploit:~
<snip>
	
if (*(PWORD)exceptionData->ContextRecord->Rip == 0xe0ff) // यदि RIP 'JMP RAX' है

<snip>

if ((contextRecord->Rcx >= (DWORD_PTR)allocation_base) && (contextRecord->Rcx <= ((DWORD_PTR)allocation_base + sizeof(sh)))) // यदि RCX आवंटन के अंदर है

<snip>

RDX, R8 और R9 (दूसरे, तीसरे और चौथे पैरामीटर) अभी तक कवर नहीं किए गए हैं।

अन्य तकनीकों के साथ अंतर और समानताएँ

ShellcodeFluctuation एक बहुत समान इन-मेमोरी चोरी अवधारणा है। इसी प्रकार, यहाँ आवंटित मेमोरी RW से RX तक 'उतार-चढ़ाव' करती है। इसके विपरीत, ShellGhost निम्नलिखित सुधार प्रस्तुत करता है:

  • एकल-बाइट XOR के बजाय RC4 एन्क्रिप्शन प्लस 'शेलकोड मैपिंग'
  • फ़ंक्शन को हुक करने की आवश्यकता नहीं
  • Metasploit शेलकोड के लिए समर्थन

हालाँकि, ShellGhost एक आदर्श तकनीक से बहुत दूर है। यह अभी भी उन सभी तकनीकों की सबसे बड़ी कमी से ग्रस्त है, अर्थात निष्पादन के दौरान किसी बिंदु पर निजी निष्पादन योग्य मेमोरी की आवश्यकता। Foliage जैसी अधिक उन्नत तकनीकों ने पहले ही इसके आसपास एक रास्ता खोज लिया है। इसके अलावा, सॉफ़्टवेयर ब्रेकपॉइंट्स से भरा मेमोरी आवंटन YARA नियम द्वारा पता लगाया जा सकता है। निम्नलिखित चित्र Moneta द्वारा RX PRV आवंटन के लिए सही ढंग से IOC का पता लगाने को दिखाता है।

जब EDR समाधान से बचने की बात आती है, तो मेमोरी स्कैनिंग एक बड़ी तस्वीर का सिर्फ एक हिस्सा है। IOCs की पूर्ण अनुपस्थिति का यह अर्थ नहीं है कि इस तकनीक का उपयोग करने वाला बाइनरी किसी दिए गए EDR के खिलाफ प्रभावी साबित होगा। जहाँ तक मैं बता सकता हूँ, मैंने उन स्थितियों का अनुभव किया जहाँ समाधान आपको अपने तरीके से बाइनरी लॉन्च करने की अनुमति भी नहीं देता। दूसरा पहलू यह है कि IOCs हमेशा सटीक संकेतक नहीं होते हैं, और उनमें से कुछ झूठे सकारात्मक साबित हो सकते हैं। ऐसा कहने के साथ, यह सिर्फ एक कच्ची तकनीक और एक प्रेरणा है जिसकी मैं आशा करता हूँ कि पाठक सराहना करेंगे। रेड टीमर जानता है कि जिस तरह EDR के घटक होते हैं, उसी तरह इन-मेमोरी चोरी भी इंजन का केवल एक घटक है।

नोट्स

संकलन के लिए इन्क्रीमेंटल लिंकिंग को अक्षम करना आवश्यक है। इस VS प्रोजेक्ट में सभी कंपाइलर/लिंकर विकल्प पहले से सेट हैं।

टूल डाउनलोड करें