
واجهة برمجة تطبيقات بايثون للاستخدام مع مواصفات C2 الخارجية لـ Cobalt Strike
إطار عمل بلغة بايثون لبناء واستخدام واجهات لنقل البيانات بين الأطر، مع تركيز خاص على العمل كامتداد لأطر القيادة والتحكم.
حالياً، هذا مخصص فقط كتنفيذ لمواصفات External C2 الخاصة بـ Cobalt Strike كما هو موضح في وثيقة المواصفات هذه، لكنه عرضة للتغيير مع نضوج المشروع.
شكر كبير لـ xychix. لم يكن هذا المشروع ممكناً على الإطلاق بدون مساهماتهم القيمة. أساساً، هذا المشروع هو إعادة بناء وتوسيع مشروع External C2 الخاص بـ Outflank
يتكون هذا المشروع من الأجزاء الرئيسية التالية:
يقرأ Builder ملف تهيئة، ويستخدم الخيارات المهيأة لإنشاء بناء عن طريق استبدال علامات داخل الهياكل العظمية.
يمكن استخدام Builder مع build_files.py. يتم توفير نموذج لتهيئة Builder كـ sample_builder_config.config.sample.
Skeletons هي "الهياكل العظمية" المختلفة للكود التي سيقوم Builder بملئها ديناميكياً لإنشاء بناء قابل للاستخدام بالكامل. تحتوي Skeletons على علامات سيتم استبدالها بقيم قابلة للاستخدام بواسطة Builder. هناك ثلاثة 'أنواع' مختلفة من الهياكل العظمية:
يمكن وضع علامة داخل أي ملف في skeleton، والتي سيتم استبدالها بقيمة محددة في تهيئة builder. في أفضل الممارسات، يجب ألا تُستخدم العلامات مطلقاً لكتابة المتغيرات مباشرة، بل يجب استخدامها فقط لتعيين القيم. إذا كان يجب إعادة استخدام قيمة علامة ما، فيفضل تخزين القيمة في متغير والإشارة إليها بهذه الطريقة، بدلاً من إعادة استخدام نفس العلامة.
تنسيق العلامة هو: ```[var:::identifier_for_the_marker]```
سيتم كتابة السلاسل النصية في الهيكل العظمي مباشرةً محاطة بعلامات اقتباس مفردة، وسيتم كتابة الأرقام كما هي.
في حالة أن السلسلة النصية في التهيئة محاطة بعلامات اقتباس مزدوجة، ستتم كتابة السلسلة مباشرةً في الملف محاطة بعلامات اقتباس مزدوجة بدلاً من ذلك، وسيتم إزالة علامات الاقتباس المفردة المحيطة.
يمكن توضيح هذه العلاقة على النحو التالي:
#################
# كود الهيكل #
#################
# يحتوي الهيكل على السطر التالي من الكود:
foo = ```[var:::bar]```
##############
# النتيجة النهائية #
##############
# مخزنة في التهيئة كـ:
# foo = bar
# مكتوبة كـ:
foo = 'bar'
# مخزنة في التهيئة كـ:
# foo = "bar"
# مكتوبة كـ:
foo = "bar"
# مخزنة في التهيئة كـ:
# foo = 2
# مكتوبة كـ:
foo = 2
# مخزنة في التهيئة كـ:
# foo = "2"
# مكتوبة كـ:
foo = "2"
Frameworks هي التطبيق الأساسي الذي يحدد البيانات التي يستخدمها Transport و Encoder، وكيفية استخدام تلك البيانات. ما يفعله Framework معين لا يهم كثيراً، طالما أن المنطق موجود لاستيراد واستخدام Encoder و Transport. سيكون معظم الأجزاء الأساسية من الـ Framework (بشكل أساسي منطق Client) مخزناً كـ skeleton، مع وجود واجهة للتفاعل مع جزء الـ Server منه مخزنة ككائن framework أساسي.
بشكل عام، يحتوي الـ Framework على Server و Client، ويستخدم Encoders و Transports لنقل البيانات بينهما.
هناك بعض الأساسيات التي يجب مراعاتها عند بناء Framework:
Framework مسؤول عن ضمان أن Encoder متاح لـ Transport لاستخدامه.Framework يستخدم علاقة عميل-خادم، فيجب تنظيمهما بشكل مناسب.Client الخاص بـ Framework، لذا إذا كنت تريد أن تكون الأشياء قابلة لإعادة التهيئة على Client، فيجب أن يكون قادراً على فعل ذلك أثناء وقت التشغيل دون أي تفاعل مباشر.skeleton لـ Server لأن المستخدم النهائي سيتفاعل مباشرةً مع Server الخاص بـ Framework. بدلاً من ذلك، اختر قراءة الخيارات من ملف تهيئة، وإعطاء المستخدم النهائي القدرة على تعديل الخيارات (مثل مؤقت الكتلة أو الإسهاب) أثناء وقت التشغيل.skeleton الخاص بـ Framework بواسطة Builder، بالتكرار عبر كل ملف فيه، لذا إذا كانت هناك حاجة لتهيئة وسيط معين في وقت البناء، يمكن القيام بذلك بسهولة.Server الخاص بـ Framework قابلاً للتفاعل من خلال framework_manager شائع.الـ Server هو التطبيق الذي يدير الاتصال بين Client و C2 Server. منطق الـ Server ثابت بشكل أساسي. منطق الـ Server لـ Framework cobalt_strike، المشار إليه باسم third-party Client Controller في المواصفات، موضح أدناه:
EncoderTransportTransportEncoderTransportTransportEncoderيجب أن يدعم Server القدرة على التعامل مع عدة Clients (لم يتم تنفيذه بعد)، وأن يكون قابلاً للتفاعل من خلال framework_manager.
الـ Client هو الحمولة التي تعمل على نقطة النهاية. منطق الـ Client لـ Framework cobalt_strike ثابت بشكل أساسي، وموضح أدناه:
TransportTransportTransport للمهام الجديدةTransportيستخدم الـ Client Encoder و Transport المحددين لنقل البيانات بينه وبين Server الخاص به.
تستقبل الـ Encoders البيانات، ثم تعدل تلك البيانات إما لتحضيرها للاستخدام للإرسال عبر الـ Transport، أو لفك ترميز البيانات المستلمة عبر الـ Transport إلى شكلها الخام ليتم تفسيرها بواسطة أي مكون من الـ Framework يستخدمها.
يجب أن تتوقع الـ Encoders أن يتم التفاعل معها مباشرةً بواسطة الـ Transport، وأن تتعامل مع البيانات بطريقة محايدة للـ Framework والمكون.
تخدم الـ Transports دور إرسال واستقبال البيانات عبر قناة اتصال، والتفاعل مع الـ Encoder لضمان تحويل البيانات إلى أي تنسيق ضروري. يجب أن تتوقع الـ Transports استقبال البيانات من مكون Framework، أو عبر قناة الاتصال، وأن تكون قادرة على إرسال البيانات عبر قناة الاتصال. الـ Transports مسؤولة عن استدعاء Encoder لترميز أو فك ترميز البيانات حسب الحاجة.
يجب أن تتوقع الـ Transports أن يتم التفاعل معها مباشرةً بواسطة مكون Framework، وأن تتعامل مع البيانات بطريقة محايدة للـ Framework والمكون.
أولاً، حدد أي وحدة نقل وترميز ترغب في استخدامها. سنستخدم transport_imgur و encoder_lsbjpg للمثال التالي.
بعد ذلك، أنشئ ملف builder_config.config يناسب احتياجاتك، راجع ملف التهيئة النموذجي والقالب المقدمين للحصول على إرشادات حول كيفية القيام بذلك.
أنشئ بناء باستخدام build_files.py. كمثال، يمكن إنشاء بناء في دليل builds باستخدام encoder_lsbjpg و transport_imgur لـ Cobalt Strike، بشكل مفصل، باستخدام الأمر التالي:
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
بعد ذلك، قم بتنفيذ الـ Client على نقطة النهاية المستهدفة.
إذا نجح كل شيء، سيتم تسجيل beacon جديد في وحدة تحكم Cobalt Strike يمكنك التفاعل معه.
لماذا كتبت هذا؟: لم يكن هناك الكثير من التطبيقات المنشورة لمواصفات Cobalt Strike، ومن بين تلك المنشورة، إما أنها ليست بلغة مألوفة لدي أو لا تحتوي على النمطية والتجريد الذي كنت أبحث عنه.
لماذا بايثون 2؟: أنا كسول ومن السهل تنفيذ قنوات نقل وترميز جديدة فيه.
الكود الخاص بك سيء: هذا ليس سؤالاً.
هل يمكنني تقديم وحدات نقل و/أو ترميز جديدة؟: نعم من فضلك! أرسل طلب سحب وسأكون سعيداً بمراجعته.
كيف يمكنني تجميع الـ Client في ملف تنفيذي يمكنني توزيعه؟:
لقد اختبرت هذا بنجاح في Kali، لإعادة إنشاء بيئتي، فقط تأكد من تثبيت veil-evasion وأنك نفذت الإعداد الخاص به. يجب أن يكون قد أنشأ بيئة wine مثبتة عليها بايثون ولديها جميع التبعيات التي تحتاجها. قد تضطر أيضاً إلى تثبيت وحدة pefile في هذه البيئة.
بعد ذلك، يمكنك الانتقال إلى دليل الـ Client الذي تريد إنشاء ملف تنفيذي له وتشغيل:
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 بأي شيء تريده. يجب أن ترى الملف التنفيذي للـ Client في دليل dist/. إذا كنت ترغب في إنشاء ملف تنفيذي يوفر وحدة تحكم يمكنك استخدامها لتصحيح الأخطاء، قم بتجميع الملف التنفيذي باستخدام wine "C:\\Python27\\python.exe" /usr/share/veil/pyinstaller/pyinstaller.py -F -r c2file.dll -c client.py.