تعريف المحمِّل الانعكاسي في Cobalt Strike

رجل يرتدي سترة سوداء بغطاء رأس يستخدم جهاز كمبيوتر محمولًا في الشارع، في تصوير لشخصية مخترق.

بينما تواصل عناصر الذكاء الاصطناعي من الجيل التالي والتعلم الآلي ضمن حلول الأمن تعزيز قدرات الكشف القائمة على السلوك، لا يزال العديد منها يعتمد في جوهره على أساليب الكشف القائمة على التوقيع. نظرًا لأن Cobalt Strike يُعَد إطار عمل شائعًا للتحكم والقيادة (C2) لدى الفريق الأحمر، ويُستخدم كذلك من قِبل عناصر التهديد منذ إطلاقه، فإنه لا يزال يخضع على نطاق واسع للكشف المعتمد على التوقيع من قِبل الحلول الأمنية.

لمواصلة الاستخدام التشغيلي لأداة Cobalt Strike كما كان في السابق، استثمرنا نحن في فريق IBM X-Force Red Adversary Simulation جهودًا كبيرة في البحث والتطوير لتخصيص Cobalt Strike باستخدام أدوات داخلية. تتوفر لبعض أدواتنا الداخلية الخاصة بـ Cobalt Strike إصدارات عامة، مثل "InlineExecute-Assembly"، و"CredBandit"، و"BokuLoader". خلال العامين الماضيين، وبسبب الإفراط في الاعتماد على التواقيع المرتبطة بأداة Cobalt Strike، قمنا بتقييد استخدامه ليقتصر على محاكاة عناصر تهديد أقل تعقيدًا، ونعتمد بدلًا من ذلك على أطر تحكم وقيادة (C2) أخرى من جهات خارجية ومن تطويرنا الداخلي عند تنفيذ تمارين الفريق الأحمر أكثر تقدمًا.

من خلال جهود البحث والتطوير، توصلنا إلى تحقيق نجاح تشغيلي أفضل في تمارين الفريق الأحمر المتقدمة باستخدام:

  • أدوات داخلية مخصصة.
  • وحدات تحميل داخلية مخصصة.
  • إطار تحكم وقيادة (C2) داخلي مخصص.
  • الاستمرار في الاستثمار لتوسيع قدرات أطر C2 البديلة من الأطراف الثالثة وتعزيز مستوى التخفي لديها.

ومع ذلك، لا يزال عدد كبير من عناصر التهديد يعتمد على نسخ مقرصنة من Cobalt Strike، ما يجعل من المهم الاستمرار في القدرة على محاكاة هذه العناصر. بالنسبة إلى الفريق الأحمر المستعد لبذل جهد في البحث والتطوير، لا يزال بالإمكان تحقيق نجاح تشغيلي باستخدام Cobalt Strike عند محاكاة هذه الجهات المعادية. بالإضافة إلى ذلك، تُعَد Cobalt Strike أداة تعليمية ممتازة، يمكن للمبتدئين الاستفادة منها للحصول على خبرة عملية مع إطار عمل C2 من خلال دورات تدريبية للفريق الأحمر.

ومع استمرارنا في توسيع قدراتنا في مجال C2، نشارك بعض الرؤى حول كيفية البناء على إطار عمل Cobalt Strike في السابق، وتحديدًا من خلال تطوير محمِّلات انعكاسية مخصصة. كما يهدف هذا المحتوى إلى تمكين فِرق الدفاع من فهم آلية عمل Cobalt Strike لبناء قدرات كشف أكثر قوة.

أحدث الأخبار التقنية، مدعومة برؤى خبراء

ابقَ على اطلاع دائم على أبرز الاتجاهات في مجالات الذكاء الاصطناعي، والأتمتة، والبيانات، وغيرها الكثير من خلال رسالة Think الإخبارية. راجع بيان الخصوصية لشركة IBM.

شكرًا لك! أنت مشترك.

سيصلك محتوى الاشتراك باللغة الإنجليزية. ستجد رابط إلغاء الاشتراك في كل رسالة إخبارية. يمكنك إدارة اشتراكاتك أو إلغاء اشتراكك من هنا. لمزيد من المعلومات، راجع بيان خصوصية IBM.

البناء على إطار العمل باستخدام المحمِّل الانعكاسي

يُعَد منشور المدونة هذا الأول ضمن سلسلة تمهيدية تستعرض أساسيات تطوير المحمِّل الانعكاسي لأداة Cobalt Strike. مع تقدُّمنا في هذه السلسلة، سنبني على هذا الأساس ونشير إلى هذا المنشور.

بنهاية هذه السلسلة، نهدف إلى إنشاء محمِّل انعكاسي يتكامل مع ميزات المراوغة الحالية في Cobalt Strike، بل ويعززها باستخدام تقنيات متقدمة غير متوفرة حاليًا في الأداة. ستتناول منشورات المدونة القادمة بمزيدٍ من التفصيل تطوير ميزات مراوغة محددة، وكيفية دمجها ضمن المحمِّل الانعكاسي في Cobalt Strike.

للبدء، سيغطي هذا المنشور ما يلي:

  • التحديات المرتبطة بتحميل وحدة C2 من القرص باستخدام محمِّل DLL في Windows.
  • المفاهيم والآليات الخاصة بعملية التحميل الانعكاسي في Cobalt Strike.
  • متطلبات التصميم اللازمة لبناء محمِّل انعكاسي فعَّال.
  • المراحل المتضمنة في عملية التحميل الانعكاسي.

أثناء استكشافنا لآلية التحميل الانعكاسي في Cobalt Strike من منظور مطوِّر أدوات الأمن الهجومي، سنسلِّط الضوء على فرص الكشف وأساليب المراوغة. سيتم تجاوز أو تبسيط بعض الجوانب التطويرية، ونشجعك على سد هذه الفجوات من خلال تتبُّع الأخطاء في مشاريع محمِّلات انعكاسية قائمة، أو إعادة بنائها من الصفر، أو الالتحاق بتدريبات متخصصة.

تحميل مكتبة Beacon DLL

يُعَد عنصر C2 في Cobalt Strike، المعروف باسم Beacon، مكتبة ربط ديناميكية (DLL) تعمل على Windows، وتُعرَف القدرة المعيارية على استخدام محمِّل DLL خاص بنا داخل Cobalt Strike باسم User‑Defined Reflective Loader (UDRL).

محمِّل DLL المدمج في نظام Windows

عادةً ما يكون محمِّل DLL المدمج في Windows مسؤولًا عن تحميل مكتبات DLL إلى مساحة الذاكرة الافتراضية للعملية. يوجد محمِّل DLL في Windows بشكل رئيسي في مساحة المستخدم، رغم أنه يتجاوز ذلك أحيانًا إلى مساحة النواة عند تحميل DLLs من القرص.

يترتب على استخدام محمِّل DLL في Windows بعض القيود عند توظيفه ضمن محاكاة الجهات المعادية، منها:

  • يجب أن يكون ملف DLL غير المنسَّق موجودًا على نظام الملفات.
  • يجب أن يكون ملف DLL غير المنسَّق خاليًا من أي تمويه.
  • يتم تفعيل أحداث تحميل صورة النواة (Kernel) عبر محمِّل DLL في Windows.

لذلك، فإن استخدام Windows DLL Loader لتحميل مكتبة Beacon DLL لا يُعَد حلًا مثاليًا. لتجاوز هذه التحديات، نقوم بتحميل مكتبة Beacon DLL من الذاكرة باستخدام محمِّل انعكاسي.

نقاط الكشف الثلاث الرئيسية التي يتجنّبها التحميل الانعكاسي هي:

  1. البرامج الضارة الموقَّعة المخزنة على نظام الملفات.
  2. أحداث تحميل صورة النواة، والتي يمكن أن تراقبها الحلول الأمنية.
  3. إدراج مكتبة DLL الخاصة بعنصر C2 في كتلة بيئة العملية (PEB).

Reflective Loader مقابل Windows DLL Loader

يمكن اعتبار التحميل الانعكاسي ببساطة عملية تحميل DLL غير منسقة مباشرةً من الذاكرة، بدلًا من تحميله من نظام الملفات.

كلٌّ من التحميل الانعكاسي ومُحمِّل Windows DLL Loader المدمج يخدمان الغرض نفسه، وهو تحميل مكتبة DLL من الصيغة غير المنسقة إلى مساحة الذاكرة الافتراضية للعملية. ومع ذلك، يمتلك التحميل الانعكاسي ميزة رئيسية مقارنةً بـ Windows DLL Loader، وهي أنه لا يتطلب وجود ملف DLL على نظام الملفات. يُتيح هذا التحميل من الذاكرة عددًا غير محدود من مراحل التحميل المتسلسل، إذ يمكن إخفاء DLL الخاص بعنصر C2 داخل طبقات متعددة من التشفير والترميز ضمن ذاكرة العملية.

تنسيق الملف غير المنسق مقابل تنسيق العنوان الافتراضي

من المفاهيم الأساسية لفهم عملية تحميل DLL، إدراك أن صيغة DLL تختلف عند وجودها على القرص مقارنةً بوجودها في الذاكرة. الاختلافات الرئيسية بين DLL في تنسيق الملف غير المنسق وتنسيق العناوين الافتراضية هي:

تنسيق الملف غير المنسق:

  • تنسيق ملف DLL كما هو موجود في نظام الملفات.
  • أقسام DLL متراصة بإحكام معًا.
  • الإزاحات تعتمد على بداية ملف DLL غير المنسق كما يكون موجودًا على القرص.
  • يشغل هذا التنسيق مساحة أقل من الذاكرة.

تنسيق العنوان الافتراضي:

  • تنسيق DLL كما هو موجود في مساحة الذاكرة الافتراضية لعملية ما.
  • الأقسام متباعدة.
  • الإزاحات هي عناوين افتراضية نسبية (RVA).
  • عند التشغيل في عملية، يقوم ملف DLL والوحدات الأخرى بتحديد المواقع عبر العناوين الافتراضية النسبية (RVA).
  • يشغل هذا التنسيق مساحة أكبر من الذاكرة.

الإشارة غير المنسقة مقابل الإشارة الافتراضية

عند فحص ملف DLL الخاص بإشارة HTTP باستخدام أداة PE-Bear من تطوير Aleksandra Doniec، نلاحظ الفروقات بين العناوين غير المنسَّقة والافتراضية لكل قسم من أقسام مكتبة DLL.

جدول يوضِّح العناوين غير المنسَّقة والافتراضية لكل قسم من أقسام ملف DLL للإشارة.

جدول يوضِّح العناوين غير المنسَّقة والافتراضية لكل قسم من أقسام ملف DLL للإشارة.

يبلغ حجم مكتبةDLL الخاصة بإشارة HTTP/S عند تحميلها في مساحة الذاكرة الافتراضية للعملية 0x52000  (327KB ) بايت، مقارنةً بحجمه0x44000  من وحدات البايت (272KB ) بايت كما هو موجود على نظام الملفات. يرجع الفرق في الحجم إلى أن الأقسام تكون موزعة في صيغة العناوين الافتراضية، مقارنةً بتكدسها بإحكام في صيغة الملف غير المنسق.

توفِّر أداة PE-Bear تمثيلًا بصريًا لملف DLL للإشارة كما هو موجود في تنسيق الملف غير المنسق مقابل تنسيق مساحة العناوين الافتراضية.

تمثيل مرئي لملف DLL للإشارة في التنسيق غير المنسق مقابل التنسيق الافتراضي

تمثيل مرئي لملف DLL للإشارة في التنسيق غير المنسق (يسار) مقابل التنسيق الافتراضي (يمين)

تحميل Beacon باستخدام Windows DLL Loader

رغم أن تنفيذ ذلك ليس الخيار الأكثر حكمة أثناء محاكاة خصم، فإن إسقاط ملف DLL غير منسَّق للإشارة دون أي تمويه على القرص ثم تحميله باستخدام Windows DLL Loader يُعَد وسيلةً ممتازة لفهم آلية عمل الإشارة وآلية تحميل DLL. في جوهره، برنامج Beacon ليس سوى ملف DLL. يعمل Windows DLL Loader ومحمِّل الانعكاس على تحميل ملف DLL داخل عملية.

لتحميل ملف DLL الخاص بـ Beacon باستخدام Windows DLL Loader، ننفِّذ الخطوات التالية:

  1. إنشاء ملف DLL لإشارة غير منسقة دون أي تشفير.
  2. إنشاء برنامج يقوم بما يلي:
    1. استخدام LoadLibrary واجهة برمجة التطبيقات لتحميل مكتبة beacon DLL من القرص.
    2. ينفِّذ الإشارة من خلال استدعاء نقطة الدخول في ملف DLL الافتراضي للإشارة.
  3. ضَع برنامجنا التنفيذي وملف DLL الخاص بالإشارة في نفس المجلد.
  4. نفِّذ برنامجنا.

إنشاء ملف DLL غير منسَّق للإشارة دون أي تمويه

أولًا، نقوم بتعطيل جميع خيارات Malleable PE التي تجعل ملف DLL الخاص بالإشارة غير قابل للتحميل بواسطة Windows DLL Loader. لتحقيق ذلك، نقوم بتعديل ملف تعريف Malleable C2 الخاص بنا وتعطيل خيارات مراوغة Malleable PE الموجودة ضمن كتلة stage:

تم تعديل كتلة ‎stage‎ في ملف تعريف Malleable C2 لتعطيل ميزات التهرّب في Cobalt Strike.

تم تعديل كتلة ‎stage‎ في ملف تعريف Malleable C2 لتعطيل ميزات التهرّب في Cobalt Strike.

بعد تعديل ملف التعريف، نعيد تشغيل خادم فريق Cobalt Strike مع تمريرno_evasion.profile  ملف التعريف الخاص بنا كوسيط.

لقطة شاشة مأخوذة لمنشور المدونة

نتصل بخادم الفريق مع عميل Cobalt Strike. ثم نُنشئ ملفWindows Stageless Payload  مع ضبط خيار الإخراج على Raw والمستمع على https . نحفظ الحمولة beacon.dll .

كلقطة شاشة لعملية إنشاء ملف DLL لإشارة "غير منسقة دون مرحلة" من Cobalt Strike Client.

كلقطة شاشة لعملية إنشاء ملف DLL لإشارة "غير منسقة دون مرحلة" من Cobalt Strike Client.

إنشاء برنامج Beacon DLL Loader الخاص بنا

باستخدام الكود أدناه، نُنشئ برنامجًا بلغة C باسم loadBeaconDLL.c  ثم نقوم بجمعه:

كود C لنظام Windows لتحميل ملف beacon DLL من القرص باستخدام Windows DLL Loader.

كود C لنظام Windows لتحميل ملف beacon DLL من القرص باستخدام Windows DLL Loader.

نحن نستخدم Kernel32.LoadLibraryA  واجهة برمجة التطبيقات (API) لتحميل beacon DLL من القرص. تستدعي واجهة ‎API‎ هذه Windows DLL Loader المدمج ، والذي يقوم بتحميل ملف beacon DLL من القرص إلى مساحة الذاكرة الافتراضية لعملية المضيف.

كجزء من عملية التحميل، يقوم محمل DLL في ويندوز بتهيئة ملف DLL الخاص بالإشارة من خلال استدعاء نقطة الدخول الخاصة به مع تمريرDLL_PROCESS_ATTACH (1) كوسيط.

بعد أن يقوم Windows DLL Loader بتحميل ملف beacon DLL وتهيئته داخل مساحة الذاكرة الافتراضية للعملية، سنحتاج إلى استدعاء نقطة الدخول لملف beacon DLL الافتراضي مرة أخرى مع تمرير الوسيط.0x4.

يجب أن يعرف برنامجنا نقطة الدخول لملف beacon DLL الافتراضي لتنفيذ هذا الملف. يمكن القيام بذلك بشكل ديناميكي داخل البرنامج عن طريق تحليل رؤوس ملف beacon DLL الافتراضي لاستخراج العنوان الافتراضي النسبي (RVA) لنقطة الدخول، أو يمكننا الاطلاع سريعًا على قيمته وكتابتها مباشرةً في الكود.

من أجل نموذج الإثبات لدينا، سنكتشف يدويًا ونثبت قيمة RVA لنقطة الدخول في ملف beacon DLL داخل برنامجنا. باستخدام PE-Bear، نكتشف أن العنوان الافتراضي النسبي (RVA) لنقطة الدخول في الإشارة هو 0x1D840 :

لقطة شاشة توضِّح تحديد العنوان الافتراضي النسبي (RVA) لنقطة الدخول في ملف beacon DLL باستخدام PE-Bear

لقطة شاشة توضِّح تحديد العنوان الافتراضي النسبي (RVA) لنقطة الدخول في ملف beacon DLL باستخدام PE-Bear

إن طريقة LoadLibraryA  واجهة برمجة تطبيقات تُرجع العنوان الأساسي لملف beacon DLL الافتراضي. نضيف هذه القيمة ببساطة إلى RVA لنقطة الدخول لتحديد نقطة الدخول.

بعد أن أصبح الكود الخاص بنا جاهزًا، نعمل على ترجمة برنامج C الخاص بنا إلى ملف تنفيذي لنظام Windows.

الأمر المستخدم لتجميع برنامجنا.

الأمر المستخدم لتجميع برنامجنا.

وضع برنامجنا وملف Beacon DLL على نظام الملفات

بوضع ملف Beacon DLL وبرنامج التحميل التنفيذي في نفس المجلد، سيتمكن Windows DLL Loader من اكتشاف ملف DLL أثناء تنفيذ روتين التحميل.

نحن نضع كليهما beacon.dll  و loadBeaconDLL.exe  في نظام الملفات داخل نفس الدليل:

تم وضع Beacon DLL وبرنامج المحمِّل في نفس الدليل.

تم وضع Beacon DLL وبرنامج المحمِّل في نفس الدليل.

تنفيذ برنامجنا

من سطح مكتب Windows، ننقر نقرًا مزدوجًا على برنامج loadBeaconDLL.exeونُنشئ اتصال beacon نشطًا بخادم الفريق الخاص بنا.

اتصال ناجح بخادم الفريق C2 من ملف beacon DLL بعد تحميله باستخدام Windows DLL Loader.

اتصال ناجح بخادم الفريق C2 من ملف beacon DLL بعد تحميله باستخدام Windows DLL Loader.

المحمِّل الانعكاسي في Cobalt Strike

تستخدم Cobalt Strike نسخة معدّلة من مشروع Reflective Loader الذي طوّره Stephen Fewer. يُعَد هذا محمِّل DLL الأسطوري العامل في الذاكرة قيد الاستخدام منذ أكثر من عقد، وقد استُخدم في Metasploit وغيرها من أدوات الأمن الهجومي البارزة.

اعتبارات استخدام UDRL

على مر السنين، تم تحسين المحمِّل الانعكاسي في Cobalt Strike للتعامل مع جميع ميزات التهرّب المصنوعة من Malleable PE التي تقدِّمها Cobalt Strike. العيب الرئيسي لاستخدام محمِّل انعكاسي مخصص معرَّف من قِبل المستخدم (UDRL) هو أن ميزات التهرُّب الخاصة بـ Malleable PE قد تكون مدعومة أو غير مدعومة بشكل افتراضي.

تكون بعض ميزات التهرُّب مطبَّقة بالكامل عند استخدام محمِّل انعكاسي مخصص (UDRL)، حيث يتم تضمينها داخل ملف beacon DLL بواسطة محرّك Malleable PE في Cobalt Strike أثناء إنشاء حمولة الإشارة. ومع ذلك، في الوقت الحالي يجب أن تتم معالجة ميزات مثل obfuscate بواسطة UDRL، في حين يتم التعامل مع ميزات أخرى مثل sleepmask و واجهة cleanup بواسطة beacon مع تكامل UDRL بشكل صحيح.

طرق التحميل الانعكاسي

طريقة المحمِّل الانعكاسي الأصلية

يتطلب مشروع المحمِّل الانعكاسي (Reflective Loader) الأصلي تجميع ReflectiveLoader  إلى مشروع DLL الخاص بنا وتصديره إلى مكتبة DLL الخاصة بعنصر C2.

ثم هناك مشروع آخر مسؤول عن:

  1. اكتشاف العنوان الافتراضي لتصدير ReflectiveLoader .
  2. يؤدي تنفيذ تصدير ReflectiveLoader ، والذي يُعيد نقطة الدخول إلى DLL التي تم تحميلها.
  3. استدعاء نقطة دخول DLL التي تم تحميلها انعكاسيًا.
رسم تخطيطي للمحمِّل الانعكاسي الأصلي، يقوم بتحميل ملف DLL إلى الذاكرة الافتراضية.

رسم تخطيطي للمحمِّل الانعكاسي الأصلي، يقوم بتحميل ملف DLL إلى الذاكرة الافتراضية.

إضافة طريقة التحميل الانعكاسي في البداية

هناك طريقة بديلة وهي إضافة المحمِّل الانعكاسي قبل DLL. فهذا يسمح بتحميل أي ملف DLL غير مُدار ولا يتطلب تجميع DLL من الكود المصدر. هذه طريقة تحميل انعكاسي قوية قادرة على تحميل أي ملف PE (EXE أو DLL).

مخطط يوضِّح المحمِّل الانعكاسي المضاف إلى DLL، يقوم بتحميل DLL إلى الذاكرة الافتراضية.

مخطط يوضِّح المحمِّل الانعكاسي المضاف إلى DLL، يقوم بتحميل DLL إلى الذاكرة الافتراضية.

طريقة المحمِّل الانعكاسي في Cobalt Strike

يعتمد تنفيذ التحميل الانعكاسي في Cobalt Strike على مزيج من الطريقتين المذكورتين أعلاه. قد تكون طريقة التحميل الانعكاسي هذه مألوفة لمن لديهم معرفة بكيفية تنفيذ Meterpreter في Metasploit لآلية التحميل الانعكاسي.

على غرار طريقة المحمِّل الانعكاسي الأصلي، يتم تجميع وظيفة ReflectiveLoader  وتصديرها في beacon DLL الأصلي. عندما يُنشئ المشغِّل حمولة beacon من عميل Cobalt Strike، تقوم وحدة Malleable PE في Cobalt Strike بترقيع ملف beacon DLL غير المنسق لإبلاغ المحمِّل الانعكاسي بخيارات Malleable PE الواجب استخدامها. يتم تعديل رأس DOS الخاص بـ Beacon لاستدعاء تصدير ReflectiveLoader عند إزاحة ثابتة مبرمجة مسبقًا. سيُشار في هذه المدونة إلى البايتات الأولية التي تم تعديلها في رأس DOS الخاص بـ beacon، والتي تستدعي وظيفة التصدير ReflectiveLoader ، باسم مقطع استدعاء المحمِّل الانعكاسي.

عند تحميل UDRL داخل Cobalt Strike، وعندما يقوم المشغِّل بإنشاء حمولة beacon من عميل Cobalt Strike، يقوم محرّك Malleable PE في Cobalt Strike بترقيع كود shellcode الخاص بالمحمِّل الانعكاسي عند إزاحة الملف غير المنسق لتصدير ReflectiveLoader  .

عند اكتمال قيام محرّك Malleable PE بتعديل ملف beacon DLL غير المنسق، يتم تسليم ملف beacon DLL غير المنسق إلى المشغِّل بصيغة تنفيذية شبيهة بـ shellcode.

مخطط يوضِّح المحمِّل الانعكاسي في Cobalt Strike أثناء تحميل beacon DLL إلى الذاكرة الافتراضية.

مخطط يوضِّح المحمِّل الانعكاسي في Cobalt Strike أثناء تحميل beacon DLL إلى الذاكرة الافتراضية.

مقطع استدعاء المحمِّل الانعكاسي الخاص بـ Beacon.

عند فحص البايتات الأولية باستخدام أداة التفكيك PE‑Bear، يمكننا ملاحظة أن beacon DLL قابل للتنفيذ بحد ذاته:

يظهر مقطع استدعاء المحمِّل الانعكاسي على هيئة أكواد عمليات تجميعية قابلة للتنفيذ.

يظهر مقطع استدعاء المحمِّل الانعكاسي على هيئة أكواد عمليات تجميعية قابلة للتنفيذ.

وحدات البايت الأولية MZAR  قابلة للتخصيص من خلال خيارات Malleable PE في الملف التعريفي لـ Cobalt Striacks C2. يجب أن تكون هذه البايتات قابلة للتنفيذ وتؤدي إلى عدم وجود عملية (nop ).

بعد تنفيذ الكود المضاف اختياريًا nops  والبايتات السحرية، يقوم مقطع استدعاء المحمِّل الانعكاسي بما يلي:

  • إنشاء إطار للمجموعة.
  • استخدام عنونة نسبية إلى RIP لتحديد العنوان الأساسي لملف beacon DLL غير المنسق.
  • استدعاء تصدير ReflectiveLoader  عند إزاحة0x16E3C  الملف غير المنسق المعروفة.
  • يستدعي نقطة دخول ملف beacon DLL.

نؤكِّد أن إزاحة الملف غير المنسق الخاصة بتصديرReflectiveLoader  هي 0x16E3C  من خلال النظر في دليل تصدير ملفات beacon DLL:

لقطة شاشة تُظهر استخدام PE‑Bear لتحديد إزاحة الملف غير المنسق لعنصر التصدير ReflectiveLoader.

لقطة شاشة تُظهر استخدام PE‑Bear لتحديد إزاحة الملف غير المنسق لعنصر التصدير ReflectiveLoader.

كما هو موجود ضمن دليل التصدير، يكون عنوان عنصر التصديرReflectiveLoader بتنسيق RVA، مشيرًا إلى beacon DLL في حالته الافتراضية. وبما أن ملف تصدير ReflectiveLoader  قابل للتنفيذ، نعلم أنه موجود ضمن قسم .text الخاص بـ beacon DLL.

لاكتشاف ملف الإزاحة غير المنسق لتصدير ReflectiveLoader ، نحتاج أولًا إلى معرفة الفرق بين .text  العناوين الافتراضية والعنوان. مع الفِرق المعروف، يمكننا ببساطة طرحه من تصدير ReflectiveLoader  الخاصة بـ RVA، لاكتشاف تصدير ReflectiveLoader  الملف غير المنسق.

إن العناوين الافتراضية وغير المنسقة .text  للقسم يتم سرد القسم داخل رؤوس أقسام beacon DLL:

عناوين أولية وافتراضية لنصوص الخاص بـ beacon DLL.

عناوين أولية وافتراضية لنصوص الخاص بـ beacon DLL.

الفرق بين الاثنين هو 0xC00  من البايتات. عن طريق طرح RVA ReflectiveLoader  لتصدير 0x17A3C  بقيمة الفرق، نكتشف أن إزاحة الملف غير المنسق هي 0x16E3C .

يمكننا تأكيد ذلك في PE‑Bear عن طريق النقر بزر الماوس الأيمن على Function RVA الخاص بوظيفة ReflectiveLoader  ثم النقر على Follow RVA:17A3C . سينتقل عارض القيم السداسية في الأداة أعلاه لعرض وظيفةReflectiveLoader  عند إزاحة الملف غير المنسق الخاصة به.

باختصار، يكون تسلسل عملية التحميل الانعكاسي في Cobalt Strike على النحو التالي:

  • يقوم المسار بتنفيذ beacon DLL غير المنسق.
  • يقوم مقطع استدعاء المحمِّل الانعكاسي باستدعاء وظيفةReflectiveLoader  عند إزاحة ملف غير منسق معروفة.
  • يقوم المحمِّل الانعكاسي بتحميل beacon DLL غير المنسق إلى الذاكرة الافتراضية للعملية المضيفة.
  • بعد التحميل، يعيد المحمِّل الانعكاسي نقطة دخول beacon DLL الافتراضي إلى مقطع استدعاء المحمِّل الانعكاسي.
  • يقوم مقطع استدعاء المحمِّل الانعكاسي باستدعاء نقطة دخول ملف beacon DLL الافتراضي.
مخطط يوضِّح المراحل الرئيسية لكيفية تنفيذ Cobalt Strike لعملية التحميل الانعكاسي لملف beacon DLL.

مخطط يوضِّح المراحل الرئيسية لكيفية تنفيذ Cobalt Strike لعملية التحميل الانعكاسي لملف beacon DLL.

متطلبات تصميم المحمِّل الانعكاسي

كود مستقل عن الموقع

نظرًا لأن المحمِّل الانعكاسي يتم تنفيذه قبل تحميل beacon DLL، يجب أن يكون كود المحمِّل الانعكاسي كود shellcode خالصًا.

أسهل طريقة لإنشاء shellcode معقد هي كتابته بلغة C دون أي تبعيات خارجية. ثم يتم تحويل ملف C إلى ملف كائن. يجب تضمين كل شيء في قسم text من ملف الكائن. وأخيرًا، نقوم باستخراج قسم.text للحصول على كود المحمِّل الانعكاسي من نوع shellcode.

كيف تعمل Cobalt Strike على إدراج UDRL الخاص بنا

سيتولى محرّك Malleable PE في Cobalt Strike مهمة استخراج كود shellcode من ملف الكائن الخاص بالمحمِّل الانعكاسي لدينا، ثم تعديلها داخل beacon DLL غير المنسق عند إزاحة الملف غير المنسق للوظيفةReflectiveLoader . يتم تنفيذ ذلك في نص Aggressor الخاص بـ UDRL كما هو موضَّح أدناه:

نص Aggressor لكتابة كود المحمِّل الانعكاسي (shellcode) داخل beacon DLL غير المنسق باستخدام Cobalt Strike.

نص Aggressor لكتابة كود المحمِّل الانعكاسي (shellcode) داخل beacon DLL غير المنسق باستخدام Cobalt Strike.

يقوم نص Aggressor الخاص بـ UDRL لدينا بجعل Cobalt Strike يكتب كود المحمِّل الانعكاسي (shellcode) من خلال تنفيذ الخطوات التالية:

  • نفتح$handle إلى ملف كائن UDRL الخاص بنا الذي يحتوي علىopenf للمؤسسة تقريبًا.
  • مع الملف$handle نقرأ تدفق البايت ونحفظه في$data متغير مصفوفة البايت.
  • ثم نغلق الملف$handle باستخدامclosef للمؤسسة تقريبًا.
  • تعمل
    <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 من مصفوفة البايت$data ، حدد موقع القسم.text من ملف كائن UDRC، واستخرج قسم .text‎ ثم احفظه في$loader متغير مصفوفة البايت.
  • تعمل
    <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 لاكتشاف موضع الإزاحة في الملف غير المنسق لوظيفةReflectiveLoader ثم دمج كود UDRL shellcode الخاص بنا من$loader متغير مصفوفة البايت.
  • أخيرًا، نُعيد ملف beacon DLL بعد تعديله إلى Cobalt Strike، ونحفظ الملف من جهة العميل.

مراحل التحميل الانعكاسي

يتولى Cobalt Strike تنفيذ العمل نيابةً عنا فيما يخص استخراج قسم .text من ملف كائن المحمِّل الانعكاسي، ودمج كود shellcode الخاص بنا، ثم استدعاء المحمِّل الانعكاسي عبر مقطع استدعاء المحمِّل الانعكاسي الموجود في ترويسة ملف beacon DLL.

هذه هي المراحل التي يجب تطويرها لتنفيذ التحميل الانعكاسي لـ beacon:

  1. البحث عن Beacon DLL غير منسقة.
  2. تحليل رؤوس Beacon DLL.
  3. تخصيص الذاكرة لملف Beacon DLL الافتراضي.
  4. تحميل الأقسام إلى مساحة الذاكرة الافتراضية.
  5. تحميل تبعيات DLL.
  6. حل جدول عناوين الاستيراد.
  7. حل عمليات إعادة التمركز.
  8. تنفيذ Beacon.

المرحلة الأولى: العثور على العنوان الأساسي لملف Beacon DLL غير المنسق.

هناك عدة طرق مختلفة يمكننا استخدامها لاكتشاف العنوان الخاص بملف beacon DLL غير المنسق في الذاكرة. وتتضمن هذه الطرق ما يلي:

  • البحث للخلف عن رؤوس MZ وPE.
  • البحث للخلف عن علامة Egg.
  • استخراج العنوان الأساسي لملف beacon DLL الخام من مقطع مستدعي المحمِّل الانعكاسي.

تحديد موضعنا في الذاكرة

عند استخدام أسلوب يعتمد على البحث للخلف، نحتاج أولًا إلى الحصول على العنوان الحالي لمؤشر التعليمات الخاص بمسار التنفيذ لدينا (RIP ). يمكننا استخدام هذه الحيلة البسيطة من أجل getRip :

  1. في UDRC الخاص بنا، أنشأنا دالة تُعرَف باسم getRip .
  2. نستدعي getRip  والتي ستقوم بدفع العنوان الذي يلي "call getRip " إلى أعلى المجموعة. هذا هو عنوان الإرجاع.
  3. ثم في وظيفة getRip  ، نحن ببساطة ننسخ عنوان إرجاع المتصل من أعلى المجموعة.
  4. في برمجة لغة C لنظام التشغيل Windows x64، يمكن للدوال أن تُرجع قيمة. تُعاد هذه القيمة إلى المُستدعي من خلال سجل RAX . عن طريق نقل عنوان الإرجاع الخاص بالمتصل إلى سجل RAX ، نقوم بإعادة عنوان الإرجاع الخاص بالمتصل إلى المتصل.
كود تجميع Intel x64 لاستخراج العنوان الأساسي لملف beacon DLL غير المنسق من السجل RDI.

كود تجميع Intel x64 لاستخراج العنوان الأساسي لملف beacon DLL غير المنسق من السجل RDI.

البحث للخلف عن رؤوس MZ وPE

يعتمد مشروع المحمِّل الانعكاسي الأصلي على البحث للخلف عن رؤوس MZ وPE. وقد أصبحت هذه الرؤوس نقاط كشف. ولمعالجة ذلك، أضافت Cobalt Strike magic_mz  و magic_pe  ميزات التخفي في Malleable PE.

توضِّح وثائق Cobalt Strike أن خيار magic_mz :

  • "تجاوز البايتات الأولى من Reflective DLL الخاصة بـ Beacon، بما في ذلك رأس MZ. يجب استخدام تعليمات صالحة، مع التأكد من أن أي تعليمة تغيِّر حالة وحدة المعالجة المركزية تتبعها تعليمة أخرى تعيد الحالة إلى وضعها السابق".

عند التكوين، تكوين بايتات MZ--  عند إزاحة الملف غير المنسق 0x00  و PE00  عند إزاحة الملف غير المنسق 0x80  معروفة للمحمِّل الانعكاسي. يتم إدخالها في ملف beacon DLL بواسطة محرك Malleable PE.

يجب أن تكون هذه البايتات فريدة من نوعها إلى حد ما، وإلا فلن يتمكن المحمِّل الانعكاسي من العثور عليها. بالإضافة إلى ذلك، يجب أن تكون وحدات البايت الخاصة برأس MZ عمليات غير قابلة للتشغيل والتنفيذ. لا يمكن أن تكون قيمًا مثل 0x00  أو قد تتعطل الإشارة. قد تكون هذه نقطة كشف محتملة.

الصيد العكسي بحثًا عن المؤشر

بعد اكتشاف نقطة الكشف المحتملة هذه، قمت بتطوير طريقة مختلفة لكنها متشابهة لتحديد عنوان الأساس لملف beacon DLL غير المنسق. تستخدم هذه الطريقة آلية بحث قادرة على المسح العكسي من RIP ، حيث تبحث عن تكرارين متطابقين لقيمة فريدة بطول 64 بت عند beacon.dll+0x50  الإزاحة غير المنسقة المعروفة للملف.

تم اختيار العنوان beacon.dll+0x50 لأنه موقع عبارة "This program cannot be run in DOS mode"، وهي عبارة غير مطلوبة عند تحميل beacon بشكل انعكاسي.

نظرًا لعدم توفر وصول سهل إلى محرك Java Malleable PE،BokuLoader.cna  يمكن استخدام سكربت UDRL Aggressor لكتابة 0xB0C0ACDC  قيمة التعريف داخل beacon. يوضِّح الكود أدناه كيفية تعديل ملف beacon DLL غير المنسق ليتضمن قيمة التعريف:

سكربت Aggressor لكتابة قيمة التعريف داخل ملف beacon DLL غير المنسق وعرض التغييرات في وحدة تحكم سكربت Cobalt Strike.

سكربت Aggressor لكتابة قيمة التعريف داخل ملف beacon DLL غير المنسق وعرض التغييرات في وحدة تحكم سكربت Cobalt Strike.

يجب أن يكون كود UDRL على علم بقيمة التعريف التي يكتبها سكربت UDRL داخل ملف beacon DLL غير المنسق. بعد تحديد قيمة التعريف، تقوم آلية البحث بالمسح العكسي للعثور على تكرارين من هذه القيمة، كما هو موضَّح في الكود أدناه:

رمز تجميع Intel x64 لأداة صيد قيم التعريف التي تبحث عن مثيلين لقيمة 64 بت.

رمز تجميع Intel x64 لأداة صيد قيم التعريف التي تبحث عن مثيلين لقيمة 64 بت.

  • يمكن تعديل كلٍ من سكربت UDRL Aggressor وكود UDRL بلغة C لاستخدام قيم مختلفة.

الآن، وبما أن ترويسات MZ وPE لم تَعُد قيد الاستخدام، يمكن استبدالها بتعليمات NOP داخل سكربت UDRL Aggressor:

سكربت Aggressor لتمويه ترويسات MZ وPE والبايتات غير المستخدمة في لافتة DOS داخل ترويسات beacon DLL غير المنسق.

سكربت Aggressor لتمويه ترويسات MZ وPE والبايتات غير المستخدمة في لافتة DOS داخل ترويسات beacon DLL غير المنسق.

استخراج عنوان الأساس لملف Beacon DLL غير المنسق من مقطع Call Reflective Loader

توجد أيضًا طريقة أخرى خاصة بأداة Cobalt Strike لاكتشاف عنوان الأساس لملف beacon DLL غير المنسق. كما رأينا أعلاه، تقوم البايتات الأولية في مقطع Call Reflective Loader بتخزين عنوان الأساس لملف beacon DLL غير المنسق في سجلRDI  قبل استدعاء المحمِّل الانعكاسي. وبدلًا من الصيد العكسي من RIP لبعض القيم، يمكننا ببساطة الحصول على القيمة من سجل RDI  في بداية كود المحمِّل الانعكاسي الخاص بنا.

لفحص هذا الأمر بشكل أكبر في مصحح الأخطاء، نعمل على إنشاء إشارة، نضيف إليها نقطة توقف مسبقًا (0xCC )، ونفتح الإشارة في x64dbg. نظرًا لإضافة نقطة التوقف في بداية المقطع، يكون عنوان الأساس لـ beacon غير المنسق عند+1  من الذاكرة المخصصة. كما رأينا أعلاه، يستخدم مقطع Call Reflective LoaderRIP العنونة النسبية لاستخراج عنوان الأساس لملف beacon DLL غير المنسق:

لقطة شاشة من X64dbg أثناء التنقل خطوة بخطوة عبر مقطع Call Reflective Loader، توضِّح أن عنوان الأساس لملف beacon DLL غير المنسق محفوظ في سجل RDI قبل استدعاء المحمِّل الانعكاسي.

لقطة شاشة من X64dbg أثناء التنقل خطوة بخطوة عبر مقطع Call Reflective Loader، توضِّح أن عنوان الأساس لملف beacon DLL غير المنسق محفوظ في سجل RDI قبل استدعاء المحمِّل الانعكاسي.

فيما يلي مثال عملي يوضِّح كيفية الحصول على عنوان الأساس لملف beacon DLL غير المنسق من مقطع Call Reflective Loader:

كود C باستخدام التجميع المضمن (Inline Assembly) للحصول على عنوان الأساس لملف beacon DLL غير المنسق من سجل RDI.

كود C باستخدام التجميع المضمن (Inline Assembly) للحصول على عنوان الأساس لملف beacon DLL غير المنسق من سجل RDI.

المرحلة الثانية: تحليل ترويسات ملف Beacon DLL

بعد الحصول على عنوان الأساس لملف beacon DLL غير المنسق، يمكننا الآن استخراج القيم اللازمة لتحميل beacon في مساحة العناوين الافتراضية للعملية.

يوضِّح الجدول أدناه القيم التي نحتاجها من ترويسات ملف beacon DLL غير المنسق، ومواقع وجودها، وأنواعها:

جدول يسرد القيم المستخرجة من ترويسة ملف beacon DLL غير المنسق والتي تُستخدم لتحميل ملف beacon DLL.

جدول يسرد القيم المستخرجة من ترويسة ملف beacon DLL غير المنسق والتي تُستخدم لتحميل ملف beacon DLL.

التخفي

ليست كل محتويات الترويسات مطلوبة لتحميل ملف beacon DLL. يمكن إعادة تعبئة القيم المطلوبة أو إخفاؤها. يمكن إزالة القيم غير المطلوبة أو توزيعها بشكل عشوائي.

المرحلة 3: تخصيص الذاكرة للإشارة الافتراضية

بمجرد معرفةSizeOfImagef الحجم من ترويسة ملف beacon DLL غير المنسق، نحتاج إلى تخصيص ذاكرة بهذا الحجم. ستحتوي مساحة الذاكرة هذه على ملف beacon DLL الافتراضي الخاص بنا.

يمكن استخدام طرق مختلفة لتخصيص الذاكرة لملف beacon DLL الافتراضي. ستستخدم الطرق المختلفة أنواعًا مختلفة من الذاكرة. الطرق المختلفة التي يدعمها محمِّل Cobalt Strike الانعكاسي الافتراضي هي:

جدول يوضِّح خيارات تخصيص الذاكرة في Cobalt Strike لملف beacon DLL الافتراضي.

جدول يوضِّح خيارات تخصيص الذاكرة في Cobalt Strike لملف beacon DLL الافتراضي.

التخفي

ويمكن اتخاذ خطوة أخرى إلى الأمام باستخدام UDR. يمكن استخدام إصدار NTAPI من هذه الوظائف بدلًا من ذلك. بالإضافة إلى ذلك، يمكن استدعاء وظائف NTAPI عبر استدعاءات نظام مباشرة أو غير مباشرة، وهو ما قد يساهم أو لا يساهم في تعزيز قدرات التخفي.

عند تعيين أسلوب تخصيص الذاكرة على VirtualAlloc  في ملف تعريف Cobalt Strike Malleable C2، سيستخدم مشروع BokuLoader حاليًا استدعاءً مباشرًا للنظام إلى NtAllocateVirtualMemory  لتخصيص الذاكرة لملف beacon DLL الافتراضي:

مثال كود من مشروع BokuLoader يوضِّح استخدام نداء نظام مباشر لتخصيص الذاكرة الخاصة بملف beacon DLL الافتراضي.

مثال كود من مشروع BokuLoader يوضِّح استخدام نداء نظام مباشر لتخصيص الذاكرة الخاصة بملف beacon DLL الافتراضي.

  • يتم اكتشاف رقم نداء النظام باستخدام أسلوب HellsGate.
  • في حال وجود رابط (hook) على مستوى userland ضمن مقطع استدعاء النظام، يتم استخدام أسلوب HalosGate.

توضِّح الصورة أدناه مثال كود يوضِّح كيفية استخدام أسلوبَي HellsGate وHalosGate لتحديد أرقام استدعاءات النظام:

مثال كود من مشروع BokuLoader يوضِّح كيفية اكتشاف استدعاءات النظام من العملية.

مثال كود من مشروع BokuLoader يوضِّح كيفية اكتشاف استدعاءات النظام من العملية.

المرحلة الرابعة: تحميل الأقسام إلى مساحة الذاكرة الافتراضية

بعد أن قمنا بتخصيص الذاكرة ملف beacon DLL الافتراضي، نحتاج إلى نسخ أقسام beacon من إزاحاتها غير المنسقة في الملف، كما هي موجودة في ملف beacon DLL غير المنسق، إلى الذاكرة المخصّصة عند إزاحاتها الافتراضية النسبية.

إذا خصصنا ذاكرتنا باستخدامREADWRITE سنحتاج إلى تتبُّع عنوان قسم .text وحجمه. قبل استدعاء نقطة الدخول إلى beacon DLL الافتراضي، سنحتاج إلى تغيير حماية الذاكرة في قسم .text إلى قابل للتنفيذ.

تخصيص ذاكرتنا باستخدام READWRITE_EXECUTE يجعل عملية التحميل الانعكاسي أسهل ولكنه يزيد من فرص الكشف بواسطة الحلول الأمنية.

فيما يلي مثال كود مبسَّط من مشروع BokuLoader يوضِّح ذلك:

مثال كود من مشروع BokuLoader يوضِّح نسخ الأقسام من ملف beacon DLL غير المنسق إلى ملف beacon DLL الافتراضي.

مثال كود من مشروع BokuLoader يوضِّح نسخ الأقسام من ملف beacon DLL غير المنسق إلى ملف beacon DLL الافتراضي.

التخفي

تتضمن بعض ميزات التخفي المتعلقة بتحميل الأقسام ما يلي:

  • عدم نسخ ترويسات beacon إلى ملف beacon DLL الافتراضي.
  • تحرير مساحة الذاكرة في ملف beacon DLL الافتراضي التي كانت ستحتوي على الترويسات.

في مشروع BokuLoader العام، لا يتم نسخ ترويسات ملف beacon DLL من الملف غير المنسق إلى ملف beacon DLL الافتراضي. حاليًا، البايتات الأولى 0x1000  من ملف beacon DLL الافتراضي كلها قيم صفرية (.0x00‘s ). من خلال الاختبار الذي أجريته، لا يعتمد beacon على ترويساته بعد أن يتم تحميله بشكل صحيح في الذاكرة الافتراضية. قد يساعد تجنُّب نسخ الترويسات على تفادي أدوات الفحص داخل الذاكرة، إلا إن هذه البايتات الصفرية قد تشكِّل أيضًا نقطة كشف محتملة.

فرصة تفادٍ محتملة أخرى تتمثل في قيام سكربت UDRL Aggressor بتشفير الأقسام. يمكن فك تشفير الأقسام في الذاكرة بواسطة UDRL باستخدام مفتاح مشترك بين UDRL وسكربت UDRL Aggressor.

المرحلة الخامسة: تحميل تبعيات DLL

تعتمد إشارة x64 HTTP/S على أربعة ملفات DLL لتعمل بشكل صحيح. إذا لم تكن ملفات DLL هذه محملة حاليًا في المعالجة، فسيتعين على أداة التحميل الانعكاسي تحميلها.

تم إدراج ملفات DLL الأربعة في دليل استيراد ملف DLL الخاص بإشارة HTTP/S:

لقطة شاشة من PE-Bear تعرض ملفات DLL من دليل استيراد ملفات beacon DLL.

لقطة شاشة من 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 المحمَّلة في العملية ومعلوماتها ذات الصلة (

InMemoryOrderModuleList

). يعمل BokuLoader على الاستفادة من ذلك لاكتشاف معلومات DLL، وتجنُّب استدعاءات واجهة برمجة التطبيقات غير الضرورية.

في حالة عدم وجود ملف DLL في InMemoryOrderModuleList ، يستخدم BokuLoader حاليًا واجهة برمجة التطبيقات NTDLL.LdrLoadDll  لتحميل تبعية DLL في الذاكرة، بالاستفادة من أداة Windows DLL Loader المدمجة.

لا يمكن استخدام التحميل الانعكاسي المتداخل بسهولة لتحميل تبعيات DLL لأن المحمِّلات الانعكاسية لا تقوم عمومًا بتسجيل DLL في العملية. لا يمكن للتعليمات البرمجية الخارجية لملف DLL استخدام ملف DLL المحمَّل بشكل انعكاسي بشكل صحيح. قد يكون مشروع DarkLoadLibrary قادرًا على تحميل ملف DLL بشكل صحيح في الذاكرة دون تشغيل حدث تحميل صورة النواة.

نموذج كود من مشروع BokuLoader يوضِّح كيفية حل عناوين DLL الأساسية المحمَّلة عن طريق استعراض InMemoryOrderModuleList.

نموذج كود من مشروع BokuLoader يوضِّح كيفية حل عناوين DLL الأساسية المحمَّلة عن طريق استعراض InMemoryOrderModuleList.

المرحلة 6: حل جدول عناوين الاستيراد

بعد تحميل ملفات DLL المطلوبة في العملية، يجب حل واجهات برمجة التطبيقات المدرجة في دليل الاستيراد. بعد ذلك، يجب كتابة عناوين واجهة برمجة التطبيقات (API) إلى جدول عناوين الاستيراد (IAT) الخاص بمكتبة beacon DLL الافتراضية. وبهذه الطريقة، يعرف جهاز الإرسال العنوان الذي يجب الانتقال إليه عند الحاجة إلى استدعاء واجهات برمجة التطبيقات مثل WININET.HttpSendRequest

يجب حل إدخال الاستيراد عن طريق السلسلة الترتيبية أو سلسلة الاسم.

في الصورة أدناه، نرى أن مكتبة Cobalt Strike beacon DLL تستخدم مزيجًا من الأرقام الترتيبية وسلاسل الأسماء لإدخالات الاستيراد:

لقطة شاشة من PE-Bear توضِّح أن بعض إدخالات الاستيراد لملف beacon DLL يجب حلها حسب الترتيب.

لقطة شاشة من PE-Bear توضِّح أن بعض إدخالات الاستيراد لملف beacon DLL يجب حلها حسب الترتيب.

يستخدم نظام المحمِّل الانعكاسي المدمج في Cobalt Strike واجهة برمجة التطبيقات Kernel32.GetProcAddress  لحل العناوين الافتراضية لإدخالات الاستيراد.

التخفي

تتضمن بعض أساليب التهرب لحل عناوين واجهة برمجة التطبيقات ما يلي:

  • تطبيقات الكود المخصصة لـ GetProcAddress
  • NTDLL.LdrGetProcedureAddress

يستخدم BokuLoader تنفيذ رمز مخصص لـGetProcAddress لحل عنوان إدخال الاستيراد، ومعالجة كلٍّ من سلاسل الأسماء والترتيبات.

ثم يتم استبدال NTDLL.LdrGetProcedureAddress قادر على التعامل مع كلٍّ من سلاسل الأسماء والترتيبات أيضًا. إذا كان العنوان المُعاد لإدخال الاستيراد عبارة عن مُعيد توجيه إلى ملف DLL آخر، فإن BokuLoader يستخدم NTDLL.LdrGetProcedureAddress افتراضيًا لحل مُعيد التوجيه.

أثناء كتابة جدول ربط التطبيقات (IAT)، يمكن تنفيذ الربط عن طريق كتابة العناوين الافتراضية لوظائف الربط التي قمنا بتنفيذها بدلًا من العنوان الافتراضي لواجهات برمجة التطبيقات المقصودة. طالما يتم إرجاع المخرجات المتوقعة إلى جهاز الإرسال (beacon) عند استدعاء العنوان الموجود في جدول عناوين الإدخال، يمكننا تنفيذ تعليمات برمجية إضافية قبل العودة إلى جهاز الإرسال. ستوضِّح المنشورات المستقبلية والإصدارات العامة لبرنامج BokuLoader كيف يمكننا الاستفادة من ربط IAT للحصول على ميزات التهرب المتقدمة.

مع إصدار حديث، يدعم مشروع BokuLoader العام obfuscate ميزة PE قابلة للتشكيل من ملف Cobalt Strike C2 مع تنفيذ مخصص. عن طريق تعديل مفتاح الإخفاء في نصBokuLoader.cna UDRL Aggressor، يمكن تحسين التعتيم عن طريق اختيار مفتاح XOR أحادي البايت الخاص بك.

فيما يتعلق بالأمن التشغيلي، من المهم معرفة أن محركات مطابقة الأنماط قادرة على استخدام القوة الغاشمة لاختراق أقنعة XOR أحادية البايت. ستوضِّح المنشورات المستقبلية كيف يمكننا إنشاء محرك PE قابل للتعديل خاص بنا باستخدام وظائف البرمجة النصية لـ Cobalt Strikes Aggressor لإخفاء الإشارات للتغلب على مطابقة الأنماط.

المرحلة 7: حل عمليات النقل

يحتوي ملف DLL الخاص بالمنارة على العديد من عمليات النقل التي يجب حلها وكتابتها في جدول النقل الأساسي لملف beacon DLL الافتراضي قبل تنفيذه.

في PE-Bear، يمكننا أن نرى أن ملف beacon DLL يحتوي افتراضيًا على عنوان قاعدة الصورة التالي: 0x180000000 :

لقطة شاشة من PE-Bear تُظهر العنوان الأساسي لصورة beacon DLL.

لقطة شاشة من PE-Bear تُظهر العنوان الأساسي لصورة beacon DLL.

قبل أن نبدأ في كتابة عمليات النقل، نحتاج إلى حساب الفرق بين العنوان الأساسي لملف beacon DLL الافتراضي والعنوان الأساسي المضمَّن في الكود.

على سبيل المثال، لنفترض أن العنوان الأساسي لملف beacon DLL الافتراضي هو 0x7FFC44FE0000 . نطرح عنوان القاعدة المضمَّن في الكود من عنوان القاعدة الخاص بملف DLL الخاص بـ beacon DLL الافتراضي للحصول على فرق عنوان الأساس:

لقطة شاشة توضِّح تغيير عنوان القاعدة

بعد ذلك، لتحديد العنوان الافتراضي لكل إدخال نقل في جدول النقل الأساسي، نضيف دلتا العنوان الأساسي إلى عنوان إدخال النقل المشفر لتحديد النقل داخل ملف beacon DLL الافتراضي الخاص بنا.

في الصورة أدناه، يمكننا أن نرى أن إدخالات إعادة توجيه الإشارات مكتوبة بشكل معكوس بتنسيق little-endian:

لقطة شاشة من PE-Bear تُظهر وجود بعض إدخالات النقل بتنسيق little-endian.

لقطة شاشة من PE-Bear تُظهر وجود بعض إدخالات النقل بتنسيق little-endian.

العنوان الثابت لإدخال النقل هذا هو 0x1800341C8 .

نضيف هذا العنوان إلى دلتا العنوان الأساسي، للحصول على العنوان الافتراضي لإعادة التوجيه كما هو موجود في beacon DLL الافتراضي:

لقطة شاشة توضِّح إضافة العنوان إلى دلتا العنوان الأساسي، للحصول على العنوان الافتراضي لإعادة التوجيه كما هو موجود في 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 قابل للقراءة البشرية، وذلك لمساعدة الآخرين الذين يريدون معرفة التفاصيل التقنية لكيفية القيام بذلك.

المرحلة 8: تنفيذ Beacon

يمكن تقسيم عملية تنفيذ Beacon إلى ثلاث خطوات:

  • التأكد من أن أقسام beacon DLL الافتراضي لديها أذونات الذاكرة الصحيحة.
  • تهيئة beacon DLL الافتراضي.
  • استدعاء نقطة دخول beacon DLL الافتراضي.

جَعْل برنامج Virtual Beacon قابلًا للتنفيذ

إذا كانت الذاكرة التي خصصناها من أجل beacon DLL الافتراضي هي READWRITE_EXECUTE ، لسنا بحاجة إلى تغيير وسائل حماية الذاكرة حتى تعمل لدينا وظيفة beacon بشكل صحيح دون تعطُّل.

إذا خصصنا ذاكرة beacon الافتراضية الخاصة بنا على أنها غير قابلة للتنفيذ (READWRITE )، سنحتاج إلى تغيير قسم .text  beacon DLL الافتراضي إلى قابل للتنفيذ. يجب أن يكون قد تم حفظ الموقع والحجم الافتراضي لقسم .text  مسبقًا داخل دالة UDR الرئيسية كمتغيرات.

في مشروع BokuLoader العام، يتم إجراء تغييرات حماية الذاكرة عن طريق استدعاءات النظام المباشرة إلى NTProtectVirtualMemory ، كما هو موضَّح في مثال التعليمات البرمجية أدناه:

نموذج التعليمات البرمجية من مشروع BokuLoader يوضِّح تغيير قسم .text من ملف beacon DLL الافتراضي إلى ملف قابل للتنفيذ.

نموذج التعليمات البرمجية من مشروع BokuLoader يوضِّح تغيير قسم .text من ملف beacon DLL الافتراضي إلى ملف قابل للتنفيذ.

تخزِّن .data  من beacon DLL الافتراضي الخاص بنا، يجب أن تتوفر الأذونات READWRITE . إذا كان القسم غير قابل للكتابة، فقد يتعطل beacon DLL أثناء التنفيذ.

تهيئة Beacon DLL الافتراضي

لكي يعمل ملف beacon DLL الافتراضي بشكل صحيح، يجب أولًا تهيئته عن طريق استدعاء نقطة دخول ملف beacon DLL الافتراضي. الوسيط الأول هو العنوان الأساسي لملف beacon DLL الافتراضي. الوسيط الثاني هو fwdReason  ويجب ضبطه على DLL_PROCESS_ATTACH (1) .

نموذج كود من مشروع BokuLoader يقوم بتهيئة beacon DLL الافتراضي.

نموذج كود من مشروع BokuLoader يقوم بتهيئة beacon DLL الافتراضي.

تنفيذ Beacon DLL الافتراضي

بعد تهيئة beacon DLL الافتراضي، يمكننا إعادة نقطة دخول المنارة الافتراضية إلى دالة التحميل الانعكاسي، أو يمكننا استدعاء نقطة دخول beacon DLL الافتراضي في ملف تعريف المستخدم الموحَّد (UDRL) الخاص بنا باستخدامfwdReason  مع ضبطه على 0x4 .

على عكس ملف DLL النموذجي حيث يكون الوسيط الأول hinstDLL  إلى 

<a href="https://learn.microsoft.com/qa-ar/windows/win32/dlls/dllmain">DLLMAIN</a>

العنوان الأساسي لملف DLL الافتراضي، بينما يتوقع beacon العنوان الأساسي لملف DLL غير المنسق. في حال عدم توفير ذلك، قد تفشل بعض ميزات التهرب في Malleable PE.

مثال برمجي من مشروع BokuLoader يوضِّح طريقتين مختلفتين لتنفيذ ملف beacon DLL الافتراضي.

مثال برمجي من مشروع BokuLoader يوضِّح طريقتين مختلفتين لتنفيذ ملف beacon DLL الافتراضي.

الأفكار الختامية

نأمل أن يساعد منشور المدونة هذا كلًّا من الفرق الحمراء والزرقاء على فهم أفضل لـ Cobalt Strike وعملية التحميل الانعكاسي. لا يزال هناك الكثير من فرص التهرب التي يمكن تنفيذها من خلال التحميل الانعكاسي. من خلال فهم أعمق لهذه المفاهيم، يمكن المؤسسات أن تُعِد نفسها بشكل أفضل للدفاع الناجح ضد التهديدات الإلكترونية.

ستركِّز المقالات القادمة في هذه السلسلة على دمج UDRL مع ميزات التخفي الحالية في Cobalt Strike، والتعمّق في ميزات التخفي غير الموثّقة الموجودة بالفعل في الإصدار العام من BokuLoader، إضافةً إلى ميزات متقدمة لم يتم طرحها للعامة بعد. ترقَّب المزيد من المعلومات المتعمقة والتقنيات المتقدمة للتعرُّف على كيفية الارتقاء باستخدام Cobalt Strike إلى مستوى أكثر تقدمًا من خلال تطوير UDRL.

Mixture of Experts | 12 ديسمبر، الحلقة 85

فك تشفير الذكاء الاصطناعي: تقرير إخباري أسبوعي

انضمّ إلى نخبة من المهندسين والباحثين وقادة المنتجات وغيرهم من الخبراء وهم يقدّمون أحدث الأخبار والرؤى حول الذكاء الاصطناعي، بعيدًا عن الضجيج الإعلامي.