
cobalt strike की External C2 specification के साथ उपयोग के लिए Python api
Python फ्रेमवर्क जो फ्रेमवर्क्स के बीच डेटा स्थानांतरित करने के लिए इंटरफेस बनाने और उपयोग करने हेतु है, जिसका विशेष ध्यान Command and Control फ्रेमवर्क्स के विस्तार के रूप में कार्य करने पर है।
वर्तमान में, यह केवल इस स्पेक दस्तावेज़ में वर्णित Cobalt Strike की External C2 विनिर्देशन के कार्यान्वयन के रूप में अभिप्रेत है, लेकिन परियोजना के परिपक्व होने के साथ इसमें बदलाव संभव है।
बहुत बड़ा श्रेय xychix को जाता है। उनके मूल्यवान योगदान के बिना यह परियोजना बिल्कुल भी संभव नहीं हो पाती। मूल रूप से यह परियोजना Outflank की External C2 परियोजना का पुनर्निर्माण और विस्तार है।
इस परियोजना में निम्नलिखित मुख्य भाग शामिल हैं:
बिल्डर एक कॉन्फ़िग फ़ाइल पढ़ता है, और skeletons के भीतर markers को प्रतिस्थापित करके एक बिल्ड उत्पन्न करने के लिए कॉन्फ़िगर किए गए विकल्पों का उपयोग करता है।
बिल्डर का उपयोग build_files.py के साथ किया जा सकता है। एक नमूना बिल्डर कॉन्फ़िगरेशन sample_builder_config.config.sample के रूप में प्रदान किया गया है।
skeletons कोड के विभिन्न "स्केलेटन" होते हैं जिन्हें builder पूर्ण रूप से उपयोग योग्य बिल्ड उत्पन्न करने के लिए गतिशील रूप से भरता है। skeletons में markers होते हैं जिन्हें builder द्वारा उपयोग योग्य मानों से प्रतिस्थापित किया जाएगा। स्केलेटन के तीन अलग-अलग 'प्रकार' हैं:
एक मार्कर को skeleton में किसी भी फ़ाइल के अंदर रखा जा सकता है, जिसे बिल्डर कॉन्फ़िग में निर्दिष्ट मान से प्रतिस्थापित किया जाएगा। सर्वोत्तम अभ्यास में, मार्कर का उपयोग कभी भी सीधे वेरिएबल लिखने के लिए नहीं किया जाना चाहिए, और केवल मान सेट करने के लिए ही किया जाना चाहिए। यदि किसी मार्कर के मान का पुनः उपयोग करना हो, तो मान को एक वेरिएबल में संग्रहीत करके उसी तरह संदर्भित करना चाहिए, न कि उसी मार्कर का पुनः उपयोग करना चाहिए।
मार्कर प्रारूप है: ```[var:::identifier_for_the_marker]```
स्ट्रिंग्स को स्केलेटन में सीधे सिंगल कोट्स में लपेटकर लिखा जाएगा, और संख्याओं को यथावत लिखा जाएगा।
यदि कॉन्फ़िग में कोई स्ट्रिंग डबल कोट्स में लपेटी गई है, तो स्ट्रिंग को फ़ाइल में सीधे डबल कोट्स में लपेटकर लिखा जाएगा, और लपेटे गए सिंगल कोट्स हटा दिए जाएंगे।
यह संबंध इस प्रकार प्रदर्शित किया जा सकता है:
#################
# Skeleton Code #
#################
# Skeleton contains the following line of code:
foo = ```[var:::bar]```
##############
# End Result #
##############
# Stored in config as:
# foo = bar
# Written as:
foo = 'bar'
# Stored in config as:
# foo = "bar"
# Written as:
foo = "bar"
# Stored in config as:
# foo = 2
# Written as:
foo = 2
# Stored in config as:
# foo = "2"
# Written as:
foo = "2"
फ्रेमवर्क्स मूल अनुप्रयोग होते हैं जो यह निर्धारित करते हैं कि transport और encoder द्वारा कौन सा डेटा उपयोग किया जा रहा है, और उस डेटा का उपयोग कैसे किया जाता है। कोई विशिष्ट framework वास्तव में क्या करता है, यह अधिक मायने नहीं रखता, जब तक कि encoder और transport को आयात और उपयोग करने की तर्क मौजूद है। किसी फ्रेमवर्क के अधिकांश आवश्यक भाग (मुख्य रूप से client तर्क) एक skeleton के रूप में संग्रहीत किए जाएंगे, जिसमें उसके सर्वर भाग के साथ इंटरैक्ट करने का इंटरफ़ेस एक आधार framework ऑब्जेक्ट के रूप में संग्रहीत किया जाएगा।
सामान्यतः, एक फ्रेमवर्क में एक server और client होता है, और उनके बीच डेटा रिले करने के लिए encoders और transports का उपयोग करता है।
framework बनाते समय विचार करने के लिए कुछ मूलभूत बातें हैं:
framework यह सुनिश्चित करने के लिए जिम्मेदार है कि encoder को उपयोग के लिए transport को उपलब्ध कराया जाए।framework क्लाइंट-सर्वर संबंध का उपयोग करता है, तो उन्हें उसी रूप में उचित रूप से व्यवस्थित किया जाना चाहिए।client के साथ सीधे इंटरैक्ट नहीं करेगा, इसलिए यदि आप client पर चीज़ों को पुनः कॉन्फ़िगर करने योग्य बनाना चाहते हैं, तो उसे बिना किसी सीधे इंटरैक्शन के रनटाइम के दौरान ऐसा करने में सक्षम होना चाहिए।server skeleton बनाने की आवश्यकता बहुत कम होनी चाहिए क्योंकि अंतिम-उपयोगकर्ता सीधे किसी फ्रेमवर्क के server के साथ इंटरैक्ट करने जा रहा है। इसके बजाय, कॉन्फ़िगरेशन से विकल्प पढ़ने और अंतिम-उपयोगकर्ता को रनटाइम के दौरान विकल्पों (जैसे ब्लॉक टाइमर या वर्बोसिटी) को संशोधित करने की क्षमता देने, दोनों का विकल्प चुनें।framework skeleton को बिल्डर द्वारा संसाधित किया जाएगा, जो उसमें मौजूद हर फ़ाइल को देखेगा, इसलिए यदि किसी विशेष तर्क को बिल्ड समय पर कॉन्फ़िगर करने योग्य बनाना हो, तो यह आसानी से किया जा सकता है।framework को एक सामान्य द्वारा इंटरफ़ेस किए जाने में सक्षम होना चाहिए।सर्वर वह अनुप्रयोग है जो client और c2 server के बीच संचार की मध्यस्थता करता है। सर्वर तर्क मुख्य रूप से स्थिर होता है। cobalt_strike फ्रेमवर्क के लिए सर्वर का तर्क, जिसे स्पेक के भीतर third-party Client Controller कहा जाता है, नीचे दिखाया गया है:
encoder मॉड्यूल के साथ एन्कोड करेंtransport मॉड्यूल के साथ ट्रांसपोर्ट करेंtransport के माध्यम से क्लाइंट से मेटाडेटा प्रतिक्रिया की प्रतीक्षा करेंencoder मॉड्यूल के साथ डिकोड करेंtransport के माध्यम से क्लाइंट तक रिले करेंtransport के माध्यम से क्लाइंट से प्रतिक्रिया प्राप्त करेंencoder मॉड्यूल के माध्यम से डिकोड करेंएक server को कई क्लाइंट्स को संभालने की क्षमता (अभी लागू नहीं) का समर्थन करना चाहिए, और एक framework_manager द्वारा इंटरफ़ेस किए जाने में सक्षम होना चाहिए।
क्लाइंट अनिवार्य रूप से वह पेलोड है जो एंडपॉइंट पर चलता है। cobalt_strike फ्रेमवर्क के लिए क्लाइंट का तर्क मुख्य रूप से स्थिर है, और नीचे दिखाया गया है:
transport का उपयोग करने हेतु आवश्यक कोई भी तैयारी चलाएंtransport के माध्यम से C2 सर्वर तक रिले करेंtransport की निगरानी करेंtransport के माध्यम से रिले करेंक्लाइंट अपने और अपने संबंधित server के बीच डेटा रिले करने के लिए निर्दिष्ट encoder और transport का उपयोग करता है।
एन्कोडर्स डेटा प्राप्त करते हैं, फिर उस डेटा को संशोधित करते हैं ताकि या तो इसे ट्रांसपोर्ट के माध्यम से भेजे जाने के लिए तैयार किया जा सके, या ट्रांसपोर्ट के माध्यम से प्राप्त डेटा को उसके कच्चे रूप में डिकोड किया जा सके, ताकि जो भी framework घटक इसका उपयोग कर रहा है उसके द्वारा व्याख्या की जा सके।
एन्कोडर्स को ट्रांसपोर्ट द्वारा सीधे इंटरफ़ेस किए जाने की अपेक्षा करनी चाहिए, और डेटा को फ्रेमवर्क और घटक-एग्नोस्टिक तरीके से संभालना चाहिए।
ट्रांसपोर्ट्स एक संचार चैनल के माध्यम से डेटा भेजने और प्राप्त करने की भूमिका निभाते हैं, और एन्कोडर के साथ इंटरफ़ेस करके यह सुनिश्चित करते हैं कि डेटा आवश्यक किसी भी प्रारूप में रूपांतरित हो। ट्रांसपोर्ट्स को किसी फ्रेमवर्क घटक से, या संचार चैनल के माध्यम से डेटा प्राप्त करने की अपेक्षा करनी चाहिए, और संचार चैनल के माध्यम से डेटा रिले करने की क्षमता रखनी चाहिए। ट्रांसपोर्ट्स की जिम्मेदारी है कि वे आवश्यकतानुसार डेटा को एन्कोड या डिकोड करने हेतु encoder को कॉल करें।
ट्रांसपोर्ट्स को framework घटक द्वारा सीधे इंटरफ़ेस किए जाने की अपेक्षा करनी चाहिए, और डेटा को फ्रेमवर्क और घटक-एग्नोस्टिक तरीके से संभालना चाहिए।
पहले, निर्धारित करें कि आप कौन सा ट्रांसपोर्ट और एन्कोडिंग मॉड्यूल उपयोग करना चाहते हैं। निम्नलिखित उदाहरण के लिए हम transport_imgur और encoder_lsbjpg का उपयोग करेंगे।
इसके बाद, अपनी आवश्यकताओं के अनुरूप एक builder_config.config बनाएं। ऐसा करने के तरीके के निर्देश के लिए प्रदान किए गए नमूना कॉन्फ़िग और टेम्पलेट देखें।
build_files.py के साथ एक बिल्ड उत्पन्न करें। उदाहरण के रूप में, कोई व्यक्ति Cobalt Strike के लिए encoder_lsbjpg और transport_imgur का उपयोग करके, विस्तृत रूप से, निम्नलिखित कमांड के साथ builds निर्देशिका में एक बिल्ड उत्पन्न करेगा:
python build_files.py -b builds -f cobalt_strike -c sample_builder_config.config.sample -e encoder_lsbjpg -t transport_imgur -v
सर्वर चलाने वाली मशीन पर, निष्पादित करें:
python server.py
अधिक विस्तृत आउटपुट के लिए, आप चला सकते हैं:
python server.py -v
यदि आप अधिक विस्तृत आउटपुट और डिबगिंग के लिए उपयोगी अतिरिक्त आउटपुट चाहते हैं, तो आप चला सकते हैं:
python server.py -d
इसके बाद, लक्षित एंडपॉइंट पर क्लाइंट निष्पादित करें।
यदि सब कुछ ठीक रहा, तो Cobalt Strike कंसोल में एक नया बीकन पंजीकृत होगा जिसके साथ आप इंटरैक्ट कर सकते हैं।
आपने यह क्यों लिखा?: Cobalt Strike स्पेक के बहुत अधिक जारी किए गए कार्यान्वयन नहीं थे, और जो जारी किए गए हैं, उनमें से या तो वे ऐसी भाषा में नहीं हैं जिससे मैं परिचित हूं, या उनमें वह मॉड्यूलरिटी और एब्स्ट्रैक्शन नहीं है जिसे मैं खोज रहा था।
Python 2 क्यों?: मैं आलसी हूं और इसमें नए ट्रांसपोर्ट और एन्कोडिंग चैनल लागू करना आसान है।
आपका कोड बेकार है: यह कोई प्रश्न नहीं है।
क्या मैं नए ट्रांसपोर्ट और/या एन्कोडर मॉड्यूल जमा कर सकता हूं?: हाँ, कृपया! एक पुल रिक्वेस्ट जमा करें और मुझे समीक्षा करने में खुशी होगी।
मैं क्लाइंट को एक निष्पादन योग्य (executable) में कैसे संकलित करूं जिसे मैं वितरित कर सकता हूं?:
मैंने इसे Kali में सफलतापूर्वक परीक्षण किया है। अपने वातावरण को फिर से बनाने के लिए, बस सुनिश्चित करें कि आपके पास veil-evasion स्थापित है और आपने इसकी सेटअप प्रक्रिया पूरी की है। इसने एक wine वातावरण स्थापित किया होना चाहिए जिसमें python स्थापित हो और जिसमें आपके लिए आवश्यक सभी निर्भरताएं हों। आपको इस वातावरण में pefile मॉड्यूल भी स्थापित करना पड़ सकता है।
फिर, आप उस क्लाइंट की निर्देशिका में जा सकते हैं जिसके लिए आप एक निष्पादन योग्य उत्पन्न करना चाहते हैं और चला सकते हैं:
chmod +x compile_dll.sh
./compile_dll.sh
wine "C:\\Python27\\python.exe" /usr/share/veil/pyinstaller/pyinstaller.py -F -r c2file.dll -w --key "ayyyyyyylmao" client.py
key के मान को अपनी पसंद के किसी भी मान से बदलें। आपको dist/ निर्देशिका में क्लाइंट निष्पादन योग्य दिखाई देना चाहिए। यदि आप एक ऐसा निष्पादन योग्य उत्पन्न करना चाहते हैं जो एक कंसोल प्रदान करता है जिसका उपयोग आप डिबगिंग के लिए कर सकते हैं, तो निष्पादन योग्य को wine "C:\\Python27\\python.exe" /usr/share/veil/pyinstaller/pyinstaller.py -F -r c2file.dll -c client.py के साथ संकलित करें।
serverframework_manager