Post

0xA. Dynamic Lab

0xA. Dynamic Lab

بسم الله الرحمن الرحيم.

في هذا المقال، سوف نقوم بحل تحدي (Lab) بسيط يعتمد بشكل كامل على التحليل الديناميكي (Dynamic Analysis) باستخدام المنقح x64dbg. سنتعلم كيف نتخطى آليات اكتشاف المنقح (Anti-Debugging) وكيف نقوم بتعديل مسار البرنامج (Patching) ليقبل أي مفتاح ندخله.

تجهيز بيئة العمل: يمكنك تحميل الملف التنفيذي الخاص بهذا اللاب من الرابط التالي dyn4m1c_cr4ckm3 في مستودع الدورة كلمة فك الضغط: p01nt


1. الاستطلاع والملاحظة (Reconnaissance)

بدايةً، نفتح موجه الأوامر (CMD) ونقوم بتشغيل البرنامج لنرى ما هي مخرجاته الأولية.

Program running شكل (1)

نلاحظ أن البرنامج يتطلب إدخال مفتاح (Arguments) ليعمل.

عند فتح قسم النصوص (Strings) باستخدام أداة PE-Bear، نلاحظ وجود رسالة مثيرة للاهتمام تشير إلى اكتشاف منقح (Debugger Detected).

PE-Bear1 شكل (2)

هذا يعني بوضوح أن هناك دالة حماية داخل الكود تقوم بفحص ما إذا كان البرنامج يعمل تحت بيئة تنقيح أم لا. بالبحث في دوال الاستيراد (Imports)، نجد الدالة التالية:

PE-Bear2 شكل (3)

دالة IsDebuggerPresent هي واجهة برمجية (API) في ويندوز مسؤولة عن اكتشاف ما إذا كان البرنامج يعمل داخل Debugger. سنأخذ هذه المعلومة كأول نقطة ارتكاز لنا.


2. تجهيز بيئة التنقيح (x64dbg Setup)

الآن، نقوم بفتح البرنامج داخل x64dbg. بما أن البرنامج يتطلب تمرير مفتاح (Argument) عند التشغيل، يجب أن نخبر المنقح بذلك:

  1. من القائمة العلوية، نضغط على File -> Change Command Line.
  2. نضيف بعد مسار البرنامج كلمة اختبارية، مثلاً test_key.

x64dbg1 شكل (4)

  1. نضغط OK، ثم نضغط على الاختصار Ctrl + F2 لإعادة تشغيل البرنامج (Restart) وتطبيق الأمر السابق.

نضغط الآن على المفتاح F9 (Run) لنجعل البرنامج ينفذ التعليمات الأولية للنظام حتى يتوقف عند نقطة الإدخال الرئيسية للبرنامج (Entry Point)، حيث سيظهر لنا اسم البرنامج في التعليقات.

x64dbg2 شكل (5)


3. تخطي حماية المنقح (Bypassing Anti-Debugging)

نريد الآن إيجاد المكان الذي يتحقق فيه البرنامج من وجود المنقح لنقوم بتعطيله.

  1. نضغط Right-Click (كليك يمين) داخل مربع عرض الأكواد (CPU Window).

x64dbg3 شكل (6)

  1. نختار: Search for -> Current Module -> String References.

  2. في نافذة النصوص التي ستظهر، نبحث عن رسالة Debugger detected وننقر عليها نقراً مزدوجاً للانتقال إلى مكانها في الكود.

x64dbg4 شكل (7)

إذا نظرنا إلى الأسطر التي تسبق هذه الرسالة، سنرى أنه يتم استدعاء دالة IsDebuggerPresent، وبعدها مباشرة يقوم البرنامج بعمل test للنتيجة ليكتشف هل نحن نعمل على Debugger أم لا، يليه قفز شرطي (je - Jump if Equal).

عملية الترقيع (Patching): الآن سنتلاعب بهذا القفز الشرطي لنعكس المنطق تماماً.

  • ننقر نقرة واحدة على تعليمة je، ثم نضغط على زر Space (مسطرة) لفتح نافذة التعديل (Edit Instruction).

x64dbg5 شكل (8)

  • نقوم بتغيير التعليمة من je (اقفز إذا كان مساوياً) إلى jne (اقفز إذا لم يكن مساوياً).

x64dbg6 شكل (9)

نتأكد من ظهور رسالة Instruction encoded successfully في الأسفل، مما يعني أن التعديل قد تم بنجاح في الذاكرة. بهذا نكون قد أعمينا البرنامج، ولن يكتشف أننا نقوم بتحليله!


4. تحليل دالة التحقق والتعديل النهائي (The Core Logic)

نعود الآن إلى نافذة النصوص (String References) مرة أخرى. هذه المرة، نبحث عن رسالة النجاح (Success Message) وننتقل إليها.

x64dbg7 شكل (10)

بالنظر إلى الكود الذي يسبق رسالة النجاح، نلاحظ استدعاء لدالة strcmp (وهي الدالة البرمجية الشهيرة التي تقوم بمقارنة نصين ببعضهما: المفتاح الأصلي والمفتاح الذي أدخلناه).

x64dbg8 شكل (11)

ننقر على تعليمة الـ call الخاصة بـ strcmp ونضغط F2 لوضع نقطة توقف (Breakpoint) عندها (سيتحول لون العنوان إلى الأحمر).

نضغط الآن على F9 (Run) مرة أو أكثر حتى يصل تنفيذ البرنامج إلى نقطة التوقف هذه. ملاحظة: البرنامج سيتخطى فحص الـ Debugger بنجاح بفضل التعديل الذي قمنا به سابقاً، ويمكنك رؤية ذلك في نافذة الـ CMD المرافقة لـ x64dbg.

x64dbg9 شكل (12)

كشف المفتاح (Leaking the Key)

قبل تنفيذ الاستدعاء لدالة strcmp مباشرة، إذا نظرنا إلى نافذة المسجلات (Registers) أو الـ Stack، سنرى أنه تم تمرير قيمتين للدالة:

  1. المفتاح التجريبي الذي أدخلناه (test_key).
  2. المفتاح الأصلي الصحيح المخزن في الذاكرة!

x64dbg10 شكل (13)

تعديل منطق القفز (Forcing Success)

نضغط الآن F8 (Step Over) لتنفيذ دالة المقارنة وتخطيها. مباشرة بعد دالة المقارنة، سنجد تعليمة test eax, eax تليها تعليمة قفز شرطي jne (والتي ستقفز إلى رسالة الفشل لأن مفتاحنا خاطئ).

x64dbg11 شكل (14)

سنقوم بعمل Patch آخر هنا: ننقر على jne ونضغط Space، ثم نغيرها إلى je. نضغط F8 للمتابعة. نلاحظ أن علم التصفير (Zero Flag - ZF) يساوي الصفر، وبسبب تغييرنا للتعليمة إلى je، فإن البرنامج سيعتبر أن المقارنة نجحت وسيقفز باتجاه رسالة النجاح.

x64dbg12 شكل (15)

نستمر بالضغط على F8 حتى نصل إلى استدعاء دالة memset أو نهاية الإجراء.

x64dbg13 شكل (16)

إذا ألقينا نظرة على نافذة الـ CMD الآن:

x64dbg14 شكل (17)

نحن الآن طبقنا مفهوم الـ Patching بنجاح، لأن البرنامج أعطانا رسالة “النجاح” بالرغم من أن المفتاح الذي أدخلناه (test_key) كان خاطئاً!


5. تأكيد المفتاح الأصلي

إذا أردنا التأكد من عملنا بشكل سليم بدون Patching، يمكننا أخذ المفتاح الأصلي الذي اكتشفناه في الذاكرة أثناء التحليل قبل استدعاء strcmp، ونقوم بتشغيل البرنامج من الـ CMD بشكل طبيعي وتمرير هذا المفتاح له.

x64dbg15 شكل (18)

تهانينا! لقد قمت للتو بهندسة برنامج عكسياً، تخطيت حماية المنقح، عدلت المنطق البرمجي، واستخرجت المفتاح السري بنجاح.

This post is licensed under CC BY 4.0 by the author.