Skip to content
KitploitKITPLOIT
أدواتعمليات الاستغلالالمدونة
Log in
إرسال
أدواتعمليات الاستغلالالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

الخلاصاتاتصالالخصوصية© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
أدوات/GitHubGitHub/janoglezcampos/deathsleep
الاستغلالتحليل البرمجيات الخبيثةالفريق الأحمرتطوير الحمولات
GitHubjanoglezcampos/deathsleep

DeathSleep

تنفيذ لإثبات المفهوم لتقنية مراوغة تهدف إلى إنهاء الخيط الحالي واستعادته قبل استئناف التنفيذ، مع تنفيذ تغييرات في حماية الصفحات أثناء عدم التنفيذ.

عرض المستودع
538778منذ 4 سنواتتمت المراجعة من قبل Kitploit

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

██████╗ ███████╗ █████╗ ████████╗██╗ ██╗███████╗██╗ ███████╗███████╗██████╗ ██╔══██╗██╔════╝██╔══██╗╚══██╔══╝██║ ██║██╔════╝██║ ██╔════╝██╔════╝██╔══██╗ ██║ ██║█████╗ ███████║ ██║ ███████║███████╗██║ █████╗ █████╗ ██████╔╝ ██║ ██║██╔══╝ ██╔══██║ ██║ ██╔══██║╚════██║██║ ██╔══╝ ██╔══╝ ██╔═══╝ ██████╔╝███████╗██║ ██║ ██║ ██║ ██║███████║███████╗███████╗███████╗██║
╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚══════╝╚═╝

تنفيذ إثبات المفهوم (PoC) لتقنية تهرب تهدف إلى إنهاء الخيط الحالي واستعادته قبل استئناف التنفيذ، مع تطبيق تغييرات حماية الصفحة أثناء عدم التنفيذ.

مقدمة

طرق السبات والإخفاء معروفة جيدًا في مجتمع تطوير البرامج الضارة (maldev)، مع تطبيقات مختلفة، تهدف إلى الاختباء من ماسحات الذاكرة أثناء السبات، عادة عن طريق تغيير حماية الصفحات وحتى إضافة ميزات رائعة مثل تشفير الشيل كود، ولكن هناك نقطة مهمة أخرى لإخفاء الشيل كود الخاص بنا، وهي إخفاء خيط التنفيذ الحالي.
انتحال المكدس (stack spoofing) أمر رائع، ولكن بعد التفكير قليلاً، خطر لي أنه ليست هناك حاجة لانتحال المكدس… إذا لم يكن هناك مكدس :)

يُترك تقييم قابلية استخدام هذه التقنية للقارئ، ولكن على أي حال، أعتقد أنها طريقة رائعة لمراجعة بعض المواضيع، وتعلم بعض تقنيات maldev لمن هم، مثلي، بدأوا للتو في هذا العالم.

التنفيذ الرئيسي المعروض هنا يحتفظ بكل ما نحتاج لإخراجه من المكدس في قسم البيانات، كمتغيرات عامة، ولكن سيتم نشر تنفيذ ينقل كل شيء إلى الكومة (heap) قريبًا. يهدف إلى إظهار بعض التعديلات الرئيسية التي يجب إجراؤها لجعل هذا الكود مستقلاً عن الموقع (PIC) وقابلاً للحقن.

هذا المستودع منعكس بين GitHub و GitLab.


ما الذي يحدث؟

قبل كل شيء

كل ما ورد هنا يأتي من فهمي للمواضيع المختلفة المطروحة، سواء من القراءة أو الخبرة أثناء التطوير. أنا مدرك أنني لست خبيرًا وآخر ما أريده هو نشر معلومات خاطئة، لذا إذا كنت تعتقد أن هناك شيئًا غير صحيح، سأكون سعيدًا بإبلاغي بذلك، يمكنك الاتصال بي على تويتر، أو فتح مشكلة (issue) في هذا المستودع. شكرًا جزيلاً لتفهمك. :)

الأساسيات

الهدف الرئيسي من هذه التقنية واضح، وهو إنهاء الخيط الحالي واستعادته قبل استئناف التنفيذ، ولكن ماذا يعني هذا بالضبط، وما القيود الجديدة التي يفرضها؟

لكي نتمكن من استعادة التنفيذ، نحتاج إلى حفظ شيئين قبل إنهاء الخيط: أولاً، حالة وحدة المعالجة المركزية (CPU state)، وثانيًا المكدس، ثم إعادة ضبطهما بشكل فعال بعد تشغيل الخيط الجديد.

تحدثت عن قيود جديدة ستظهر في هذه التقنية، وهناك اثنان رئيسيان: أولاً، نحتاج إلى تخزين أي شيء مطلوب خارج المكدس من لحظة إنهاء الخيط حتى استعادة المكدس، وكما سترى، هذا يخلق تحديات جديدة.

ثانيًا، نحتاج دائمًا إلى وجود خيط آخر على الأقل قيد التشغيل في عمليتنا، لأننا بإنهاء خيطنا، إذا لم تكن هناك خيوط أخرى، ستنتهي العملية. لا أعتقد أن هذه مشكلة كبيرة، نظرًا لأن معظم العوامل (agents) تُحقن في عمليات أخرى، يمكننا افتراض أن هذه العملية ستحتفظ بخيط واحد على الأقل قيد التشغيل.

مكونات DeathSleep:

يمكننا رؤية 4 وظائف أساسية في هذا الإثبات:

  • البرنامج الرئيسي: هذا هو المكان الذي ستكتب فيه كود الوكيل الخاص بك، وهو الجزء من الكود الذي سيستخدم DeathSleep.
  • وظيفة الاستيقاظ (Awake): هذه هي نقطة الدخول لجميع خيوطنا، وهي المسؤولة عن حفظ نقطة البداية للمكدس الذي سنستعيده. كما أنها مسؤولة عن استعادة المكدس وسياق وحدة المعالجة المركزية عند الحاجة، أو مجرد تشغيل برنامجنا الرئيسي.
  • DeathSleep: هذه هي الوظيفة الرئيسية لهذه التقنية، وهي المسؤولة عن نسخ سياق الخيط والمكدس احتياطيًا، وكذلك إعداد كل شيء لحدوث السحر.
  • Rebirth: وظيفة بسيطة مسؤولة فقط عن تشغيل خيوطنا الجديدة.

حفظ المكدس.

عندما نكون على وشك حفظ المكدس، يطرح سؤال: ما مقدار المكدس الذي يجب حفظه؟

دعنا نراجع أولاً ما هو موجود في المكدس بعد استدعائنا لوظيفة DeathSleep (هذه هي الوظيفة التي تحفظ السياق والمكدس وتعد كل شيء للإخفاء والاستعادة).

كما نرى، كل وظيفة تتكون من ثلاثة أجزاء:

  • Shadow space: مساحة بحجم 32 بايت، يتم تخصيصها بواسطة المتصل (caller)، ولكن يستخدمها المستدعى (callee). على حد علمي وما رأيته، وظيفتها الرئيسية هي الاحتفاظ، إذا لزم الأمر، بالوسائط التي تم تمريرها إلى الوظيفة المستدعاة في السجلات، ولكن يمكن استخدامها لأي شيء تقرره الوظيفة المستدعاة.
  • عنوان العودة (Return address): هذا هو عنوان التعليمات التالية التي سيتم تنفيذها في وظيفة المتصل، يتم دفعه بواسطة تعليمة CALL، بحيث تأخذ تعليمة RET في الوظيفة المستدعاة هذا العنوان و"تقفز" إليه عند انتهائها.
  • مساحة مكدس الوظيفة (Function stack space): هذه هي المساحة التي تحجزها الوظيفة المستدعاة لتخزين قيمة السجلات التي تحتاج إلى استعادة وقيمة متغيراتها المحلية.

الحد الأدنى من المكدس الذي نحتاج بالتأكيد لحفظه هو كل شيء داخل برنامجنا الرئيسي، وهذا يعني مساحة Shadow space الخاصة به، وعنوان العودة الخاص به، وكل شيء حتى وظيفة DeathSleep. أي شيء قبل ذلك ليس مطلوبًا حقًا (حفظ المكدس المستخدم بواسطة وظيفة الدخول له مزايا، لكننا سنناقش ذلك لاحقًا)، لأن هذا هو المكدس المستخدم بواسطة إجراءات Windows لتشغيل خيطنا الجديد. بالإضافة إلى ذلك، قررت أيضًا تخزين مساحة Shadow space الخاصة بوظيفة DeathSleep (ليس ضروريًا حقًا، لكنه يجعل حساب Rsp في لحظة الاستيقاظ أسهل).

لذا في النهاية، نحن نحفظ هذا:

كيفية العثور على عناوين المكدس لدينا:

كل وظيفة في الترجمة القياسية يجب أن تتكون من 3 أجزاء: المقدمة (prologue)، كود الوظيفة، والخاتمة (epilogue).

يجب تعديل Rsp (مؤشر المكدس) فقط في مقدمة وخاتمة الوظيفة. المقدمة تزيد مؤشر المكدس (تذكر أن زيادة المكدس تعني تقليل العناوين، لأنها تسير في اتجاهين متعاكسين)، لحفظ السجلات، لاحتواء جميع متغيراتها المحلية ثم لاحتواء Shadow space، والخاتمة تفعل العكس تمامًا.

هذا يعني أن مؤشر المكدس داخل كود الوظيفة يجب أن يشير دائمًا إلى نهاية Shadow space (الأرجواني في الصورة أعلاه)، ومجموع حجم مكدس الوظيفة و Shadow space يمكن العثور عليه عن طريق حساب مقدار زيادة مؤشر المكدس في المقدمة. يمكن حساب هذه القيمة بسهولة باستخدام المعلومات المحمولة في جداول فك اللف (unwind tables)، شرح استخدامها ليس شيئًا سنغطيه هنا، ولكن كملخص، تُستخدم هذه الجداول للسماح لأي خيط أو عملية أخرى بالتحرك بشكل صحيح عبر المكدس لرؤية محتوياته، أو للتعامل مع الاستثناءات أو تحليلها.

التقاط السياق وإعداده للاستعادة.

التقاط السياق هو على الأرجح أسهل شيء يمكن القيام به، حيث يمكننا ببساطة تنفيذ RtlCaptureContext() في أول سطر من DeathSleep، قبل أي تعديل على السجلات غير المتطايرة (non-volatile registers). لا يزال يتعين علينا إجراء تعديلين على السياق الذي سنستعيد فيه التنفيذ.

أول تعديل سيكون تعديل Rip، كما تتذكر، هذا هو السجل الذي يحمل التعليمات التالية للتشغيل، وإذا تركناه دون تعديل، فسيستأنف التنفيذ داخل وظيفة DeathSleep. ما سنفعله هو تغيير Rip ليحمل عنوان العودة الخاص بـ DeathSleep، والذي يشير إليه Rsp الحالي بعد إزاحة مقدار الزيادة في الخاتمة (المناطق الخضراء + الأرجوانية في الصور أعلاه).

التعديل الثاني سيتم عند استعادة الخيط، وهو يتضمن تعيين Rsp ليشير إلى أعلى المكدس المستعاد؛ سيتم ذلك خلال مرحلة الاستعادة، لأننا لا نعرف أين سيتم وضع مكدسنا الجديد. ستكون القيمة ببساطة هي عنوان نهاية المكدس المستعاد، لأنه كما ناقشنا لاحقًا، قمنا بنسخ أيضًا مساحة Shadow space المحجوزة بواسطة متصل DeathSleep، وهذه هي بالضبط قيمة RSP قبل استدعاء DeathSleep.

استعادة المكدس:

تنزيل الأداة