
تقنية تهرب متقدمة في الذاكرة تعمل على تذبذب حماية ذاكرة الشيلكود بين RW/NoAccess و RX، ومن ثم تشفير/فك تشفير محتوياته
تنفيذ PoC لتقنية مراوغة أخرى في الذاكرة تقوم بتشفير وفك تشفير محتويات الشيل كود بشكل دوري لجعله يتأرجح بين حماية الذاكرة RW (أو NoAccess) و RX.
عندما تقيم شيل كود الخاص بنا في صفحات ذاكرة RW أو NoAccess، فإن الماسحات الضوئية مثل Moneta أو pe-sieve لن تتمكن من تتبعه وتفريغه لتحليله لاحقًا.
بعد إصدار ThreadStackSpoofer تلقيت بعض الأسئلة حول النقطة التالية من ملف README:
غيّر حماية صفحات ذاكرة الـ Beacon الخاص بك إلى RW (من RX/RWX) وقم بتشفير محتوياتها قبل النوم (قد يؤدي ذلك إلى مراوغة ماسحات ضوئية مثل Moneta أو pe-sieve)
في السابق كنت واثقًا تمامًا من أن المجتمع يعرف بالفعل كيفية تشفير/فك تشفير الحمولات وقلب حمايات الذاكرة الخاصة بها لمجرد مراوغة ماسحات الذاكرة التي تبحث عن مناطق تنفيذ غير طبيعية. لكن الأسئلة أثبتت عكس ذلك، لذا قررت إصدار هذا الـ PoC غير المسلّح لتوثيق استراتيجية مراوغة أخرى وتقديم تنفيذ نموذجي ليعمل معه المجتمع.
هذا الـ PoC هو عرض لتقنية بسيطة نسبيًا، معروفة بالفعل لدى مجتمع الهجوم (لذا لا أحضر أي شيء جديد هنا حقًا) على أمل كشف السر وراء السحر الذي تُظهره بعض الأطر التجارية التي تعرض قدراتها على المراوغة مستهدفةً الماسحين الضوئيين المذكورين أعلاه.
فيما يلي مقارنة عند التأرجح إلى RW (خيار آخر هو التأرجح إلى PAGE_NOACCESS - موصوف أدناه):

هذا التنفيذ إلى جانب ThreadStackSpoofer الخاص بي يقدم للمجتمع الأمني الهجومي تطبيقات نموذجية للحاق بالعروض المقدمة من منتجات C2 التجارية، حتى لا نكون أسوأ حالًا في أدوات Red Team الخاصة بنا. 💪
يقوم هذا البرنامج بتنفيذ حقن ذاتي للشيل كود (تقريبًا عبر VirtualAlloc الكلاسيكية + memcpy + CreateThread).
عند تشغيل الشيل كود (يستهدف هذا التنفيذ تحديدًا حمولات Cobalt Strike Beacon) سيتم ربط دالة ويندوز لاعتراض اللحظة التي ينام فيها الـ Beacon عبر kernel32!Sleep.
عندما يتم استدعاء دالة MySleep المربوطة، ستحدد حدود تخصيص الذاكرة الخاص بها، وتقلب حمايتها إلى RW وتقوم بعمل xor32 على جميع البايتات المخزنة هناك.
بعد الانتظار للمدة الزمنية المتوقعة، عندما يعود الشيل كود إلى معالج MySleep الخاص بنا، سنقوم بفك تشفير بيانات الشيل كود وقلب الحماية مرة أخرى إلى RX.
PAGE_READWRITE يعمل على النحو التاليkernel32!Sleep بحيث يشير إلى دالة الاستدعاء الخاصة بنا.VirtualAlloc + memcpy + CreateThread. على عكس ما كان لدينا في ThreadStackSpoofer، لا نقوم هنا بربط أي شيء في ntdll لتشغيل الشيل كود الخاص بنا بل نقفز إليه من داخل الدالة الخاصة بنا. تحاول هذه الطريقة تجنب ترك مؤشرات IOC بسيطة في الذاكرة تشير إلى ذاكرة ntdll معدّلة.MySleep الخاصة بنا.RWkernel32!Sleep الأصلية لتجنب ترك مؤشر IOC بسيط في الذاكرة يشير إلى أن Sleep قد تم تعديلها بـ trampoline (ربط داخلي inline).::Sleep الأصلي للسماح للـ Beacon بالنوم أثناء انتظار التواصل اللاحق.RX ثم نعيد ربط kernel32!Sleep لضمان اعتراض النوم اللاحق.PAGE_NOACCESS يعمل على النحو التاليkernel32!Sleep بحيث يشير إلى دالة الاستدعاء الخاصة بنا.VirtualAlloc + memcpy + CreateThread ...MySleep الخاصة بنا.PAGE_NOACCESSkernel32!Sleep الأصلية لتجنب ترك مؤشر IOC بسيط في الذاكرة يشير إلى أن Sleep قد تم تعديلها بـ trampoline (ربط داخلي inline).::Sleep الأصلي للسماح للـ Beacon بالنوم أثناء انتظار التواصل اللاحق.kernel32!Sleep لضمان اعتراض النوم اللاحق.RX ويُستأنف الشيل كود.التقنية ليست جديدة كليًا، وليست شيئًا ابتكرته بنفسي. إنها مجرد تنفيذ يعرض المفهوم واستخدامه العملي للسماح لمجتمعنا الأمني الهجومي باللحاق بالعروض المقدمة من أطر C2 التجارية.
في الواقع، تم تعريفّي بفكرة قلب حماية ذاكرة الشيل كود قبل عدة سنوات من خلال عمل Josh Lospinoso في مشروعه المذهل Gargoyle.
فيما يلي مزيد من الخلفية:
Gargoyle يأخذ مفهوم الشيل كود الواعي بذاته والمتأرجح بذاته إلى أبعد من ذلك، من خلال الاستفادة من تسلسل ROP الذي يستدعي VirtualProtect.
ومع ذلك، التقنية مثيرة للإعجاب، لكن من الصعب بنفس القدر استخدامها مع Cobalt Strike's Beacon دون الحاجة إلى قتل الخيط الخاص به والاستمرار في إعادة تهيئة الـ Beacon أثناء تواجده في الذاكرة.
هذا بعيد عن المثالية، لكن نظرًا لأننا نعمل بالفعل من أرضية عملية تحميل ذاتي خاصة بنا، فنحن قادرون على فعل ما نشاء بالبيئة التي يعمل فيها الشيل كود وإخفائه بالطريقة التي نريدها. تُظهر هذه التقنية (والتقنية السابقة ThreadStackSpoofer) مزايا تشغيل الشيل كود الخاص بنا بهذه الطريقة.
تنفيذ التأرجح إلى PAGE_NOACCESS مستوحى من عمل ORCA666 المعروض في https://github.com/ORCA666/0x41 injector.
لقد أظهر أنه:
يحتوي هذا التنفيذ على هذه الفكرة مطبقة، وهي متاحة مع الخيار 2 في <fluctuate>.
تأكد من الاطلاع على مشاريعه الأخرى أيضًا.
تقبل الأداة ShellcodeFluctuation ثلاثة معاملات: الأول هو المسار إلى الشيل كود والثاني هو معدّل وظيفتنا.```
Usage: ShellcodeFluctuation.exe
:
-1 - Read shellcode but dont inject it. Run in an infinite loop.
0 - Inject the shellcode but don't hook kernel32!Sleep and don't encrypt anything
1 - Inject shellcode and start fluctuating its memory with standard PAGE_READWRITE.
2 - Inject shellcode and start fluctuating its memory with ORCA666's PAGE_NOACCESS.
### إيجابية كاذبة (على ما يبدو) من Moneta```
C:\> ShellcodeFluctuation.exe beacon64.bin -1
لذا أولاً سنرى ما يراه ماسح Moneta64 حول عملية لا تفعل أي شيء مريب وتكتفي ببساطة بتشغيل حلقة لا نهائية:

كما نرى هناك بعض الإيجابيات الكاذبة (على الأقل كما أعتبرها) التي يُزعم أنها تكتشف Mismatching PEB module / Phantom image.
حدود الذاكرة تشير إلى وحدة ShellcodeFluctuate.exe نفسها وقد تشير إلى أن هذه الوحدة، رغم كونها من نوع MEM_IMAGE، غير مرتبطة في PEB الخاصة بالعملية - وهو أمر غير معتاد ويبدو غريباً إلى حد ما.
سبب هذا الـ IOC غير معروف بالنسبة لي ولم أحاول فهمه بشكل أفضل، لكنه ليس شيئاً يجب أن نقلق بشأنه حقاً.
إذا كان أي شخص يعرف سبب هذا الاكتشاف، فسأكون فضولياً جداً لسماعه! يرجى التواصل معي.