بينما تواصل عناصر الذكاء الاصطناعي من الجيل التالي والتعلم الآلي ضمن حلول الأمن تعزيز قدرات الكشف القائمة على السلوك، لا يزال العديد منها يعتمد في جوهره على أساليب الكشف القائمة على التوقيع. نظرًا لأن Cobalt Strike يُعَد إطار عمل شائعًا للتحكم والقيادة (C2) لدى الفريق الأحمر، ويُستخدم كذلك من قِبل عناصر التهديد منذ إطلاقه، فإنه لا يزال يخضع على نطاق واسع للكشف المعتمد على التوقيع من قِبل الحلول الأمنية.
لمواصلة الاستخدام التشغيلي لأداة Cobalt Strike كما كان في السابق، استثمرنا نحن في فريق IBM X-Force Red Adversary Simulation جهودًا كبيرة في البحث والتطوير لتخصيص Cobalt Strike باستخدام أدوات داخلية. تتوفر لبعض أدواتنا الداخلية الخاصة بـ Cobalt Strike إصدارات عامة، مثل "InlineExecute-Assembly"، و"CredBandit"، و"BokuLoader". خلال العامين الماضيين، وبسبب الإفراط في الاعتماد على التواقيع المرتبطة بأداة Cobalt Strike، قمنا بتقييد استخدامه ليقتصر على محاكاة عناصر تهديد أقل تعقيدًا، ونعتمد بدلًا من ذلك على أطر تحكم وقيادة (C2) أخرى من جهات خارجية ومن تطويرنا الداخلي عند تنفيذ تمارين الفريق الأحمر أكثر تقدمًا.
من خلال جهود البحث والتطوير، توصلنا إلى تحقيق نجاح تشغيلي أفضل في تمارين الفريق الأحمر المتقدمة باستخدام:
ومع ذلك، لا يزال عدد كبير من عناصر التهديد يعتمد على نسخ مقرصنة من Cobalt Strike، ما يجعل من المهم الاستمرار في القدرة على محاكاة هذه العناصر. بالنسبة إلى الفريق الأحمر المستعد لبذل جهد في البحث والتطوير، لا يزال بالإمكان تحقيق نجاح تشغيلي باستخدام Cobalt Strike عند محاكاة هذه الجهات المعادية. بالإضافة إلى ذلك، تُعَد Cobalt Strike أداة تعليمية ممتازة، يمكن للمبتدئين الاستفادة منها للحصول على خبرة عملية مع إطار عمل C2 من خلال دورات تدريبية للفريق الأحمر.
ومع استمرارنا في توسيع قدراتنا في مجال C2، نشارك بعض الرؤى حول كيفية البناء على إطار عمل Cobalt Strike في السابق، وتحديدًا من خلال تطوير محمِّلات انعكاسية مخصصة. كما يهدف هذا المحتوى إلى تمكين فِرق الدفاع من فهم آلية عمل Cobalt Strike لبناء قدرات كشف أكثر قوة.
النشرة الإخبارية الخاصة بالمجال
ابقَ على اطلاع دائم على أبرز الاتجاهات في مجالات الذكاء الاصطناعي، والأتمتة، والبيانات، وغيرها الكثير من خلال رسالة Think الإخبارية. راجع بيان الخصوصية لشركة IBM.
سيصلك محتوى الاشتراك باللغة الإنجليزية. ستجد رابط إلغاء الاشتراك في كل رسالة إخبارية. يمكنك إدارة اشتراكاتك أو إلغاء اشتراكك من هنا. لمزيد من المعلومات، راجع بيان خصوصية IBM.
يُعَد منشور المدونة هذا الأول ضمن سلسلة تمهيدية تستعرض أساسيات تطوير المحمِّل الانعكاسي لأداة Cobalt Strike. مع تقدُّمنا في هذه السلسلة، سنبني على هذا الأساس ونشير إلى هذا المنشور.
بنهاية هذه السلسلة، نهدف إلى إنشاء محمِّل انعكاسي يتكامل مع ميزات المراوغة الحالية في Cobalt Strike، بل ويعززها باستخدام تقنيات متقدمة غير متوفرة حاليًا في الأداة. ستتناول منشورات المدونة القادمة بمزيدٍ من التفصيل تطوير ميزات مراوغة محددة، وكيفية دمجها ضمن المحمِّل الانعكاسي في Cobalt Strike.
للبدء، سيغطي هذا المنشور ما يلي:
أثناء استكشافنا لآلية التحميل الانعكاسي في Cobalt Strike من منظور مطوِّر أدوات الأمن الهجومي، سنسلِّط الضوء على فرص الكشف وأساليب المراوغة. سيتم تجاوز أو تبسيط بعض الجوانب التطويرية، ونشجعك على سد هذه الفجوات من خلال تتبُّع الأخطاء في مشاريع محمِّلات انعكاسية قائمة، أو إعادة بنائها من الصفر، أو الالتحاق بتدريبات متخصصة.
يُعَد عنصر C2 في Cobalt Strike، المعروف باسم Beacon، مكتبة ربط ديناميكية (DLL) تعمل على Windows، وتُعرَف القدرة المعيارية على استخدام محمِّل DLL خاص بنا داخل Cobalt Strike باسم User‑Defined Reflective Loader (UDRL).
عادةً ما يكون محمِّل DLL المدمج في Windows مسؤولًا عن تحميل مكتبات DLL إلى مساحة الذاكرة الافتراضية للعملية. يوجد محمِّل DLL في Windows بشكل رئيسي في مساحة المستخدم، رغم أنه يتجاوز ذلك أحيانًا إلى مساحة النواة عند تحميل DLLs من القرص.
يترتب على استخدام محمِّل DLL في Windows بعض القيود عند توظيفه ضمن محاكاة الجهات المعادية، منها:
لذلك، فإن استخدام Windows DLL Loader لتحميل مكتبة Beacon DLL لا يُعَد حلًا مثاليًا. لتجاوز هذه التحديات، نقوم بتحميل مكتبة Beacon DLL من الذاكرة باستخدام محمِّل انعكاسي.
نقاط الكشف الثلاث الرئيسية التي يتجنّبها التحميل الانعكاسي هي:
يمكن اعتبار التحميل الانعكاسي ببساطة عملية تحميل DLL غير منسقة مباشرةً من الذاكرة، بدلًا من تحميله من نظام الملفات.
كلٌّ من التحميل الانعكاسي ومُحمِّل Windows DLL Loader المدمج يخدمان الغرض نفسه، وهو تحميل مكتبة DLL من الصيغة غير المنسقة إلى مساحة الذاكرة الافتراضية للعملية. ومع ذلك، يمتلك التحميل الانعكاسي ميزة رئيسية مقارنةً بـ Windows DLL Loader، وهي أنه لا يتطلب وجود ملف DLL على نظام الملفات. يُتيح هذا التحميل من الذاكرة عددًا غير محدود من مراحل التحميل المتسلسل، إذ يمكن إخفاء DLL الخاص بعنصر C2 داخل طبقات متعددة من التشفير والترميز ضمن ذاكرة العملية.
من المفاهيم الأساسية لفهم عملية تحميل DLL، إدراك أن صيغة DLL تختلف عند وجودها على القرص مقارنةً بوجودها في الذاكرة. الاختلافات الرئيسية بين DLL في تنسيق الملف غير المنسق وتنسيق العناوين الافتراضية هي:
تنسيق الملف غير المنسق:
تنسيق العنوان الافتراضي:
عند فحص ملف DLL الخاص بإشارة HTTP باستخدام أداة PE-Bear من تطوير Aleksandra Doniec، نلاحظ الفروقات بين العناوين غير المنسَّقة والافتراضية لكل قسم من أقسام مكتبة DLL.
جدول يوضِّح العناوين غير المنسَّقة والافتراضية لكل قسم من أقسام ملف DLL للإشارة.
يبلغ حجم مكتبةDLL الخاصة بإشارة HTTP/S عند تحميلها في مساحة الذاكرة الافتراضية للعملية
توفِّر أداة PE-Bear تمثيلًا بصريًا لملف DLL للإشارة كما هو موجود في تنسيق الملف غير المنسق مقابل تنسيق مساحة العناوين الافتراضية.
تمثيل مرئي لملف DLL للإشارة في التنسيق غير المنسق (يسار) مقابل التنسيق الافتراضي (يمين)
رغم أن تنفيذ ذلك ليس الخيار الأكثر حكمة أثناء محاكاة خصم، فإن إسقاط ملف DLL غير منسَّق للإشارة دون أي تمويه على القرص ثم تحميله باستخدام Windows DLL Loader يُعَد وسيلةً ممتازة لفهم آلية عمل الإشارة وآلية تحميل DLL. في جوهره، برنامج Beacon ليس سوى ملف DLL. يعمل Windows DLL Loader ومحمِّل الانعكاس على تحميل ملف DLL داخل عملية.
لتحميل ملف DLL الخاص بـ Beacon باستخدام Windows DLL Loader، ننفِّذ الخطوات التالية:
LoadLibrary
واجهة برمجة التطبيقات لتحميل مكتبة beacon DLL من القرص.أولًا، نقوم بتعطيل جميع خيارات Malleable PE التي تجعل ملف DLL الخاص بالإشارة غير قابل للتحميل بواسطة Windows DLL Loader. لتحقيق ذلك، نقوم بتعديل ملف تعريف Malleable C2 الخاص بنا وتعطيل خيارات مراوغة Malleable PE الموجودة ضمن كتلة stage:
تم تعديل كتلة stage في ملف تعريف Malleable C2 لتعطيل ميزات التهرّب في Cobalt Strike.
بعد تعديل ملف التعريف، نعيد تشغيل خادم فريق Cobalt Strike مع تمرير
نتصل بخادم الفريق مع عميل Cobalt Strike. ثم نُنشئ ملف
كلقطة شاشة لعملية إنشاء ملف DLL لإشارة "غير منسقة دون مرحلة" من Cobalt Strike Client.
باستخدام الكود أدناه، نُنشئ برنامجًا بلغة C باسم
كود C لنظام Windows لتحميل ملف beacon DLL من القرص باستخدام Windows DLL Loader.
نحن نستخدم
كجزء من عملية التحميل، يقوم محمل DLL في ويندوز بتهيئة ملف DLL الخاص بالإشارة من خلال استدعاء نقطة الدخول الخاصة به مع تمرير
بعد أن يقوم Windows DLL Loader بتحميل ملف beacon DLL وتهيئته داخل مساحة الذاكرة الافتراضية للعملية، سنحتاج إلى استدعاء نقطة الدخول لملف beacon DLL الافتراضي مرة أخرى مع تمرير الوسيط.
يجب أن يعرف برنامجنا نقطة الدخول لملف beacon DLL الافتراضي لتنفيذ هذا الملف. يمكن القيام بذلك بشكل ديناميكي داخل البرنامج عن طريق تحليل رؤوس ملف beacon DLL الافتراضي لاستخراج العنوان الافتراضي النسبي (RVA) لنقطة الدخول، أو يمكننا الاطلاع سريعًا على قيمته وكتابتها مباشرةً في الكود.
من أجل نموذج الإثبات لدينا، سنكتشف يدويًا ونثبت قيمة RVA لنقطة الدخول في ملف beacon DLL داخل برنامجنا. باستخدام PE-Bear، نكتشف أن العنوان الافتراضي النسبي (RVA) لنقطة الدخول في الإشارة هو
لقطة شاشة توضِّح تحديد العنوان الافتراضي النسبي (RVA) لنقطة الدخول في ملف beacon DLL باستخدام PE-Bear
إن طريقة
بعد أن أصبح الكود الخاص بنا جاهزًا، نعمل على ترجمة برنامج C الخاص بنا إلى ملف تنفيذي لنظام Windows.
الأمر المستخدم لتجميع برنامجنا.
بوضع ملف Beacon DLL وبرنامج التحميل التنفيذي في نفس المجلد، سيتمكن Windows DLL Loader من اكتشاف ملف DLL أثناء تنفيذ روتين التحميل.
نحن نضع كليهما
تم وضع Beacon DLL وبرنامج المحمِّل في نفس الدليل.
من سطح مكتب Windows، ننقر نقرًا مزدوجًا على برنامج loadBeaconDLL.exeونُنشئ اتصال beacon نشطًا بخادم الفريق الخاص بنا.
اتصال ناجح بخادم الفريق C2 من ملف beacon DLL بعد تحميله باستخدام Windows DLL Loader.
تستخدم Cobalt Strike نسخة معدّلة من مشروع Reflective Loader الذي طوّره Stephen Fewer. يُعَد هذا محمِّل DLL الأسطوري العامل في الذاكرة قيد الاستخدام منذ أكثر من عقد، وقد استُخدم في Metasploit وغيرها من أدوات الأمن الهجومي البارزة.
على مر السنين، تم تحسين المحمِّل الانعكاسي في Cobalt Strike للتعامل مع جميع ميزات التهرّب المصنوعة من Malleable PE التي تقدِّمها Cobalt Strike. العيب الرئيسي لاستخدام محمِّل انعكاسي مخصص معرَّف من قِبل المستخدم (UDRL) هو أن ميزات التهرُّب الخاصة بـ Malleable PE قد تكون مدعومة أو غير مدعومة بشكل افتراضي.
تكون بعض ميزات التهرُّب مطبَّقة بالكامل عند استخدام محمِّل انعكاسي مخصص (UDRL)، حيث يتم تضمينها داخل ملف beacon DLL بواسطة محرّك Malleable PE في Cobalt Strike أثناء إنشاء حمولة الإشارة. ومع ذلك، في الوقت الحالي يجب أن تتم معالجة ميزات مثل بواسطة UDRL، في حين يتم التعامل مع ميزات أخرى مثل و واجهة
يتطلب مشروع المحمِّل الانعكاسي (Reflective Loader) الأصلي تجميع
ثم هناك مشروع آخر مسؤول عن:
رسم تخطيطي للمحمِّل الانعكاسي الأصلي، يقوم بتحميل ملف DLL إلى الذاكرة الافتراضية.
هناك طريقة بديلة وهي إضافة المحمِّل الانعكاسي قبل DLL. فهذا يسمح بتحميل أي ملف DLL غير مُدار ولا يتطلب تجميع DLL من الكود المصدر. هذه طريقة تحميل انعكاسي قوية قادرة على تحميل أي ملف PE (EXE أو DLL).
مخطط يوضِّح المحمِّل الانعكاسي المضاف إلى DLL، يقوم بتحميل DLL إلى الذاكرة الافتراضية.
يعتمد تنفيذ التحميل الانعكاسي في Cobalt Strike على مزيج من الطريقتين المذكورتين أعلاه. قد تكون طريقة التحميل الانعكاسي هذه مألوفة لمن لديهم معرفة بكيفية تنفيذ Meterpreter في Metasploit لآلية التحميل الانعكاسي.
على غرار طريقة المحمِّل الانعكاسي الأصلي، يتم تجميع وظيفة
عند تحميل UDRL داخل Cobalt Strike، وعندما يقوم المشغِّل بإنشاء حمولة beacon من عميل Cobalt Strike، يقوم محرّك Malleable PE في Cobalt Strike بترقيع كود shellcode الخاص بالمحمِّل الانعكاسي عند إزاحة الملف غير المنسق لتصدير
عند اكتمال قيام محرّك Malleable PE بتعديل ملف beacon DLL غير المنسق، يتم تسليم ملف beacon DLL غير المنسق إلى المشغِّل بصيغة تنفيذية شبيهة بـ shellcode.
مخطط يوضِّح المحمِّل الانعكاسي في Cobalt Strike أثناء تحميل beacon DLL إلى الذاكرة الافتراضية.
عند فحص البايتات الأولية باستخدام أداة التفكيك PE‑Bear، يمكننا ملاحظة أن beacon DLL قابل للتنفيذ بحد ذاته:
يظهر مقطع استدعاء المحمِّل الانعكاسي على هيئة أكواد عمليات تجميعية قابلة للتنفيذ.
وحدات البايت الأولية
بعد تنفيذ الكود المضاف اختياريًا
نؤكِّد أن إزاحة الملف غير المنسق الخاصة بتصدير
لقطة شاشة تُظهر استخدام PE‑Bear لتحديد إزاحة الملف غير المنسق لعنصر التصدير ReflectiveLoader.
كما هو موجود ضمن دليل التصدير، يكون عنوان عنصر التصدير
لاكتشاف ملف الإزاحة غير المنسق لتصدير
إن العناوين الافتراضية وغير المنسقة
عناوين أولية وافتراضية لنصوص الخاص بـ beacon DLL.
الفرق بين الاثنين هو
يمكننا تأكيد ذلك في PE‑Bear عن طريق النقر بزر الماوس الأيمن على Function RVA الخاص بوظيفة
باختصار، يكون تسلسل عملية التحميل الانعكاسي في Cobalt Strike على النحو التالي:
مخطط يوضِّح المراحل الرئيسية لكيفية تنفيذ Cobalt Strike لعملية التحميل الانعكاسي لملف beacon DLL.
نظرًا لأن المحمِّل الانعكاسي يتم تنفيذه قبل تحميل beacon DLL، يجب أن يكون كود المحمِّل الانعكاسي كود shellcode خالصًا.
أسهل طريقة لإنشاء shellcode معقد هي كتابته بلغة C دون أي تبعيات خارجية. ثم يتم تحويل ملف C إلى ملف كائن. يجب تضمين كل شيء في قسم وأخيرًا، نقوم باستخراج قسم.text
سيتولى محرّك Malleable PE في Cobalt Strike مهمة استخراج كود shellcode من ملف الكائن الخاص بالمحمِّل الانعكاسي لدينا، ثم تعديلها داخل beacon DLL غير المنسق عند إزاحة الملف غير المنسق للوظيفة
نص Aggressor لكتابة كود المحمِّل الانعكاسي (shellcode) داخل beacon DLL غير المنسق باستخدام Cobalt Strike.
يقوم نص Aggressor الخاص بـ UDRL لدينا بجعل Cobalt Strike يكتب كود المحمِّل الانعكاسي (shellcode) من خلال تنفيذ الخطوات التالية:
<a href="https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics_aggressor-scripts/as-resources_functions.htm#extract_reflective_loader">extract_reflective_loader</a>دالة Cobalt Strike Agidersor المدمجة على تحليل ملف كائن UDRl من مصفوفة البايت
<a href="https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics_aggressor-scripts/as-resources_functions.htm#setup_reflective_loader">setup_reflective_loader</a>ستستخدم وظيفة Cobalt Strike Aggressor محرك Malleable PE لاكتشاف موضع الإزاحة في الملف غير المنسق لوظيفة
يتولى Cobalt Strike تنفيذ العمل نيابةً عنا فيما يخص استخراج قسم .text من ملف كائن المحمِّل الانعكاسي، ودمج كود shellcode الخاص بنا، ثم استدعاء المحمِّل الانعكاسي عبر مقطع استدعاء المحمِّل الانعكاسي الموجود في ترويسة ملف beacon DLL.
هذه هي المراحل التي يجب تطويرها لتنفيذ التحميل الانعكاسي لـ beacon:
هناك عدة طرق مختلفة يمكننا استخدامها لاكتشاف العنوان الخاص بملف beacon DLL غير المنسق في الذاكرة. وتتضمن هذه الطرق ما يلي:
عند استخدام أسلوب يعتمد على البحث للخلف، نحتاج أولًا إلى الحصول على العنوان الحالي لمؤشر التعليمات الخاص بمسار التنفيذ لدينا (
كود تجميع Intel x64 لاستخراج العنوان الأساسي لملف beacon DLL غير المنسق من السجل RDI.
يعتمد مشروع المحمِّل الانعكاسي الأصلي على البحث للخلف عن رؤوس MZ وPE. وقد أصبحت هذه الرؤوس نقاط كشف. ولمعالجة ذلك، أضافت Cobalt Strike
توضِّح وثائق Cobalt Strike أن خيار
عند التكوين، تكوين بايتات
يجب أن تكون هذه البايتات فريدة من نوعها إلى حد ما، وإلا فلن يتمكن المحمِّل الانعكاسي من العثور عليها. بالإضافة إلى ذلك، يجب أن تكون وحدات البايت الخاصة برأس MZ عمليات غير قابلة للتشغيل والتنفيذ. لا يمكن أن تكون قيمًا مثل
بعد اكتشاف نقطة الكشف المحتملة هذه، قمت بتطوير طريقة مختلفة لكنها متشابهة لتحديد عنوان الأساس لملف beacon DLL غير المنسق. تستخدم هذه الطريقة آلية بحث قادرة على المسح العكسي من
تم اختيار العنوان
نظرًا لعدم توفر وصول سهل إلى محرك Java Malleable PE،
سكربت Aggressor لكتابة قيمة التعريف داخل ملف beacon DLL غير المنسق وعرض التغييرات في وحدة تحكم سكربت Cobalt Strike.
يجب أن يكون كود UDRL على علم بقيمة التعريف التي يكتبها سكربت UDRL داخل ملف beacon DLL غير المنسق. بعد تحديد قيمة التعريف، تقوم آلية البحث بالمسح العكسي للعثور على تكرارين من هذه القيمة، كما هو موضَّح في الكود أدناه:
رمز تجميع Intel x64 لأداة صيد قيم التعريف التي تبحث عن مثيلين لقيمة 64 بت.
الآن، وبما أن ترويسات MZ وPE لم تَعُد قيد الاستخدام، يمكن استبدالها بتعليمات NOP داخل سكربت UDRL Aggressor:
سكربت Aggressor لتمويه ترويسات MZ وPE والبايتات غير المستخدمة في لافتة DOS داخل ترويسات beacon DLL غير المنسق.
توجد أيضًا طريقة أخرى خاصة بأداة Cobalt Strike لاكتشاف عنوان الأساس لملف beacon DLL غير المنسق. كما رأينا أعلاه، تقوم البايتات الأولية في مقطع Call Reflective Loader بتخزين عنوان الأساس لملف beacon DLL غير المنسق في سجل
لفحص هذا الأمر بشكل أكبر في مصحح الأخطاء، نعمل على إنشاء إشارة، نضيف إليها نقطة توقف مسبقًا (
لقطة شاشة من X64dbg أثناء التنقل خطوة بخطوة عبر مقطع Call Reflective Loader، توضِّح أن عنوان الأساس لملف beacon DLL غير المنسق محفوظ في سجل RDI قبل استدعاء المحمِّل الانعكاسي.
فيما يلي مثال عملي يوضِّح كيفية الحصول على عنوان الأساس لملف beacon DLL غير المنسق من مقطع Call Reflective Loader:
كود C باستخدام التجميع المضمن (Inline Assembly) للحصول على عنوان الأساس لملف beacon DLL غير المنسق من سجل RDI.
بعد الحصول على عنوان الأساس لملف beacon DLL غير المنسق، يمكننا الآن استخراج القيم اللازمة لتحميل beacon في مساحة العناوين الافتراضية للعملية.
يوضِّح الجدول أدناه القيم التي نحتاجها من ترويسات ملف beacon DLL غير المنسق، ومواقع وجودها، وأنواعها:
جدول يسرد القيم المستخرجة من ترويسة ملف beacon DLL غير المنسق والتي تُستخدم لتحميل ملف beacon DLL.
ليست كل محتويات الترويسات مطلوبة لتحميل ملف beacon DLL. يمكن إعادة تعبئة القيم المطلوبة أو إخفاؤها. يمكن إزالة القيم غير المطلوبة أو توزيعها بشكل عشوائي.
بمجرد معرفةSizeOfImagef
يمكن استخدام طرق مختلفة لتخصيص الذاكرة لملف beacon DLL الافتراضي. ستستخدم الطرق المختلفة أنواعًا مختلفة من الذاكرة. الطرق المختلفة التي يدعمها محمِّل Cobalt Strike الانعكاسي الافتراضي هي:
جدول يوضِّح خيارات تخصيص الذاكرة في Cobalt Strike لملف beacon DLL الافتراضي.
ويمكن اتخاذ خطوة أخرى إلى الأمام باستخدام UDR. يمكن استخدام إصدار NTAPI من هذه الوظائف بدلًا من ذلك. بالإضافة إلى ذلك، يمكن استدعاء وظائف NTAPI عبر استدعاءات نظام مباشرة أو غير مباشرة، وهو ما قد يساهم أو لا يساهم في تعزيز قدرات التخفي.
عند تعيين أسلوب تخصيص الذاكرة على
مثال كود من مشروع BokuLoader يوضِّح استخدام نداء نظام مباشر لتخصيص الذاكرة الخاصة بملف beacon DLL الافتراضي.
توضِّح الصورة أدناه مثال كود يوضِّح كيفية استخدام أسلوبَي HellsGate وHalosGate لتحديد أرقام استدعاءات النظام:
مثال كود من مشروع BokuLoader يوضِّح كيفية اكتشاف استدعاءات النظام من العملية.
بعد أن قمنا بتخصيص الذاكرة ملف beacon DLL الافتراضي، نحتاج إلى نسخ أقسام beacon من إزاحاتها غير المنسقة في الملف، كما هي موجودة في ملف beacon DLL غير المنسق، إلى الذاكرة المخصّصة عند إزاحاتها الافتراضية النسبية.
إذا خصصنا ذاكرتنا باستخدامREADWRITE قبل استدعاء نقطة الدخول إلى beacon DLL الافتراضي، سنحتاج إلى تغيير حماية الذاكرة في قسم
تخصيص ذاكرتنا باستخدام يجعل عملية التحميل الانعكاسي أسهل ولكنه يزيد من فرص الكشف بواسطة الحلول الأمنية.
فيما يلي مثال كود مبسَّط من مشروع BokuLoader يوضِّح ذلك:
مثال كود من مشروع BokuLoader يوضِّح نسخ الأقسام من ملف beacon DLL غير المنسق إلى ملف beacon DLL الافتراضي.
تتضمن بعض ميزات التخفي المتعلقة بتحميل الأقسام ما يلي:
في مشروع BokuLoader العام، لا يتم نسخ ترويسات ملف beacon DLL من الملف غير المنسق إلى ملف beacon DLL الافتراضي. حاليًا، البايتات الأولى
فرصة تفادٍ محتملة أخرى تتمثل في قيام سكربت UDRL Aggressor بتشفير الأقسام. يمكن فك تشفير الأقسام في الذاكرة بواسطة UDRL باستخدام مفتاح مشترك بين UDRL وسكربت UDRL Aggressor.
تعتمد إشارة x64 HTTP/S على أربعة ملفات DLL لتعمل بشكل صحيح. إذا لم تكن ملفات DLL هذه محملة حاليًا في المعالجة، فسيتعين على أداة التحميل الانعكاسي تحميلها.
تم إدراج ملفات DLL الأربعة في دليل استيراد ملف DLL الخاص بإشارة HTTP/S:
لقطة شاشة من PE-Bear تعرض ملفات DLL من دليل استيراد ملفات beacon DLL.
يستخدم المحمِّل الانعكاسي المدمج في Cobalt Strike واجهة برمجة التطبيقات kernel32.LoadLibraryA لتحميل DLL.
يمكن تحقيق تحميل ملفات DLL بطرق مختلفة ومتنوعة، مع مراعاة اعتبارات أمنية تشغيلية مختلفة. وتتضمن هذه الطرق ما يلي:
إذا كان DLL موجودًا بالفعل في العملية، فيمكن استخدام واجهات برمجة التطبيقات السابقة لنظام Windows للحصول على عناوين قاعدة DLL، رغم أن ذلك قد يؤدي إلى تنبيهات كشف غير مرغوب فيها.
أو بدلًا من ذلك، يحتوي PEB على مؤشر إلى مقطع
<a title="https://learn.microsoft.com/qa-ar/windows/win32/api/winternl/ns-winternl-peb_ldr_data" href="https://learn.microsoft.com/qa-ar/windows/win32/api/winternl/ns-winternl-peb_ldr_data">_PEB_LDR_DATA</a>
. يحتوي الملف على قائمة مرتبطة بجميع ملفات DLL المحمَّلة في العملية ومعلوماتها ذات الصلة (
). يعمل BokuLoader على الاستفادة من ذلك لاكتشاف معلومات DLL، وتجنُّب استدعاءات واجهة برمجة التطبيقات غير الضرورية.
في حالة عدم وجود ملف DLL في
لا يمكن استخدام التحميل الانعكاسي المتداخل بسهولة لتحميل تبعيات DLL لأن المحمِّلات الانعكاسية لا تقوم عمومًا بتسجيل DLL في العملية. لا يمكن للتعليمات البرمجية الخارجية لملف DLL استخدام ملف DLL المحمَّل بشكل انعكاسي بشكل صحيح. قد يكون مشروع DarkLoadLibrary قادرًا على تحميل ملف DLL بشكل صحيح في الذاكرة دون تشغيل حدث تحميل صورة النواة.
نموذج كود من مشروع BokuLoader يوضِّح كيفية حل عناوين DLL الأساسية المحمَّلة عن طريق استعراض InMemoryOrderModuleList.
بعد تحميل ملفات DLL المطلوبة في العملية، يجب حل واجهات برمجة التطبيقات المدرجة في دليل الاستيراد. بعد ذلك، يجب كتابة عناوين واجهة برمجة التطبيقات (API) إلى جدول عناوين الاستيراد (IAT) الخاص بمكتبة beacon DLL الافتراضية. وبهذه الطريقة، يعرف جهاز الإرسال العنوان الذي يجب الانتقال إليه عند الحاجة إلى استدعاء واجهات برمجة التطبيقات مثل
يجب حل إدخال الاستيراد عن طريق السلسلة الترتيبية أو سلسلة الاسم.
في الصورة أدناه، نرى أن مكتبة Cobalt Strike beacon DLL تستخدم مزيجًا من الأرقام الترتيبية وسلاسل الأسماء لإدخالات الاستيراد:
لقطة شاشة من PE-Bear توضِّح أن بعض إدخالات الاستيراد لملف beacon DLL يجب حلها حسب الترتيب.
يستخدم نظام المحمِّل الانعكاسي المدمج في Cobalt Strike واجهة برمجة التطبيقات
تتضمن بعض أساليب التهرب لحل عناوين واجهة برمجة التطبيقات ما يلي:
GetProcAddress
NTDLL.LdrGetProcedureAddress
يستخدم BokuLoader تنفيذ رمز مخصص لـGetProcAddress
ثم يتم استبدال إذا كان العنوان المُعاد لإدخال الاستيراد عبارة عن مُعيد توجيه إلى ملف DLL آخر، فإن BokuLoader يستخدم افتراضيًا لحل مُعيد التوجيه.
أثناء كتابة جدول ربط التطبيقات (IAT)، يمكن تنفيذ الربط عن طريق كتابة العناوين الافتراضية لوظائف الربط التي قمنا بتنفيذها بدلًا من العنوان الافتراضي لواجهات برمجة التطبيقات المقصودة. طالما يتم إرجاع المخرجات المتوقعة إلى جهاز الإرسال (beacon) عند استدعاء العنوان الموجود في جدول عناوين الإدخال، يمكننا تنفيذ تعليمات برمجية إضافية قبل العودة إلى جهاز الإرسال. ستوضِّح المنشورات المستقبلية والإصدارات العامة لبرنامج BokuLoader كيف يمكننا الاستفادة من ربط IAT للحصول على ميزات التهرب المتقدمة.
مع إصدار حديث، يدعم مشروع BokuLoader العام عن طريق تعديل مفتاح الإخفاء في نصBokuLoader.cna
فيما يتعلق بالأمن التشغيلي، من المهم معرفة أن محركات مطابقة الأنماط قادرة على استخدام القوة الغاشمة لاختراق أقنعة XOR أحادية البايت. ستوضِّح المنشورات المستقبلية كيف يمكننا إنشاء محرك PE قابل للتعديل خاص بنا باستخدام وظائف البرمجة النصية لـ Cobalt Strikes Aggressor لإخفاء الإشارات للتغلب على مطابقة الأنماط.
يحتوي ملف DLL الخاص بالمنارة على العديد من عمليات النقل التي يجب حلها وكتابتها في جدول النقل الأساسي لملف beacon DLL الافتراضي قبل تنفيذه.
في PE-Bear، يمكننا أن نرى أن ملف beacon DLL يحتوي افتراضيًا على عنوان قاعدة الصورة التالي:
لقطة شاشة من PE-Bear تُظهر العنوان الأساسي لصورة beacon DLL.
قبل أن نبدأ في كتابة عمليات النقل، نحتاج إلى حساب الفرق بين العنوان الأساسي لملف beacon DLL الافتراضي والعنوان الأساسي المضمَّن في الكود.
على سبيل المثال، لنفترض أن العنوان الأساسي لملف beacon DLL الافتراضي هو
بعد ذلك، لتحديد العنوان الافتراضي لكل إدخال نقل في جدول النقل الأساسي، نضيف دلتا العنوان الأساسي إلى عنوان إدخال النقل المشفر لتحديد النقل داخل ملف beacon DLL الافتراضي الخاص بنا.
في الصورة أدناه، يمكننا أن نرى أن إدخالات إعادة توجيه الإشارات مكتوبة بشكل معكوس بتنسيق little-endian:
لقطة شاشة من PE-Bear تُظهر وجود بعض إدخالات النقل بتنسيق little-endian.
العنوان الثابت لإدخال النقل هذا هو
نضيف هذا العنوان إلى دلتا العنوان الأساسي، للحصول على العنوان الافتراضي لإعادة التوجيه كما هو موجود في beacon DLL الافتراضي:
لكل عملية نقل، سنحتاج إلى التحقق من أن النوع هو
<a title="https://learn.microsoft.com/qa-ar/windows/win32/debug/pe-format" href="https://learn.microsoft.com/qa-ar/windows/win32/debug/pe-format">IMAGE_REL_BASED_DIR64 (0xA)</a>
. إذا كان هذا غير صحيح، فسوف نتخطى كتابة عملية النقل.
بمجرد تحديد العنوان الافتراضي للنقل كما هو موجود داخل beacon DLL، نكتبه إلى مساحة الذاكرة التي تحتوي على عنوان إدخال النقل المشفر.
إذا كنت مهتمًا بمعرفة المزيد حول كيفية إجراء عمليات نقل الملفات، فراجع كود الدالة doRelocations في مشروع BokuLoader العام. قبل نشر هذه المدونة، قمت بتغيير كود إعادة التوجيه من لغة التجميع إلى كود C قابل للقراءة البشرية، وذلك لمساعدة الآخرين الذين يريدون معرفة التفاصيل التقنية لكيفية القيام بذلك.
يمكن تقسيم عملية تنفيذ Beacon إلى ثلاث خطوات:
إذا كانت الذاكرة التي خصصناها من أجل beacon DLL الافتراضي هي
إذا خصصنا ذاكرة beacon الافتراضية الخاصة بنا على أنها غير قابلة للتنفيذ (
في مشروع BokuLoader العام، يتم إجراء تغييرات حماية الذاكرة عن طريق استدعاءات النظام المباشرة إلى
نموذج التعليمات البرمجية من مشروع BokuLoader يوضِّح تغيير قسم .text من ملف beacon DLL الافتراضي إلى ملف قابل للتنفيذ.
تخزِّن
لكي يعمل ملف beacon DLL الافتراضي بشكل صحيح، يجب أولًا تهيئته عن طريق استدعاء نقطة دخول ملف beacon DLL الافتراضي. الوسيط الأول هو العنوان الأساسي لملف beacon DLL الافتراضي. الوسيط الثاني هو
نموذج كود من مشروع BokuLoader يقوم بتهيئة beacon DLL الافتراضي.
بعد تهيئة beacon DLL الافتراضي، يمكننا إعادة نقطة دخول المنارة الافتراضية إلى دالة التحميل الانعكاسي، أو يمكننا استدعاء نقطة دخول beacon DLL الافتراضي في ملف تعريف المستخدم الموحَّد (UDRL) الخاص بنا باستخدام
على عكس ملف DLL النموذجي حيث يكون الوسيط الأول
<a href="https://learn.microsoft.com/qa-ar/windows/win32/dlls/dllmain">DLLMAIN</a>
العنوان الأساسي لملف DLL الافتراضي، بينما يتوقع beacon العنوان الأساسي لملف DLL غير المنسق. في حال عدم توفير ذلك، قد تفشل بعض ميزات التهرب في Malleable PE.
مثال برمجي من مشروع BokuLoader يوضِّح طريقتين مختلفتين لتنفيذ ملف beacon DLL الافتراضي.
نأمل أن يساعد منشور المدونة هذا كلًّا من الفرق الحمراء والزرقاء على فهم أفضل لـ Cobalt Strike وعملية التحميل الانعكاسي. لا يزال هناك الكثير من فرص التهرب التي يمكن تنفيذها من خلال التحميل الانعكاسي. من خلال فهم أعمق لهذه المفاهيم، يمكن المؤسسات أن تُعِد نفسها بشكل أفضل للدفاع الناجح ضد التهديدات الإلكترونية.
ستركِّز المقالات القادمة في هذه السلسلة على دمج UDRL مع ميزات التخفي الحالية في Cobalt Strike، والتعمّق في ميزات التخفي غير الموثّقة الموجودة بالفعل في الإصدار العام من BokuLoader، إضافةً إلى ميزات متقدمة لم يتم طرحها للعامة بعد. ترقَّب المزيد من المعلومات المتعمقة والتقنيات المتقدمة للتعرُّف على كيفية الارتقاء باستخدام Cobalt Strike إلى مستوى أكثر تقدمًا من خلال تطوير UDRL.