تشغيل PowerShell في الذاكرة: وش يصير فعلًا، وليش هذا ما يعني أن الأداة صارت مخفية؟
تقرأ شرحًا لأداة Active Directory وتلقى عبارة In-Memory، فتتصور أنها تمر من الجدار الناري ولا يلاحظها نظام الحماية. هنا فيه خلط بين مكان وجود الكود، والاتصالات التي يفتحها، وطريقة فحصه وتسجيله. الذاكرة موضوع تنفيذ، والجدار الناري موضوع حركة شبكة، وAMSI وسجلات PowerShell ونظام حماية الطرفيات لهم مصادر رؤية مختلفة. خلنا نشرح الفكرة على وحدة تعليمية بسيطة لا تتصل بأي هدف ولا تفحص Active Directory. بعدها نربطها بطريقة تجهيز أدواتك في مختبر CRTP: مصدر واضح، إصدار معروف، فهم للصلاحيات، وأدلة يمكن مراجعتها بدل الاعتماد على كلمة مخفي.
المقصود بالذاكرة يعتمد على نوع الأداة
في PowerShell قد تكون الدالة مكتوبة مباشرة في الجلسة، أو تأتي من Script Module على القرص، أو تكون داخل Dynamic Module لا يحتاج ملف وحدة دائمًا. وفي أدوات .NET توجد مفاهيم تحميل وتشغيل مختلفة. جمع هذه كلها تحت عبارة تحميل في الذاكرة يخفي فروقًا مهمة في المصدر والعمر والتبعيات وسلوك النظام.
مقالنا يستخدم آلية PowerShell الموثقة New-Module لإنشاء وحدة من ScriptBlock. ما نتكلم عن حقن في عملية ثانية أو تغيير ذاكرة مكون حماية. مثالنا يعمل داخل الجلسة التي فتحتها أنت، ويصدر دالة تعطي معلومة محلية غير حساسة. بهذه الطريقة تقدر ترى الفكرة دون أن تضيف شبكة أو أسرار أو هدفًا خارجيًا إلى التجربة.
قبل تشغيل أي أداة تعليمية اسأل: ما نوعها؟ هل تعتمد ملفات أو مكتبات أخرى؟ ما إصدار المحرك المطلوب؟ هل تحفظ نتيجة على القرص؟ الإجابات تحدد التجربة. لو الأداة تقول In-Memory لكنها تكتب ملفًا للتقرير، فلا يوجد تناقض؛ مكان الوحدة ومكان النتائج موضوعان مختلفان، وكل واحد يحتاج قراءة مستقلة.
الجدار الناري ما يقرر مكان حفظ الكود
الجدار الناري يطبق قواعد على حركة الشبكة وفق قدراته وإعداداته. لو دالة تعمل محليًا ولا تفتح اتصالًا، فلا توجد حركة شبكة جديدة من هذه الدالة لكي تسمح بها قاعدة أو تمنعها. ولو أداة قراءة تتصل بـLDAP، فالحركة تظل اتصالًا له مصدر ووجهة وخدمة حتى لو الكود موجود في الذاكرة.
خلنا نفترض وحدتين تنفذان نفس استعلام القراءة المصرح: واحدة مثبتة كملف، والثانية دالة داخل جلسة. تغير شكل حفظ الكود لا يغير تلقائيًا حساب الاتصال أو صلاحياته أو هدفه. وقد تختلف بعض إشارات الطرفية، لكن لا تستطيع استنتاج عدم الرؤية من هذا الفرق وحده.
النقطة المهمة عند تشخيص فشل أداة: هل فشلت قبل الاتصال أم خلاله أم بعد وصول الرد؟ رسالة منع سياسة تطبيق ليست منع شبكة، ورفض LDAP بسبب التفويض ليس خطأ تحميل. تحديد المرحلة أوفر من تبديل طريقة التشغيل عشوائيًا، كما يمنعك من تعطيل حماية سليمة لأنك نسبت كل فشل إلى الجدار الناري.
AMSI والسجلات والطرفية يرون جوانب مختلفة
AMSI واجهة يرسل إليها تطبيق داعم محتوى لفحصه بواسطة محرك مكافحة برمجيات ضارة. توضح Microsoft أن PowerShell على Windows يمرر ScriptBlocks إلى AMSI في الإصدارات والأنظمة المدعومة. أما Script Block Logging فيسجل محتوى عند تفعيل إعداداته، ومراقبة الطرفيات قد تضيف أحداث عمليات واتصالات وسلوكيات أخرى.
هذه ليست قائمة ضمانات أن كل جهاز يرى كل شيء. التغطية تعتمد الإعداد والإصدار والمحرك وتجميع الأحداث. لذلك تجربتك التعليمية تقيس البيئة المحددة: ما الحدث الذي ظهر؟ أين ظهر؟ ما الوقت؟ وما الدليل الذي لم يكن متاحًا؟ لا تكتب قاعدة عامة من لقطة واحدة أو من غياب تنبيه في شاشة محلية.
كذلك السماح بتشغيل مثال سليم لا يثبت فشل AMSI؛ المقصود من الحماية ليس منع كل PowerShell. وظهور 4104 لا يعني أن محرك الفحص أصدر تنبيهًا. فصل التسجيل عن التصنيف عن المنع يعطيك فهمًا أفضل أثناء مختبر Active Directory، ويجنبك تقريرًا يساوي النجاح الوظيفي بعدم قدرة الدفاع على الرؤية.
جهز جلسة مختبر يمكن تكرارها
استخدم جهازًا تملكه أو جهاز مختبر مصرحًا، وسجل إصدار PowerShell قبل التجربة. الأمر $PSVersionTable يعرض معلومات المحرك. سجل أيضًا ما إذا كانت الجلسة محلية أو بعيدة، وهل هناك سياسة Application Control معتمدة. لا تغير السياسة لكي تتوافق مع المثال؛ لو منعت وظيفة معينة، فهذا جزء من النتيجة التي تشرحها.
الأمر $ExecutionContext.SessionState.LanguageMode يبين وضع اللغة في الجلسة التي تقرأه فيها. لا تعتبره وصفًا لكل الجلسات على الجهاز، ولا تدعي أن FullLanguage تعني غياب وسائل حماية. هو معلومة عن سياق التنفيذ الحالي، تحتاج ربطها بمصدر السياسة وسلوك الملف أو الوحدة المحددة.
حدد وقت البداية والنهاية واختر اسم دالة فريدًا حتى لا تصطدم بدالة موجودة. في التجربة التالية سنستخدم Get-CyberPTSLabMarker. هي دالة تعرض اسم الجهاز والعملية الحالية فقط، ولا تقرأ أسرارًا ولا تستعلم شبكة. اختيار مثال محدود يساعدك تميز أثر الوحدة من نشاطات أخرى في الجلسة ويجعل المقارنة أسهل.
مثال وحدة ديناميكية بسيطة
في جلسة مختبر محلية تقدر تستخدم هذا السطر التعليمي: $labModule = New-Module -Name CyberPTSLab -ScriptBlock { function Get-CyberPTSLabMarker { "Lab computer: $env:COMPUTERNAME; process: $PID" }; Export-ModuleMember -Function Get-CyberPTSLabMarker } . ثم استدع الدالة باسمها: Get-CyberPTSLabMarker . المثال ينشئ وحدة ودالة تصدر نصًا، دون اتصال أو تعديل إعدادات.
اقرأ النتيجة بدل الاكتفاء بأنها اشتغلت. اسم الجهاز يربطها بالسياق المحلي، ورقم العملية يبين العملية التي نفذت الدالة. لو كنت في جلسة بعيدة، قد تكون البيئة المعروضة للجهة البعيدة، فلا تنسبها إلى جهازك المحلي دون فهم السياق. ولا تحتاج صلاحيات مسؤول لهذا المثال في جلسة عادية تسمح به السياسة.
إذا ظهر رفض في بيئة مقيدة، احتفظ بالرسالة والإصدار ووضع اللغة ووقت المحاولة. لا تتجاوز السياسة ولا تبدل المثال إلى Loader. هدفنا فهم نموذج الوحدة، لا الوصول إلى نتيجة تشغيل بأي وسيلة. يمكن إعادة التجربة على مختبر مخصص يسمح بهذا الاستخدام مع المحافظة على إعدادات الحماية المعتمدة فيه.
ليش Get-Command يراها وGet-Module قد لا يعرضها؟
هنا نقطة مفيدة موثقة في New-Module: الوحدة الديناميكية موجودة في الذاكرة، ودوالها المصدرة يمكن اكتشافها بـGet-Command، لكن Get-Module لا يعرض الوحدة الديناميكية مباشرة بنفس الطريقة ما لم تُستورد في قائمة الوحدات. لذلك اختلاف القائمتين لا يعني اختفاء الكود أو خطأ في الأمر.
اقرأ الدالة باستخدام Get-Command Get-CyberPTSLabMarker، وانظر إلى CommandType وما يحدد مصدرها. بعدها يمكنك استيراد كائن الوحدة الذي أنشأته بالأمر $labModule | Import-Module، ثم قراءة Get-Module CyberPTSLab. الاستيراد هنا يسجل الوحدة للجلسة، ولا يحولها تلقائيًا إلى ملف دائم على القرص.
هذه التجربة تعلمك كيف تقرأ حالة المحرك بدل حفظ أمر تحميل. في أدوات المختبر، لو توقع شرح وجود Module ولم تظهر، راجع هل الدوال أُنشئت مباشرة، وهل هناك استيراد، وهل الاسم صحيح. لا تستنتج أن الأداة فشلت أو نجحت في التخفي من مخرج واحد لا يقيس أصلًا كل الأشكال التي يمكن للدوال أن توجد بها.
عمر الجلسة وحدود Scope
الوحدة الديناميكية ليست تثبيتًا دائمًا. وجودها مرتبط بالجولة الحالية وسياقها، ودوال الوحدة لها نطاق داخلي يساعد تنظيم المتغيرات والمساعدة. إغلاق الجلسة يغير الحالة، وجلسة جديدة لا يفترض أن تحتوي الدالة لمجرد أن جلسة سابقة احتوتها. هذا مفيد لبناء تجربة قابلة للضبط.
بعد نهاية المثال أزل الوحدة المستوردة بالاسم باستخدام Remove-Module CyberPTSLab إذا كنت استوردتها، ثم أغلق جلسة المختبر. إزالة الوحدة هنا تنظيف لتعريف تعليمي داخل المحرك، وليست إزالة للسجلات أو نتيجة مراقبة. لا تحذف أحداث النظام؛ تبقى جزءًا من الدليل وتساعدك على مقارنة ما حدث أثناء التجربة.
في تدريب CRTP، يتسبب خلط الجلسات في أخطاء عملية: دالة موجودة في نافذة، وغير موجودة في نافذة ثانية؛ هوية مختلفة في جلسة بعيدة؛ أو متغير نتيجة يحتفظ بمعلومة قديمة. سجل الجلسة والهوية والوقت واسم الأداة. فهم Scope وعمر النتائج يمنعك من قراءة بيانات قديمة كأنها استجابة جديدة من الدليل.
مصدر الأداة أهم من طريقة تحميلها
طريقة التشغيل لا تعوض مراجعة المصدر. قبل إدخال أداة Active Directory إلى المختبر، راجع المستودع الرسمي والإصدار والملفات المطلوبة، وطابق التجزئة إن قدمها المشروع أو إجراء المؤسسة. اقرأ وظيفة الأوامر التي تنوي استخدامها، خصوصًا هل هي قراءة أم تعديل أم اتصال واسع إلى أجهزة.
لا تنفذ نصًا جلبته من رابط مجهول داخل الجلسة مباشرة. وجود النص في الذاكرة لا يجعله أكثر أمانًا، كما أن امتداد الملف وحده لا يحكم على محتواه. الأفضل الحصول على نسخة معروفة ومراجعتها وفق إجراء المختبر، ثم تشغيل الوظائف المسموحة بعامل وصول محدود.
خلنا نفترض أن شرحًا قديمًا يستخدم اسم دالة تغير في نسخة حديثة. تحميل النص بطريقة مختلفة لن يصحح اختلاف الوظيفة. اقرأ Get-Command والمساعدة الموجودة للإصدار وتحقق من نوع الكائن الناتج. ما تحتاجه في المختبر هو أداة مفهومة يمكن تفسيرها وتكرارها، لا وصف عام أنها سريعة أو لا تحتاج تثبيتًا أو يصعب على الآخرين رؤيتها.
ضع قياس الرؤية داخل التجربة
اطلب من فريق الدفاع في مختبرك مصادر القراءة المسموحة: سجل PowerShell المناسب للإصدار، أحداث العملية، أو نتيجة مراقبة مركزية. استخدم وقت التجربة واسم الدالة الفريد لربطها. لا تضع كلمات مرور أو رموز وصول في المثال؛ قد تظهر النصوص المدخلة في سجلات لا تتوقعها.
قارن ثلاث نتائج منفصلة: نجحت الدالة، ظهر أثر تسجيل، وظهر أو لم يظهر تنبيه. لا تجمعها تحت نجحت الحماية أو فشلت. مثال سليم يفترض عادة أن يعمل إن سمحت السياسة، ولا يلزم أن يولد تنبيهًا. التسجيل يمكن أن يظل مفيدًا للتحقيق حتى عندما لا يوجد حدث مصنف كتهديد.
لو لم تجد السجل، راجع اسم القناة والإصدار وصلاحية القراءة وتجميع الأحداث قبل أن تقول لا يوجد أثر. وقد يتأخر ظهور الحدث في المنصة المركزية عن ظهوره محليًا. احفظ الملاحظة بحدها: لم يظهر حدث في المصدر الذي راجعناه خلال الفترة المحددة. هذه جملة أدق من لا يمكن اكتشاف التنفيذ في الذاكرة.
التشخيص بالمرحلة، مو بتغيير كل شيء
إذا فشل المثال، ابدأ بأبسط تفسير مدعوم: خطأ كتابة، اسم دالة متعارض، وضع لغة مقيد، أو فرق إصدار. لا تقفز إلى مشكلة شبكة لأن التجربة لا تحتاج شبكة أصلًا. وإذا نجح المثال وفشلت أداة أخرى، فقارن المتطلبات؛ نجاح دالة نصية لا يثبت أن مكتبات الأداة الثانية وتبعياتها متاحة.
اختبر تغييرًا واحدًا في كل مرة داخل نطاقك: اسم الدالة، جلسة نظيفة، أو إصدار موثق يناسب الأداة. حافظ على سياسة الحماية، وسجل النتيجة قبل وبعد. بهذه الطريقة تعرف سبب الفرق ولا ينتهي بك الأمر إلى بيئة تغيرت فيها عدة إعدادات ثم لا تقدر تفسر لماذا اشتغلت.
الأخطاء التقنية نفسها مادة تعلم جيدة. رسالة تتعلق بالوحدة تختلف عن رفض اتصال LDAP، ورفض تفويض يختلف عن عدم وجود خدمة. المختبر الذي يعرف أين توقف المسار يختار الخطوة التالية بهدوء، ويقدر يشرحها في التقرير. أما تكرار التحميل بطرق مختلفة فقد يخفي السبب ويخلق نشاطًا زائدًا بلا سؤال واضح.
كيف تستفيد من الفكرة في تدريب Active Directory؟
استخدم فهم الجلسة والوحدات لتنظيم عملك، ثم ركز على السؤال الأمني الذي تحتاج الأداة للإجابة عنه. إذا كان السؤال عضوية حساب مختبر، اختر وظيفة قراءة محدودة وقارن المخرج مع أداة إدارة معتمدة. لا تجعل تجربة تحميل الوحدة بديلًا عن فهم الخصائص التي تقرأها وصلاحيات الهوية التي تستعلم بها.
دوّن اسم الأداة والإصدار والهوية وهدف القراءة والنتيجة ونوع الكائن. وسجل هل الاتصال يستخدم حساب الجلسة أم اعتمادًا صريحًا وفره مالك المختبر. حين تختلف النتائج بين أداتين، ارجع إلى Base والفلتر والخصائص والتوقيت، لا إلى طريقة التحميل باعتبارها التفسير التلقائي.
هذا هو الجزء المفيد في أي تدريب عملي، ومنها مختبرات CRTP المصرح بها: تعرف بيئتك، تقلل حجم السؤال، وتفسر النتيجة قبل الانتقال. لا توجد هنا تجربة امتحان شخصية أو ادعاء أن إعدادًا معينًا مطلوب في نسخة الاختبار. تفاصيل المختبر والشهادة تُراجع من مقدمها، بينما أساس PowerShell يساعدك عبر سيناريوهات كثيرة.
المراجع وما الذي يأتي بعد هذا المقال؟
التشغيل في الذاكرة يصف مكانًا أو شكلًا لوجود الكود، ولا يثبت غياب ملفات نتائج أو سجلات أو مراقبة شبكة. تجربة New-Module البسيطة تعطيك نموذجًا واضحًا للدوال والنطاق وعمر الجلسة بدون دخول في أي أسلوب لتجاوز الحماية. الخطوة التالية هي قراءة مصادر الرؤية نفسها، خصوصًا AMSI وScript Block Logging.
مرجع New-Module وسلوك Get-Command وGet-Module: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/new-module . مرجع ميزات حماية PowerShell: https://learn.microsoft.com/en-us/powershell/scripting/security/security-features . ووضع اللغة موضح هنا: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_language_modes .
راجع المصادر حسب نسخة المحرك والنظام، ثم كرر المثال السليم وسجل ما رأيته فعلًا. المعرفة التي تستحق الاحتفاظ بها ليست سطرًا يُحمّل أداة، بل قدرتك على وصف أين يعمل الكود، ومن ينفذه، وما الذي يفعله، وأي دليل يثبت ذلك. بهذا تصير أدوات Active Directory أوضح وأسهل للتشخيص داخل نطاق اختبارك.