Module 11: تعديل وإصلاح الإكسبلويتات

الموديول ده بيركّز على محورين أساسيين:

1تعديل إكسبلويتات بتستهدف ثغرات memory corruption
2تعديل إكسبلويتات مصمَّمة لتطبيقات الويب

تطوير إكسبلويت من الصفر غالبًا معقَّد ومحتاج وقت وخبرة كبيرين. من ناحية تانية، إيجاد إكسبلويت عام جاهز يطابق بالظبط ظروف تقييم حقيقي ممكن يكون صعب بنفس القدر. الحل العملي هو ناخد إكسبلويت متاح ونعدّله عشان يناسب متطلبات بيئة الهدف المحددة.

لما نتعامل مع مشاكل memory corruption — زي ثغرات buffer overflow — كذا مكوّن حرج عادةً محتاج تعديل. ده ممكن يشمل تفاصيل اتصال الشبكة، عناوين الـ return، إعداد الـ payload، وoffsets الذاكرة. كل عنصر من دول لازم يتماشى بالظبط مع نظام الهدف.

⚠ Scope & Risk

لو نظام الهدف بيشغّل نظام تشغيل حديث زي Windows Server 2022 لكن الإكسبلويت اتطوّر أصلًا لمنصة أقدم بكتير زي Windows Server 2003، آليات دفاعية حديثة — خصوصًا حماية زي Address Space Layout Randomization (ASLR) — على الأرجح هتمنع الإكسبلويت من إنه يشتغل صح وممكن تسبّب كراش للتطبيق. الكراش ده ممكن يعطّل الخدمة العرضة للاستغلال مؤقتًا أو يأثّر سلبًا على أنظمة إنتاجية — نتيجة لازم مختبري الاختراق يتجنّبوها كل ما أمكن.

قبل أي اختبار، نطاق المهمة لازم يحدد بوضوح المخاطر المقبولة، بما فيها احتمالية تعطّل الخدمة. العملاء لازم يوافقوا على المخاطر دي مُسبقًا. كمحترفين أمنيين، مسؤوليتنا هي تقليل التأثير التشغيلي مع تحقيق أهداف الاختبار برضه.

لتقليل احتمالية التعطّل، أفضل ممارسة هي مراجعة كود الإكسبلويت بدقة، تعديله بحرص، والتحقق منه جوه بيئة لاب متحكَّم فيها بتحاكي الهدف قدر الإمكان قبل استخدامه في سيناريو حي.

الاختلافات الخاصة بكل هدف كمان بتفسّر ليه مستودعات زي Exploit Database غالبًا بتوفّر نسخ متعددة من الإكسبلويت لنفس الثغرة — كل نسخة ممكن تكون معدَّلة لإصدار نظام تشغيل، معمارية، أو إعدادات مختلفة.

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

أبعد من إكسبلويتات memory corruption، تعديل إكسبلويتات الويب بيجيب اعتبارات مختلفة. دي غالبًا بتتضمّن تعديل إعدادات اتصال الشبكة وتفاصيل خاصة بالتطبيق زي مسارات الطلبات، المعطيات، الـ headers، توكينز التوثيق، وكوكيز الجلسة عشان تطابق تطبيق الويب المستهدَف.


01إصلاح إكسبلويتات Memory Corruption

أهداف الوحدة

1استيعاب المفاهيم الأساسية ورا ثغرات buffer overflow
2تعلّم cross-compiling للبرامج لأنظمة تشغيل ومعماريات مختلفة
3فهم إزاي نعدّل ونحدّث إكسبلويتات memory corruption موجودة

Buffer Overflow — المفهوم الأساسي

⬦ Definition

الـ Buffer هو جزء محجوز من الذاكرة بيُستخدم لتخزين بيانات مؤقتًا، غالبًا متوفّرة من مستخدم أو مكوّن برنامج تاني. بعض الـ buffers تقدر تتوسّع ديناميكيًا، بينما تانية بتتخصّص بحجم ثابت مُسبقًا.

ثغرات buffer overflow من أقدم أشكال عيوب memory corruption، موثَّقة من أواخر الثمانينات. رغم عقود من التحسينات الدفاعية، لسه بتظهر في سوفت وير حديث.

على مستوى عالي، buffer overflow بيحصل لما بيانات الإدخال تتجاوز المساحة المخصَّصة وتفيض لمناطق ذاكرة مجاورة. لما ده يحصل على الـ stack، يقدر يكتب فوق قيم حرجة مخزَّنة قريب.

تخيّل buffer مصمَّم لتخزين باسورد بحد أقصى 8 بايت. لو مستخدم بعت نص أطول، الحروف الزيادة هتمتد أبعد من حدود الـ buffer. من غير ضمانات مناسبة، الـ overflow ده يقدر يفسد ذاكرة قريبة ويؤدي لسلوك غير متوقَّع.

Stack مقابل Heap

المنطقةالوصف
Heapذاكرة مُدارة ديناميكيًا بتُستخدم لبيانات كبيرة أو قابلة للوصول عالميًا
Stackمنطقة ذاكرة منظَّمة بتُستخدم لاستدعاءات الدوال، المتغيّرات المحلية، والتحكّم بتدفّق التنفيذ

الـ stack عادةً بيخزّن متغيّرات محلية زي buffers وأعداد صحيحة، بالإضافة لمعلومات تحكّم زي معطيات الدوال وعناوين الـ return.

c
char buffer[64];
strcpy(buffer, argv[1]);

هنا، buffer بحجم ثابت 64 بايت مُعلَن، وبيانات المستخدم بتتنسخ جواه باستخدام الدالة strcpy. الدالة دي غير آمنة لأنها مابتعملش فحص حدود (bounds checking). لو الإدخال تجاوز 64 بايت، هيكتب فوق ذاكرة مجاورة.

ليه الـ Return Address مهم

لما دالة تتنفّذ، الـ stack كمان بيخزّن return address بيوضّح من أنهي نقطة البرنامج لازم يكمّل لما الدالة تخلّص. لو الـ overflow كتب فوق العنوان ده، الـ processor هيقفز لأي قيمة اتحطّت مكانه لما الدالة ترجع. ده ممكن لأن تعليمة الـ return بتحمّل العنوان في register الـ instruction pointer (EIP/RIP)، اللي بيتحكّم في تدفّق تنفيذ البرنامج.

مهاجم بيتحكّم في العنوان ده يقدر يوجّه التنفيذ لكود خبيث.

سيناريو استغلال نموذجي

1
تحفيز الـ Overflow

بإرسال إدخال أكبر من الـ buffer

2
الكتابة فوق Return Address

بقيمة متحكَّم فيها من المهاجم

3
وضع الكود الخبيث

الـ shellcode جوه الـ buffer

4
توجيه التنفيذ

للكود المحقون

غالبًا، المهاجمين بيكتبوا فوق الـ return address بموقع تعليمة زي "jump to stack pointer"، وده بيخلّي البرنامج ينفّذ الـ payload المخزَّن في الذاكرة. لزيادة الموثوقية، المهاجمين ممكن يضيفوا سلسلة من تعليمات no-operation (NOP sled) قبل الـ payload، وده بيسمح للتنفيذ "ينزلق" جوه الـ shellcode حتى لو القفزة مش محاذية تمامًا.

low addressBuffer (A...A)Saved EBPReturn Addr→ JMP ESPNOP sled\x90\x90…Shellcodehigh address
بنية الـ stack المُستهدَفة: padding ← return address (معدَّل) ← NOP sled ← shellcode

الحماية الحديثة

بما إن الهجمات دي موجودة من عشرات السنين، أنظمة التشغيل قدّمت دفاعات زي:

لأغراض التعلّم، سيناريوهات تطوير الإكسبلويت غالبًا بتفترض إن الحمايات دي معطَّلة.

تعديل إكسبلويتات موجودة

لما بنعدّل إكسبلويت buffer overflow لهدف محدد، كذا مكوّن ممكن يحتاج تعديل:

أي تغيير بيأثّر على طول الـ buffer ممكن يزحزح الـ offset المطلوب للكتابة فوق return address، يعني الإكسبلويت لازم يتم معايرته من جديد.

حتى لو إكسبلويت عام فيه return address شغّال، الأأمن إنك تحدد العنوان الصح بنفسك. ده عادةً بيتم بمحاكاة بيئة الهدف جوه آلة افتراضية وتحليل التطبيق العرضة للاستغلال باستخدام debugger.

اعتبارات الـ Payload

الإكسبلويتات العامة غالبًا بتتضمّن payloads مُرمَّزة. دي مايجبش تتوثق فيها عمياني أبدًا، لأنها ممكن تنفّذ أفعال غير مقصودة. الأفضل إن المختبرين يولّدوا ويضيفوا الـ payloads بتاعتهم بأنفسهم، معدَّة بعنوان وبورت الـ listener بتاعهم.

⚠ Bad Characters

أثناء إنشاء الـ payload، حروف معينة لازم غالبًا تتجنّب. "الحروف السيئة" (bad characters) دي ممكن تعطّل الإكسبلويت لأن التطبيق بيفسّرها كإشارات تحكّم. مثلًا، null byte (\x00) ممكن ينهي النص بدري ويقطع الـ payload.

في بعض الحالات، الإكسبلويت بيعتمد على payload متخصّص مرتبط بإحكام بالثغرة. لو كده، فهم سلوكه ممكن يحتاج reverse engineering، اللي ممكن يكون معقَّد. عشان كده، سير العمل العملي غالبًا بيركّز على استبدال الـ shellcode بـ بديل آمن ومعروف كل ما أمكن.

$ cat ./lu1_takeaways.txt

02Cross-Compiling للإكسبلويت

الأفضل إن كود الإكسبلويت يتجمّع باستخدام compiler أصلي (native) يطابق نظام تشغيل الهدف. لكن ده مش دايمًا ممكن أثناء تقييم. في كتير من الحالات، المختبرين بيشتغلوا من منصة هجوم واحدة — غالبًا Kali Linux — بينما محتاجين يبنوا إكسبلويت مُعَد لنظام مختلف زي Windows.

لما التجميع المباشر على منصة الهدف مش ممكن، cross-compilation بتوفّر حل فعّال. الـ cross-compiler بيسمح بتجميع كود على نظام تشغيل بينما بيُنتج executable لنظام تاني.

استخدام Cross-Compiler

واحدة من أكتر toolchains استخدامًا لإنتاج binaries خاصة بـ Windows من Linux هي MinGW-w64. لو مش متثبّتة، تقدر تضيفها عن طريق مدير الباكيدجات.

بالـ toolchain ده، كود C المصدري يقدر يتجمّع لملف Windows Portable Executable (PE) مباشرة من جهاز الهجوم.

حل أخطاء التجميع

أثناء التجميع، أخطاء linker ممكن تظهر بتوضّح مراجع غير محلولة لوظائف شبكية. الأخطاء دي غالبًا بتحصل لأن الكود بيعتمد على مكتبات شبكة Windows اللي مش متضمَّنة تلقائيًا.

البحث عن رسائل الخطأ عادةً بيكشف إن وظائف زي network initialization وsocket operations بتنتمي لـ Windows Sockets (Winsock) API. لحل كده، المكتبة المناسبة لازم تتربط صراحةً أثناء التجميع. إضافة linker flag الصح بيوجّه الـ compiler إنه يضمّن مكتبة الشبكة المطلوبة في الـ executable النهائي.

✓ Lesson

كتير من فشل التجميع مش بسبب أخطاء صياغة (syntax)، لكن بسبب dependencies ناقصة.

تعديل معطيات الهدف

بعد التجميع الناجح، الخطوة الجاية هي مراجعة كود الإكسبلويت بحثًا عن قيم إعداد مُدمَجة (hard-coded). في كتير من الإكسبلويتات العامة، تفاصيل اتصال زي عنوان IP الهدف، البورت المستهدَف، وإعدادات البروتوكول بتكون مُدمَجة مباشرة في الكود المصدري. القيم دي لازم تتعدّل عشان تطابق بيئة الهدف الفعلية.

مثال عملي: Cross-Compiling إكسبلويت

كود إكسبلويت نموذجي (C) — أنشئ ملف اسمه exploit.c:

c
#include <stdio.h>
#include <winsock2.h>

int main() {
    WSADATA wsa;
    SOCKET s;
    struct sockaddr_in server;

    printf("Starting exploit...\n");
    WSAStartup(MAKEWORD(2,2), &wsa);

    s = socket(AF_INET, SOCK_STREAM, 0);
    server.sin_addr.s_addr = inet_addr("192.168.1.10"); // Target IP
    server.sin_family = AF_INET;
    server.sin_port = htons(80); // Target port

    connect(s, (struct sockaddr *)&server, sizeof(server));
    printf("Connected to target!\n");

    closesocket(s);
    WSACleanup();
    return 0;
}

ده برنامج proof-of-concept بسيط بيؤسس اتصال TCP للهدف — شبيه بإيه ما كتير من إكسبلويتات الشبكة بتعمله داخليًا.

تثبيت الـ Cross-Compiler (لو مش متثبّت):

bash
sudo apt update
sudo apt install mingw-w64

تجميع لـ Windows Executable، باستخدام الـ cross-compiler الخاص بـ Windows:

bash
i686-w64-mingw32-gcc exploit.c -o exploit.exe -lws2_32

اختبار الـ Executable: انقل exploit.exe لجهاز Windows وشغّله. لو IP والبورت المستهدفين متاحين، الخرج هيكون:

output
Starting exploit...
Connected to target!

ليه التقنية دي مهمة

التقنية دي بالظبط بتُستخدم لما:

حالات شائعة في الواقع تشمل: إكسبلويتات local privilege escalation، هجمات client-side، ومواقف فيها runtime للسكربتات مش متاح. المختبرين الأمنيين غالبًا بيجمّعوا كود إكسبلويت عام من مصادر زي Exploit Database عشان يطابقوا بيئة المهمة بتاعتهم.


03دراسة حالة: Sync Breeze — من الكراش لحد Reverse Shell

✎ بيئة السيناريو

التطبيق المستهدَف هو Sync Breeze Enterprise v10.0.28. هنفحص واحد من الإكسبلويتات العامة المتاحة للثغرة دي، بهدف الحصول على إكسبلويت شغّال مناسب لبيئة اللاب بتاعتنا وبعدين فهم إزاي نعدّله لو لزم.

اختيار الإكسبلويت المناسب

لما بندوّر بالاسم والإصدار، بنلاقي إدخالات متعددة، منها سكربتات proof-of-concept مكتوبة بلغات مختلفة. من بين الخيارات المتاحة، واحد منها Denial-of-Service (DoS) proof of concept، وتانيين بيوضّحوا استغلال remote buffer overflow.

هجمات DoS بس بتعطّل الخدمة من غير ما تدّي تحكّم في النظام، فغالبًا أقل فايدة أثناء اختبار اختراق لما يكون فيه مسار استغلال كامل متاح. فالتركيز لازم يتوجّه لإكسبلويتات buffer overflow، اللي بتمكّن تنفيذ الكود.

الثغرة موجودة في خدمة HTTP المدمَجة في السوفت وير. طلب POST معدّ بعناية بيحفّز حالة buffer overflow، وده بيسمح للمهاجم يكتب فوق تدفّق التنفيذ.

فهم منطق الإكسبلويت

رغم إن مراجعة الكود المصدري الكامل موصى بيها، السلوك الأساسي يقدر يتلخّص مفاهيميًا:

  1. سلسلة من حروف padding بتملا الـ buffer العرضة للاستغلال لحد offset محدد
  2. الـ instruction pointer بيتكتب فوقه بعنوان تعليمة "jump to stack"
  3. payload (shellcode) بيتضاف، مسبوق بتعليمات NOP لتحسين الموثوقية
  4. الـ buffer الخبيث بيتوصّل عبر طلب HTTP

Python مقابل C

الجانبPythonC
نموذج التنفيذبيتنفّذ عبر interpreter، مابيولّدش binaries مستقلة افتراضيًابيتجمّع لـ executables أصلية تقدر تشتغل بشكل مستقل
إدارة الذاكرةدمج النصوص بسيط وتلقائيالذاكرة لازم تُدار صراحةً، وعمليات النصوص محتاجة حرص شديد
التشغيل في بيئة مقيَّدةمش هيشتغل من غير interpreter — PyInstaller ممكن يحوّله لـ executable لكن محتاج تعديل يدويمناسب لمواقف مفيهاش runtime للسكربتات متاح
✓ Tip

بسبب الفروق دي، تعديل إكسبلويتات مبنية على C بيحتاج حرص وفهم تقني أكتر من تعديل سكربتات مكتوبة بلغات مستوى أعلى.

تجهيز الإكسبلويت للتعديل

عشان نبدأ تعديل الإكسبلويت، بننسخ الكود المصدري من المستودع المحلي لمجلد الشغل بتاعنا باستخدام خيار mirror (-m في SearchSploit). ده بيسمح لنا نعدّل ونجمّع الكود من غير ما نغيّر الإدخال الأصلي في قاعدة البيانات.

بعد النسخ، أول خطوة هي فحص الكود المصدري بحثًا عن تفاصيل خاصة بالمنصة. في بداية ملف C المصدري، ملفات الـ header بتكشف بيئة التجميع المقصودة — مثلًا، إشارات لمكتبات شبكة Windows بتوضّح إن الإكسبلويت اتصمّم عشان يتجمّع على نظام Windows. ده معناه إن محاولة تجميعه مباشرة على Linux هتفشل من غير خطوات إضافية.

فحص DLL المفقود

بفحص الكود المصدري بعمق أكتر، بنلاقي إنه بيعتمد على return pointer موجود جوه مكتبة runtime الخاصة بـ Visual Basic msvbvm60.dll، اللي مش فعليًا متضمَّنة مع التطبيق العرضة للاستغلال.

لما نفحص الموديولات المحمَّلة بواسطة عملية الهدف جوه debugger على جهاز Windows الاختباري، بنلاقي إن الـ DLL ده مفقود — معناه إن الـ return pointer المختار مش هيشتغل في بيئتنا.

✎ خطوات التحقق

نبدأ خدمة Sync Breeze على نظام Windows 10، نفتح Immunity Debugger بصلاحيات إدارية، نربطه بعملية syncbrs الشغّالة، ونراجع الموديولات المحمَّلة عبر executable modules view. بفحص أسماء الموديولات ومساراتها، نقدر نتأكد إن مكتبة الـ runtime المطلوبة مش موجودة.

استبدال الـ Return Address

بما إن النسخة الـ Python من الإكسبلويت معلَّمة كـ verified على Exploit Database ومعروف إنها بتشتغل صح، نقدر نعيد استخدام الـ return address من النسخة دي بدل العنوان الغلط:

c
unsigned char retn[] = "\x83\x0c\x09\x10"; // 0x10090c83

لو مفيش return address شغّال متاح من إكسبلويت تاني، فيه بدائل تانية:

في سيناريوهات buffer overflow الكلاسيكية، الاعتماد على عناوين من مكتبات النظام غير موثوق لأن حمايات زي ASLR بتعشوّشها كل إقلاع (boot). الأأمن إننا نختار تعليمات من موديولات التطبيق نفسه اللي مش محمية بـ ASLR.

فهم قسم الـ Payload

مراجعة أعمق بتوضّح إن متغيّر الـ shellcode بيحتوي payload الهجوم مُرمَّز كـ hexadecimal bytes، وده بيخلّي وظيفته مش واضحة من أول نظرة. المؤشّر الوحيد الواضح هو وجود NOP sled في البداية.

بما إن إكسبلويت Python بيحدد مسبقًا الحروف الإشكالية (bad characters) اللي لازم نتجنّبها، نقدر نولّد payload جديد مصمَّم لإعدادنا باستخدام أداة Metasploit msfvenom من Metasploit Framework. الـ payload بيتعدّ لـ 32-bit Windows reverse shell وبيتنسّق للتضمين في كود C المصدري مع استبعاد الحروف السيئة.

تحديث كود الإكسبلويت

بعد استبدال: (1) عنوان وبورت الهدف، (2) الـ return pointer، (3) الـ payload (shellcode) — الكود المصدري للإكسبلويت دلوقتي بيبني طلب HTTP POST فيه الـ buffer الخبيث ويبعته للخدمة العرضة للاستغلال. بنية الـ buffer بتشمل:

  1. Padding عشان نوصل لنقطة الكتابة فوق instruction pointer
  2. الـ return address المختار
  3. الـ NOP sled
  4. الـ payload الفعلي
  5. باقي معطيات الطلب

بنجمّع الكود المعدَّل باستخدام الـ cross-compiler toolchain اللي اتكلّمنا عنه، والتجميع بيكتمل بنجاح من غير أخطاء.

الاختبار بالـ Debugger — سلوك غير متوقَّع

نرجع لـ Immunity Debugger: نربط بعملية Sync Breeze الشغّالة، نروح لعنوان JMP ESP المختار، نحط breakpoint عند النقطة دي، ونكمّل التنفيذ. بعدين نشغّل الإكسبلويت المُجمَّع — وبما إن الـ binary بيستهدف Windows، ممكن نشغّله على Linux باستخدام Wine.

☠ Crash Analysis

رغم إن الإكسبلويت بيتصل بنجاح ويبعت الطلب الخبيث، الـ breakpoint مابيتفعّلش. بدل كده، التطبيق بيعمل كراش، وregister الـ instruction pointer بيحتوي القيمة 0x9010090c.

ده بيدّل على إن الكتابة فوق العنوان حصلت فعلًا — لكن غلط. العنوان بيبان مُزاح بايت واحد، معناه إن الـ offset المستخدَم للوصول للـ instruction pointer المحفوظ على الـ stack غير دقيق. نتيجة لكده، الـ processor بيحمّل عنوان غير مقصود بدل تعليمة JMP المرغوبة.

عمليًا، طول buffer الإكسبلويت محسوب بشكل خاطئ قليلًا، وده بيخلّي الكتابة فوق العنوان تهبط في الموقع الغلط. تصحيح الـ offset ده أساسي عشان نحقق تحكّم موثوق في تدفّق التنفيذ.

تغيير Buffer الـ Overflow — السبب الجذري

عشان نشخّص ليه الكتابة فوق instruction pointer كانت بتهبط غلط، لازم نفحص إزاي الإكسبلويت بيبني الـ padding buffer الأولي بتاعه. في بداية الكود، بلوك كبير من الذاكرة ممتلئ بحرف "A" بيتعمل باستخدام تخصيص ديناميكي:

c
int initial_buffer_size = 780;
char *padding = malloc(initial_buffer_size);

القيمة دي مش عشوائية. تحليل سابق حدد إن 780 بايت هي المسافة الدقيقة المطلوبة للوصول لـ saved return address على الـ stack والكتابة فوقه، وده في النهاية بيسمح بالتحكّم في register EIP.

الذاكرة المتحصَّل عليها من malloc غير مُهيَّأة (uninitialized)، فالإكسبلويت بيملاها صراحةً:

c
memset(padding, 0x41, initial_buffer_size);

هنا، 0x41 بيمثّل قيمة ASCII لحرف "A"، منتجة سلسلة متواصلة من حروف "A". السلسلة دي بتخدم كـ padding عشان تدفع تدفّق التنفيذ بالظبط لموقع الـ return address.

بعدها مباشرة، عملية تانية بتعدّل آخر بايت في المنطقة دي:

c
memset(padding + initial_buffer_size - 1, 0x00, 1);

السطر ده بيستبدل آخر حرف بـ null byte (0x00)، وبالفعل بيحوّل الـ padding لنص C-style سليم.

ليه الـ Null Terminator مهم

في لغة C، البيانات النصية بتتعامل كـ null-terminated strings. الدوال اللي بتدمج أو تنسخ نصوص — زي strcpy وstrcat — بتحدد نهاية النص بإيجاد أول null byte. لاحقًا في الإكسبلويت، buffer طلب أكبر بيتجمّع:

c
char *buffer = malloc(buffer_length);
memset(buffer, 0x00, buffer_length);
strcpy(buffer, request_one);
strcat(buffer, content_length_string);
strcat(buffer, request_two);
strcat(buffer, padding);
strcat(buffer, retn);
strcat(buffer, shellcode);
strcat(buffer, request_three);

البرنامج بيخصّص مساحة للطلب النهائي، يمسحها، وبعدين يضيف مكوّنات متعددة بالترتيب: headers الطلب، طول المحتوى المحسوب، أجزاء طلب إضافية، بلوك الـ padding، الـ return pointer المختار، الـ payload، وبيانات إغلاق الطلب.

☠ Root Cause: Off-by-One

بما إن الـ padding اتحوّل لنص null-terminated، بس الحروف اللي قبل الـ null byte هي اللي بتتضاف. رغم إن حجم التخصيص كان 780 بايت، الـ padding القابل للاستخدام بقى 779 حرف، لأن آخر بايت بقى الآن هو الـ terminator.

التفصيلة الدقيقة دي بتفسّر ليه الكتابة فوق العنوان فاتت موقعها المقصود — الإكسبلويت كان فعليًا ناقص بايت واحد بالظبط.

تصحيح الإزاحة

الحل بسيط: نخصّص بايت إضافي واحد عشان طول النص الفعلي يطابق الـ offset المطلوب.

c
int initial_buffer_size = 781;
char *padding = malloc(initial_buffer_size);
memset(padding, 0x41, initial_buffer_size);
memset(padding + initial_buffer_size - 1, 0x00, 1);

بالتعديل ده، الـ padding دلوقتي بيحتوي 780 حرف "A" بالإضافة للـ null المنهي، وبيعيد المسافة الصحيحة للـ return address، ممكّن تحكّم دقيق في تدفّق التنفيذ.

التحقق من الإصلاح

1
إعادة التجميع

باستخدام الـ cross-compiler القادر على إنتاج Windows executables من Linux

2
بدء Listener

لاستقبال الاتصال العكسي (مثلًا Netcat على بورت 443)

3
تأكيد تشغيل الخدمة

التأكد إن خدمة Sync Breeze العرضة للاستغلال شغّالة على نظام الهدف

4
تنفيذ الإكسبلويت

تشغيل الـ binary (على Linux، ممكن عبر Wine لتشغيل برامج Windows)

بمجرد التحفيز، الإكسبلويت بيبعت الطلب المصاغ، والـ overflow بيحصل في الموقع الصح، والـ payload بينفّذ.

✓ النتيجة الناجحة

لما الـ listener يستقبل اتصال داخل، ده بيدّل على إن الـ payload اتنفّذ بنجاح وفتح command shell على جهاز الهدف. المهاجم دلوقتي عنده وصول command-line عن بعد. ميزة إضافية للإكسبلويت المُحسَّن ده هي قابلية النقل (portability): مابقاش محتاج Windows attack host وممكن يتطلق مباشرة من بيئة اختبار اختراق زي Kali Linux.

$ cat ./lu3_takeaways.txt

04إكسبلويتات تطبيقات الويب

أهداف الوحدة

1تعديل كود إكسبلويت بيستهدف تطبيقات ويب
2تشخيص وحل أعطال شائعة أثناء تشغيل الإكسبلويتات دي

على عكس ثغرات memory corruption، عيوب تطبيقات الويب عادةً مابتعملش كراش للبرامج أو تتلاعب بالذاكرة مباشرة. بسبب كده، حمايات نظام التشغيل زي DEP أو ASLR عادةً ما بتتدخّلش. نتيجة لكده، إكسبلويتات الويب غالبًا أسهل في التعديل وإعادة الاستخدام. مع ذلك، الاستغلال الناجح لسه يقدر يكشف محتوى قاعدة بيانات حساس أو حتى يوفّر تنفيذ أوامر على السيرفر.

اعتبارات أساسية قبل تعديل إكسبلويت ويب

رغم إن إكسبلويتات الويب ممكن تبان أبسط، تعديلها لسه بيحتاج مراجعة كود دقيقة. قبل إجراء تغييرات، المُقيّم لازم يحلّل إزاي الإكسبلويت بيتفاعل مع التطبيق المستهدَف عن طريق سؤال نفسه:

مهم كمان نتذكّر إن الإكسبلويتات المنشورة للعامة نادرًا ما بتاخد بالاعتبار إجراءات دفاعية زي قواعد سيرفر مخصَّصة أو web application firewalls. الحمايات دي مش معروفة للمؤلف الأصلي وممكن تمنع أو تعدّل الطلبات أثناء الاختبار الحقيقي.

سيناريو عملي: تعديل إكسبلويت عام — CMS Made Simple

✎ بيئة السيناريو

تقييم فيه سيرفر Linux بيشغّل خدمة Apache. الـ enumeration كشف تثبيت CMS Made Simple v2.2.5، متاح عبر بورت TCP 443. الأبحاث بتوضّح إن الإصدار ده فيه ثغرة remote code execution وله إكسبلويت عام متاح. رغم إن الاستغلال محتاج بيانات اعتماد صالحة، تفاصيل دخول إدارية اتحصّل عليها قبل كده أثناء الاستطلاع.

1. تصحيح الـ Base URL

python / before
base_url = "http://192.168.1.10/cmsms/admin"
python / after
base_url = "https://192.168.50.120/admin"

التغيير ده بيحاذي الإكسبلويت مع عنوان IP الصحيح، المسار، واستخدام HTTPS.

2. التعامل مع شهادات SSL غير صالحة

أثناء تصفّح الموقع، المختبر بيواجه خطأ تحقق شهادة بيوضّح إن السيرفر بيستخدم شهادة غير موثوقة. بما إن الإكسبلويت بيعتمد على مكتبة Python requests، التحقق من SSL لازم يتعطّل عشان نمنع فشل الاتصال. كل طلب POST في السكربت بيتعدّل بإضافة:

python
verify=False

ده بيوجّه المكتبة إنها تتجاهل أخطاء التحقق من الشهادة وتكمّل الاتصال.

3. تحديث بيانات اعتماد التوثيق

python / before
username = "admin"
password = "password"
python / after
username = "admin"
password = "HUYfaw763"

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

إزاي الإكسبلويت بيشتغل بعد التعديل

بعد التعديل، الإكسبلويت بينفّذ التسلسل ده:

  1. بيتوثّق للواجهة الإدارية
  2. برفع ملف نصي فيه كود خبيث
  3. بينسخ أو بيعيد تسمية الملف لسكربت قابل للتنفيذ على السيرفر
  4. بيوفّر رابط ممكن نبعت منه أوامر للتنفيذ عن بعد

العملية دي فعليًا بتحوّل ثغرة authenticated لـ remote command execution كامل.

مواجهة خطأ تنفيذ: IndexError عند CSRF Token

لما السكربت المعدَّل بيتشغّل، التوثيق بينجح، لكن خطأ runtime بيحصل أثناء معالجة CSRF token المستخرَج من رد الـ redirect بتاع السيرفر. الخطأ بيوضّح إن السكربت حاول يوصل لعنصر قائمة مش موجود.

منهجية استكشاف الأخطاء — "Index Out of Range"

1
تحديد مكان الخطأ

مفسّر Python أبلغ إن الفشل حصل جوه الدالة المسؤولة عن استخراج CSRF token من URL. السطر المشكوك فيه بيستخدم ميزة تقسيم النصوص في Python (split()) لفصل URL حسب اسم معطى معين وبعدين يوصل للعنصر التاني في القائمة الناتجة.

تقسيم نص لثلاث أجزاء بيدّي indices 0، 1، 2. محاولة الوصول لـ index 1 لما جزء واحد بس موجود هيسبّب IndexError.

2
فهم إيه اللي الكود كان متوقِّعه

الإكسبلويت افترض إنه بعد التوثيق، السيرفر هيوجّه المتصفح لرابط فيه معطى معين بيُستخدم كـ anti-CSRF token. السكربت كان متوقِّع حاجة زي:

url
https://target/admin?__c=TOKEN_VALUE

وكان مخطَّط يقسّم الـ URL عند "__c=" ويستخرج التوكين من الجزء التاني. لو المعطى ده مش موجود في الـ URL، التقسيم بيُنتج جزء واحد بس — وده بيسبّب الكراش.

3
فحص رد السيرفر الفعلي

بدل التخمين، بنطبع النص الحقيقي اللي التطبيق بيرجّعه قبل معالجته — خطوة debugging مهمة جدًا في تعديل الإكسبلويتات. بعد إضافة print، السكربت كشف الـ URL الفعلي للـ redirect:

url
https://target/admin?_sk_=TOKEN_VALUE

دلوقتي بنشوف المشكلة بوضوح: الإكسبلويت افترض المعطى الغلط. التطبيق بيستخدم اسم معطى مختلف.

4
تحديد السبب الجذري

ليه ده ممكن يحصل؟ أسباب واقعية متعددة: (1) إصدار سوفت وير مختلف عن اللي مؤلف الإكسبلويت استخدمه، (2) اختلافات إعداد التطبيق، (3) تحديثات أمنية غيّرت أسماء المعطيات، (4) توطين (localization) أو تخصيص. في المهمات الحقيقية، اختلافات كده طبيعية.

5
تعديل الإكسبلويت للهدف

بما إن السيرفر بيستخدم _sk_ بدل __c، بنحدّث المتغيّر جوه الإكسبلويت تبعًا لكده. ده بيحاذي السكربت مع سلوك تطبيق الهدف. بعد التعديل، منطق الاستخراج بيطلع التوكين صح.

6
إعادة تشغيل الإكسبلويت ومراقبة السلوك

بعد تطبيق الإصلاح: التوثيق بينجح، خطوة رفع الملف بتتنفّذ، ملف الـ payload بيتنسخ/يتغيّر اسمه، والإكسبلويت بيبلّغ عن نجاح. ده بيأكّد إن مشكلة الـ parsing كانت العائق الوحيد.

7
التحقق من الاستغلال الناجح

متوثقش في خرج الإكسبلويت بس — دايمًا تحقّق يدويًا. web shell اترفع، فنتفاعل معاه بإرسال طلب أمر. تنفيذ أمر نظام بسيط زي فحص المستخدم الحالي بيأكّد تنفيذ الأوامر عن بعد. لو الأمر رجّع حساب مستخدم سيرفر الويب (مثلًا www-data على أنظمة Linux)، الاستغلال مؤكَّد.

الدروس الأساسية لمهمات حقيقية

1دايمًا تحقّق من الافتراضات — الإكسبلويتات العامة بتفترض بيئة محددة نادرًا ما تطابق الهدف الحقيقي بالظبط
2الـ Debugging أساسي — إضافة بيانات خرج مؤقتة غالبًا أسرع طريقة لفهم الأعطال
3توقّع اختلافات الإصدار — حتى تحديثات بسيطة ممكن تغيّر أسماء معطيات، تدفّقات توثيق، وصيغ ردود
4مهارات التكيّف أهم من الأدوات — المختبرين الممتازين بينجحوا لأنهم يقدروا يعدّلوا ويستكشفوا أعطال الإكسبلويتات، مش بس يشغّلوها
★ Professional Mindset

لما إكسبلويت يفشل: حدد الخطأ بالظبط ← افهم إيه اللي الكود كان متوقِّعه ← افحص سلوك التطبيق الفعلي ← حدد التباين ← عدّل تبعًا لكده ← تحقّق من النجاح يدويًا.


05منهجية الـ 12 خطوة لإصلاح إكسبلويت عام

خطوات منظَّمة ممكن تتبعها كل ما إكسبلويت عام مش شغّال "زي ما هو":

01
تأكيد الثغرة وتفاصيل الهدف
حدد اسم السوفت وير والإصدار بالظبط، أكّد إن الخدمة متاحة (بورت، بروتوكول، مسار)، وتحقق من متطلب التوثيق ونظام التشغيل/المعمارية
02
اقرأ توثيق وكود الإكسبلويت
راجع ملاحظات المؤلف، المعطيات المطلوبة، IPs/بورتات/بيانات اعتماد مُدمَجة، ونوع الـ payload — متشغّلش كود مجهول عمياني
03
أعِد إنتاج الفشل في بيئة متحكَّم فيها
شغّل الإكسبلويت ضد نظام اختباري، راقب رسائل الخطأ، فشل الاتصال، الكراشات، والردود غير المتوقَّعة
04
عدّل المعطيات الخاصة بالهدف
IP/hostname الهدف، البورت، البروتوكول، مسار التطبيق، بيانات الاعتماد، وcallback IP/port للـ reverse shells
05
عدّل الـ Payload لجهاز الهجوم بتاعك
حدّث IP الـ reverse shell لجهازك، اختار بورت مسموح عبر الـ firewalls، وعدّل نوع الـ shell لنظام الهدف
06
تعامل مع اختلافات البيئة
شهادات SSL ذاتية التوقيع، مجلدات تثبيت غير افتراضية، تطبيق خلف proxy أو WAF، وظائف معطَّلة أو صلاحيات مقيَّدة
07
صحّح سلوك الطلب/الرد (إكسبلويتات ويب)
استخدم أدوات اعتراض الترافيك، قارن الأفعال اليدوية بسلوك الإكسبلويت، وتأكد من وجود الـ headers والكوكيز والتوكينز المطلوبة
08
صلّح أخطاء المنطق أو الـ Parsing
افحص إزاي الإكسبلويت بيعالج ردود السيرفر، تحقق من الافتراضات عن البيانات المرجَعة، وحدّث دوال الـ parsing لو الصيغ مختلفة
09
أعِد التجميع أو التعبئة لو لازم
ثبّت المكتبات المطلوبة، صحّح أخطاء التجميع، وcross-compile لمنصة الهدف لو لازم
10
اختبر بشكل تدريجي
متشغّلش الإكسبلويت كامل فورًا — اختبر الاتصال، التوثيق، توصيل الـ payload، والتنفيذ كمراحل منفصلة
11
قلّل التأثير وحافظ على الاستقرار
تجنّب كراش خدمات إنتاجية، استخدم أقل الـ payloads تعطيلًا الأول، ونسّق مع أصحاب المصلحة لو فيه احتمال تعطّل
12
وثّق كل تعديل
احتفظ بملاحظات عن إيه اتعدّل، ليه كان ضروري، وإزاي الإكسبلويت النهائي بيشتغل — مفيدة للتقرير والمهمات المستقبلية
$ cat ./workflow_summary.txt

Cheat Sheet مرجعي

أوامر Cross-Compiling

الأمرالوظيفة
sudo apt install mingw-w64تثبيت toolchain التجميع المتقاطع لـ Windows
i686-w64-mingw32-gcc file.c -o file.exe -lws2_32تجميع C لـ Windows PE (32-bit) مع ربط مكتبة Winsock
x86_64-w64-mingw32-gcc file.c -o file.exe -lws2_32نفس الشيء لنسخة 64-bit
wine file.exeتشغيل Windows binary على Linux

تصنيف الحروف السيئة الشائعة (Bad Characters)

البايتليه مشكلة
\x00null byte — بينهي النص قبل الأوان في دوال زي strcpy/strcat
\x0a / \x0dline feed / carriage return — ممكن تكسر بروتوكولات نصية زي HTTP
\x25علامة % — ممكن تتفسّر كـ format specifier

مكوّنات بنية الـ Overflow Buffer

المكوّنالدور
Paddingيملا الـ buffer لحد الـ offset المطلوب (راعِ null terminator عند الحساب)
Return Addressيكتب فوق instruction pointer بعنوان تعليمة زي JMP ESP
NOP Sledيحسّن موثوقية الهبوط جوه الـ shellcode
Shellcodeالـ payload الفعلي (يُفضَّل يتولَّد بـ msfvenom مع استبعاد bad chars)

فحوصات سريعة لإكسبلويت ويب مش شغّال

العرَضالفحص الأول
فشل الاتصال فورًاbase_url صحيح؟ HTTP ولا HTTPS؟
خطأ شهادة SSLأضف verify=False في requests
فشل التوثيقبيانات الاعتماد مُحدَّثة؟ شكل الطلب صح؟
IndexError / KeyErrorاطبع الرد الفعلي — اسم المعطى أو بنية الرد اختلفت

الخلاصة العامة للموديول

في الموديول ده، غطّينا المقاطع الأساسية لإكسبلويت stack-based buffer overflow بسيط احتاج تعديل مكثّف عشان يطابق بيئة الهدف بتاعتنا. بعد كده عملنا cross-compile للكود عشان يشتغل من منصة الهجوم Kali بتاعتنا.

كمان عدّلنا إكسبلويت ويب عشان نوضّح إزاي الأنواع دي من الإكسبلويتات ممكن تتعاد استخدامها لبيئة هدف مختلفة.

السيناريوهات دي كاشفة لحلول عوائق شائعة بتواجه مختبري الاختراق لما بيتعاملوا مع إكسبلويتات عامة أثناء مهمة. الفرق بين إكسبلويت "مكسور" وإكسبلويت شغّال غالبًا بيكون تفصيلة صغيرة — offset غلط ببايت واحد، اسم معطى مختلف، أو شهادة SSL غير موثوقة — مش مشكلة في جوهر الثغرة نفسها.


نهاية نوتس الموديول الحادي عشر — OSCP: Fixing Exploits