انتقل إلى المحتوى

Persistence Hunter

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

juntei persistence-hunter منفَذ أصلي (native) بلغة Rust لأداة PyrsistenceSniper من Hexastrike، ويتضمن 131 فحصًا: فهرس PyrsistenceSniper المكوّن من 130 فحصًا إضافةً إلى فحص أصلي لـ COM في قائمة "ابدأ".

للاطلاع على شرح كل آلية، ومواقع أدلتها، وكيفية التحقيق في النتيجة، راجع دليل الاستمرارية ذي الـ 131 فحصًا. وتصف صفحة شكر وتقدير الخاصة بالاستمرارية مشروعات Python وPowerShell التي يقوم عليها الفهرس.

الاستخدام

Version: 1.1.0 (CODE BLUE Release)
Yamato Security (https://github.com/Yamato-Security/juntei - @SecurityYamato)

Usage:
  juntei persistence-hunter -d <EVIDENCE> [OPTIONS]

Input:
  -d, --directory <DIR>  Evidence directory (a mounted Windows volume or a collection of hosts)
  -f, --file <FILE>      One registry hive (filesystem checks need a directory)
      --no-logs          Read dirty hives without replaying transaction logs

Filtering:
      --profile <FILE>               Replace the bundled allow/block profile with a YAML profile
      --min-severity <MIN_SEVERITY>  Minimum classification to include: info, low, medium, high [default: medium] [possible values: info, low, medium, high]
      --check <ID>                   Run only these check or ATT&CK IDs (comma separated; repeatable) [alias: --technique]

General Options:
  -h, --help         Show the help menu
      --list-checks  Show every available check and its ATT&CK technique

Analysis:
      --no-timeline  Skip MFT and event-log timestamp correlation
      --mft <FILE>   MFT to use for timestamp correlation (one host only)

Performance:
  -T, --threads <N>  Worker threads (default: logical CPU count)

Output:
  -o, --output <FILE>              Save findings to a file
  -t, --output-type <OUTPUT_TYPE>  Output type: csv (default), json, jsonl; without -o, write data to stdout [possible values: csv, json, jsonl]
      --coverage <FILE>            Save per-check coverage and errors to CSV
  -C, --clobber                    Overwrite output files

Display Settings:
  -K, --no-color  Disable color output
  -q, --quiet     Quiet mode: do not display the launch banner

الفحص الأول

juntei persistence-hunter -d evidence/ -o PersistenceHunter.csv --coverage Coverage.csv

يمكن أن تكون الأدلة وحدة تخزين Windows مركّبة، أو مجموعة Velociraptor، أو مجلدًا يحتوي على عدة حواسيب جرى جمعها. وتبقى الحواسيب منفصلة أثناء التحليل، وتتضمن كل نتيجة Comp. ويُفك ترميز رموز الهروب في أسماء الملفات المجمّعة عند حل مسارات Windows.

لخلية واحدة:

juntei persistence-hunter -f SOFTWARE -o software-persistence.csv --no-timeline

لا يمكن لخلية واحدة أن تلبي الفحوص التي تحتاج إلى خلية أخرى أو إلى أدلة من نظام الملفات. اقرأ تقرير التغطية قبل التعامل مع نتيجة فارغة على أنها ذات دلالة.

اسرد معرّفات الفحوص وتعييناتها في ATT&CK:

juntei persistence-hunter --list-checks
juntei persistence-hunter -d evidence/ --check run_keys,windows_service_image_path -o focused.csv

استخدم معرّفات الفحوص التي يطبعها --list-checks، أو معرّف ATT&CK مثل T1547.001. ويحدد المعرّف الأب مثل T1547 تقنياته الفرعية. و--technique اسم بديل لـ --check. ويتضمن كل فحص تقنيته ووصفه وروابطه المرجعية في النتائج.

الفحوص المتوازية

يستخدم الأمر مجمّع عمّال مشتركًا، يساوي افتراضيًا عدد وحدات المعالجة المنطقية. اضبط -T, --threads <N> لاختيار عدد العمّال، أو -T 1 لفحص بخيط تنفيذ واحد:

juntei persistence-hunter -d evidence/ --min-severity info -T 4 -o PersistenceHunter.csv

يجري اكتشاف الأدلة، والفحوص المستقلة، والبيانات الوصفية للحمولات، ومصادر الجدول الزمني من MFT/EVTX بالتوازي. وتُشارَك خلايا سجل Windows المحمّلة لمضيف ما للقراءة فقط، وتُهيّأ البيانات الوصفية المخزنة مؤقتًا للحمولة نفسها مرة واحدة. وتُحمَّل المضيفات واحدًا تلو الآخر لتجنب مضاعفة ذاكرة الخلايا عبر المجموعة. وتبقى النتائج، والتغطية، واختيار الطوابع الزمنية، وترتيب التحذيرات كما هي عند اختلاف عدد الخيوط.

يشغّل auto-parse عمليات المحللات بالتوازي أصلًا، لذا يمنح كل عملية فرعية من persistence-hunter عاملًا واحدًا. ويتحكم خيار -T الخاص به في عدد عمليات المحللات المتزامنة.

الأدلة الواجب جمعها

المصدر أمثلة على الفحوص
SYSTEM وسجلات المعاملات المجاورة الخدمات، وأوامر استرداد الخدمات، وحزم LSA، وإعدادات الإقلاع، وموفرو المصادقة
SOFTWARE وسجلات المعاملات المجاورة مفاتيح Run، وWinlogon، وIFEO، وتسجيلات COM، وTaskCache، وإعدادات Office
ملفا NTUSER.DAT وUsrClass.dat لكل مستخدم التشغيل التلقائي للمستخدم، ومتغيرات البيئة، وتجاوزات COM، وإعدادات Office
SAM وSOFTWARE حالات شاذة في RID، والحسابات المخفية، والعضوية غير المعتادة في مجموعة Administrators المحلية
Windows/System32/Tasks أوامر المهام المجدولة ومعالجات COM؛ والمقارنة مع TaskCache
ملفات .library-ms في قائمة "ابدأ" لكل مستخدم والمجلدات المسماة بمعرّفات CLSID مرشحات مشغّلات تنشيط COM، مربوطة بتسجيلات الفئات المطابقة على مستوى المستخدم/الجهاز
مجلدات Startup، وملفات تعريف PowerShell، وقوالب Office، وإعدادات Terminal الملفات والأوامر التي تشغّلها مشغّلات المستخدم أو النظام
ملف WMI ‏OBJECTS.DATA مثيلات مستهلكي الأحداث وروابط المرشحات بالمستهلكين
BITS ‏qmgr.db أو qmgr*.dat أوامر الإشعارات المستردة ومعرّفات SID للمالكين
$MFT وملفات EVTX ذات الصلة ربط مستقل للطوابع الزمنية
الملفات التنفيذية وملفات DLL وملفات الكتالوج المشار إليها تجزئات SHA256 والبيانات الوصفية الوصفية لـ PE/الشهادات

تُعاد تطبيق سجلات معاملات سجل Windows عند توفرها. ويقرأ --no-logs الخلايا كما جُمعت؛ وقد تُسقط الخلية غير النظيفة التي لم يُعد تطبيق سجلاتها تغييرات حديثة، ويُبلَغ عنها في التغطية. وتُستخدم مجموعة التحكم الحالية لفحوص النظام النشط. ويفحص فحص الباب الخلفي DSRM إضافةً إلى ذلك ControlSet001 وControlSet002 وCurrentControlSet عند وجودها؛ فتحقق من المسار الذي يُبلغ عنه مقابل SYSTEM\\Select قبل وصف ذلك الإعداد بأنه نشط. ويمكن فحص مجموعات التحكم التاريخية الأخرى باستخدام أوامر محللات سجل Windows الفردية.

تتشارك قراءات الخلايا ميزانية إدخال قدرها 1 GiB لكل حاسوب. وتُجرَّب خلايا الجهاز قبل خلايا المستخدمين؛ ويُذكر في التغطية الجزئية اسم المدخلات أو سجلات المعاملات التي لا تتسع لها الميزانية. وتستمر الخلايا الأخرى القابلة للقراءة والفحوص المعتمدة على الملفات. ولا تثبت هوية الخلية إلا المواقع القياسية للخلايا أو الملفات المصدّرة الممرّرة صراحةً؛ فلا يمكن لنسخة داخل المجلد المؤقت لمستخدم ما أن تحل محل الخلية الحقيقية لذلك المستخدم. ويُعيَّن محرك أقراص النظام الأصلي المسجل في SOFTWARE إلى وحدة تخزين النظام الملتقطة، لذا فإن تركيب وحدة تخزين C: أصلية تحت تسمية محرك أقراص أدلة مختلفة لا يُسقط البيانات الوصفية للحمولات.

يشغّل auto-parse أيضًا أداة البحث ويحفظ persistence/PersistenceHunter.csv (أو .json/.jsonl) داخل مجلد كل حاسوب، مع PersistenceHunter-logs.txt بجواره. وتدخل نتائجه أيضًا في الجدول الزمني الاختياري لـ SIEM ‏-j <FILE>. ويستخدم التحليل التلقائي --min-severity info للاحتفاظ بالجرد الكامل للتكوين، بما في ذلك الإدخالات التي تطابقها قواعد السماح.

تسجيلات COM ومشغّلات التنشيط

يختار الفحص scheduled_task_files الجهة الأساسية (principal) لكل إجراء باستخدام Actions Context في ملف XML للمهمة وPrincipal id المطابق. وتُحفظ الجهة الأساسية التي تكون مجموعةً بوصفها مجموعة؛ إذ لا يمكنها تحديد تسجيلات الفئات الخاصة بأي مستخدم بعينه ستُستخدم.

تُحل مرشحات معالجات COM بشكل منفصل في طريقتي عرض الفئات الأصلية وذات 32 بت. ولا يُنظر إلا في UsrClass.dat/NTUSER.DAT الملتقطين للمستخدم المطابق وفي SOFTWARE الخاصة بالجهاز. وتُربط الجهات الأساسية المحددة بمعرّف SID عبر مسارات ProfileList الملتقطة. وتفضّل أسماء الحسابات، بما فيها HOST\user وDOMAIN\user، ملف التعريف المطابق user.DOMAIN على ملف التعريف البسيط user. وتستخدم الأسماء البديلة للمضيف المحلي و.\user أسماء المضيفين الملتقطة لمطابقة اللاحقة؛ وتتقدم اللاحقة المطابقة تمامًا على الأسماء البديلة الأخرى للمضيف. ولا يُنظر في ملف التعريف البسيط إلا عندما لا يطابق أي ملف تعريف مؤهَّل. وتُوسم كل مطابقة من هذا النوع صراحةً بأنها استدلال قائم على اسم المجلد في Description؛ وهي لا تثبت ملكية الحساب أو العضوية في المجال. وتبقى المطابقات الملتبسة دون حل ويُبلَغ عنها في كل من وصف النتيجة والتغطية؛ ولا يؤدي الالتباس بين ملفات التعريف المؤهلة إلى الرجوع إلى ملف التعريف البسيط. ولا يعتمد ذلك على Volatile Environment، الذي يكون عادةً في الذاكرة فقط ولا يُحفظ مع خلايا سجل Windows. ويحجب معرّف CLSID المكرر لدى المستخدم العناصر الفرعية لمعرّف CLSID الخاص بالجهاز. وتستخدم الجهات الأساسية التي تكون مجموعات مرشحات COM الخاصة بالجهاز وتحتفظ بهذا القيد في وصف النتيجة؛ ولا تجعل الجهة الأساسية العادية التي تكون مجموعةً التغطيةَ جزئية في حد ذاتها ولا تستهلك إدخالات ملخص الأخطاء.

يتتبع المحلِّل InprocServer32 وLocalServer32، ويستخدم مسارات CodeBase المُدارة (بما فيها المفاتيح الفرعية للإصدارات)، ويربط LocalService الخاص بـ AppID بقيمة ImagePath للخدمة في خلية SYSTEM المجمّعة. وتُحفظ ارتباطات أسماء الملفات التنفيذية في AppID، لكن الاسم الأساسي (basename) لا يحدد المسار الكامل للملف التنفيذي. ويُفك ترميز عناوين URL المحلية file: في CodeBase؛ وتُسجَّل عناوين URL البعيدة دون الوصول إليها. وتحتفظ التسجيلات المفقودة بمعرّف CLSID مع ResolutionStatus: unresolved_com_class، وحقول مسار/تجزئة فارغة، وقيمة Exists غير معروفة.

يقرأ الفحص start_menu_com عناوين URL في ملفات XML ‏.library-ms في قائمة "ابدأ" لكل مستخدم ويجمع المجلدات المسماة بمعرّفات CLSID، بما فيها المجلدات الفارغة. ويُبلغ عن مسار المشغّل، ومعرّف CLSID، والخادم المرشح، ومصدر سجل Windows. ولا يمكن لعملية اكتساب تقتصر على الملفات أن تحفظ مجلدًا فارغًا، وتحول خلايا المستخدمين المفقودة دون البحث الكامل في التسجيلات لكل مستخدم. ولا تُتبع الارتباطات الرمزية. وهذه مرشحات تكوين: فقد تؤثر البنية المعمارية، ورفع الامتيازات، وUAC، والنهج، وسياق التنشيط في ما إذا كان التسجيل يُستخدم فعلًا. أكّد التنفيذ بأدلة من العمليات، أو تحميل الوحدات، أو أدلة مستقلة أخرى.

التصنيف والملفات الشخصية

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

juntei persistence-hunter -d evidence/ --min-severity info -o all-persistence.csv

استخدم جميع مستويات الخطورة عند مراجعة المجموعات غير المكتملة

يمكن لقاعدة سماح واسعة أن تطابق جزئيًا أمرًا للمهاجم حتى عندما يكون موقِّعه مفقودًا أو مختلفًا. ويصنّف المشروع الأصلي التطابقات الجزئية على أنها LOW، وهو ما يخفيه الحد الافتراضي medium للأمر اليدوي. وقد يؤثر ذلك في المهام المجدولة الضارة الموجودة تحت مجلدات Windows. استخدم --min-severity info لتحقيق كامل وراجع PolicyReason وSignerStatus والأمر وأدلة المصدر معًا. ويحتفظ auto-parse بهذه الإدخالات أصلًا.

التصنيف المعنى
HIGH تطابقت قاعدة حظر مكوَّنة تطابقًا كاملًا
MEDIUM لم تتطابق أي قاعدة سماح أو حظر
LOW تطابقت الشروط الصارمة لقاعدة سماح، لكن البيانات الوصفية للموقِّع لم تتطابق أو لم تكن متاحة
INFO تطابقت قاعدة سماح تطابقًا كاملًا

هذه تصنيفات قائمة على النهج، وليست احتمالات مُقاسة للاختراق. والإدخال MEDIUM الافتراضي ليس دليلًا على وجود برمجيات خبيثة. ولا يثبت INFO أن الملف يحمل توقيعًا صالحًا أو أن المهاجم لم يُسئ استخدامه. والتطابق الجزئي مع قاعدة سماح يقع دون الحد الافتراضي، لذا أدرج --min-severity low أو info عند مراجعة المجموعات الشحيحة أو ضبط قائمة السماح.

مرّر ملفًا شخصيًا بصيغة YAML باستخدام --profile profile.yaml. وهو يحل محل الملف الشخصي المضمّن. وتُجمع القواعد العامة والقواعد الخاصة بكل فحص داخل الملف المختار؛ وتغلب أي قاعدة حظر تتطابق تطابقًا كاملًا. على سبيل المثال:

allow: []
block:
  - reason: Example known-bad command fragment
    value_matches: 'example-malicious-loader\.exe'
checks:
  windows_service_image_path:
    enabled: true
    allow:
      - reason: Organization's expected service path
        value_matches: '^C:\\Program Files\\ExampleCorp\\Agent\\agent\.exe$'
        signer: ExampleCorp

شروط القواعد المدعومة هي path_matches وvalue_matches وhash (‏64 رقمًا ست عشريًا لتجزئة SHA256) وnot_lolbin وsigner (سلسلة فرعية دون تمييز لحالة الأحرف). ويجب أن تتطابق جميع الشروط الصارمة المذكورة. والبيانات الوصفية للموقِّع هي الشرط المرن الموصوف أعلاه. وتستخدم التعبيرات النمطية صيغة التعبيرات النمطية في Rust: إذ لا تُدعم عمليات النظر حول النص (lookarounds) ولا المراجع الخلفية (backreferences). وتؤدي معرّفات الفحوص غير المعروفة، والتعبيرات غير الصالحة، وحقول الملف الشخصي غير المعروفة إلى خطأ بدلًا من إضعاف النهج بصمت.

حقول الإخراج

CSV هو تنسيق الملف الافتراضي. استخدم -t json للحصول على كائنات JSON مقروءة أو -t jsonl للحصول على إخراج مضغوط بكائن واحد في كل سطر. ودون -o، يكتب -t الصريح البيانات فقط إلى stdout؛ وتذهب تحذيرات التغطية إلى stderr. ودون أي من الخيارين، يطبع Juntei ملخصًا وما يصل إلى 30 مرشحًا.

الحقول كيفية تفسيرها
Comp، CheckID، Technique، MitreID الحاسوب وآلية الاستمرارية اللذان يصفهما الصف
Path، Value موقع سجل Windows، أو الملف، أو المهمة، أو السجل المسترد، ومحتواه المكوَّن
Description، References سبب أهمية الآلية وأين يمكن قراءة المزيد
AccessGained النطاق المعتاد للآلية (USER أو SYSTEM؛ ويمكن لـ BITS أيضًا تحديد LOCAL_SERVICE/NETWORK_SERVICE)؛ وليس دليلًا على أن أمرًا بعينه قد حقق ذلك الامتياز
Severity، PolicyReason تصنيف الملف الشخصي، وشرح النهج المطابق، وأي تقييد ناتج عن تطابق جزئي أو موقِّع لم يُتحقق منه
SourceFile، RecordStatus المصدر المجمّع بدقة، ومساره بدءًا من المُدخل كما مُرّر (./HOST/... من auto-parse)، وسياق التخصيص/إعادة التطبيق/الاسترداد؛ تتبّعه رجوعًا إلى الأدلة الأصلية
KeyLastWrite الطابع الزمني لـ مفتاح سجل Windows. ولا يؤرّخ قيمة بعينها
LastChange، ChangeSource، ChangeEvidence وقت التغيير المرتبط بشكل مستقل، ودليل المصدر، وما إذا كان الربط قد نجح
ResolvedPath، ResolutionStatus، Exists مسار الحمولة ونتيجة الحل دون اتصال؛ والأدلة غير المجمّعة تكون مجهولة، لا false
SHA256 تجزئة SHA256 لبايتات الحمولة المجمّعة، عندما تكون قابلة للقراءة
Signer، SignerStatus البيانات الوصفية الوصفية للشهادة/الكتالوج المضمّنة ومدى توفرها؛ ولا يُتحقق من الثقة في الشهادة ولا من صلاحية التوقيع
IsLolbin، Launcher ما إذا كان المشغّل أو الحمولة المكوَّنة ضمن قائمة LOLBAS المضمّنة، والمشغّل المستخدم لحمولة تُشغَّل عبر وسيط
IsBuiltin، IsInOS-Directory سياق لأوامر Windows الشائعة ومجلدات النظام؛ ولا يثبت أي من الحقلين المشروعية

يمكن لأمر rundll32.exe أن يسمّي حمولة DLL. ويحتفظ Juntei بالمشغّل أثناء حل الحمولة وحساب تجزئتها. ولا يُستبدل بملف من جهاز المحلل أيٌّ من المرجع الواقع خارج الحاسوب المجمّع، أو محرك الأقراص المفقود، أو التطابق الملتبس دون تمييز لحالة الأحرف، أو متغير البيئة الذي لم يُحل.

الطوابع الزمنية والقيود

لا تستخدم أداة البحث أوقات تعديل الملفات المنسوخة في الجهاز الافتراضي للمحلل بوصفها طوابع زمنية للهجوم. وحيثما أمكن، تربط عمليات الكتابة في سجل Windows بحدث Sysmon رقم 13، وتثبيت المهام بحدث Security 4698 أو Task Scheduler 106، وتثبيت الخدمات بحدث System 7045، والتكوين المعتمد على الملفات بالطوابع الزمنية الأصلية في $MFT. ويظهر المصدر في ChangeSource. يمكن للحدث أن يؤرّخ تغييرًا في التكوين دون أن يثبت أن الحمولة المكوَّنة قد شُغّلت. ويمكن لحدث System المحلي 6011 أن يثبت اسم حاسوب سابقًا. وتتبع أداة البحث سلاسل إعادة التسمية التي جرى التحقق منها والمرتكزة على الحاسوب المجمّع، فتحافظ على قيمة Comp الحالية مع تسجيل حاسوب الحدث الأصلي ودليل سجل إعادة التسمية في ChangeSource. ولا تُقبل عبر هذه القاعدة الأسماء الأجنبية غير المثبتة، ولا السجلات المؤرشفة، ولا السجلات المُعاد توجيهها، ولا تثبيت Windows آخر.

توفر قيم ComputerName/ActiveComputerName، وHostname/NV Hostname في TCP/IP، واسم المضيف/FQDN في معلومات العميل الملتقطة أسماءً بديلة للمضيف، تغطي اختلافات DNS/NetBIOS وعمليات إعادة التسمية المعلقة. وعند عدم وجود هوية ملتقطة، يمكن لاسم واحد في السجلات الأساسية أن يدعم التأريخ مع مصدر صريح يفيد بأن الهوية لم يُتحقق منها وتحذير في التغطية. ولا تُنسب الأسماء المتعددة التي لم يُتحقق منها إلى المضيف. ويُبلَغ عن أسماء Computer المرفوضة بوصفها قيدًا في تغطية الربط؛ وتظل قنواتها موسومة بأنها مجمّعة.

استخدم --mft <FILE> لاختيار MFT جُمع خارجيًا لحاسوب واحد. واستخدم --no-timeline لتخطي ربط الطوابع الزمنية. وتفسّر NOT_RUN وNOT_APPLICABLE وNO_ARTIFACT وNO_MATCH وREJECTED خلوّ LastChange؛ والحقل الفارغ ليس دليلًا على أن الإدخال غير ضار.

استرداد WMI وBITS هو اقتطاع (carving) محدود وليس محللًا كاملًا لمعاملات قاعدة البيانات. وقد تتضمن السلاسل النصية أو الروابط المستردة بيانات قديمة/محذوفة؛ ويجب تأكيد هذه السجلات. ولا تُحتسب مخططات فئات WMI وحدها بوصفها اشتراكات. وإدخال TaskCache الذي لا يقابله ملف XML مجمّع للمهمة تباينٌ يستدعي المراجعة؛ فقد تكون مجموعة الفرز قد أغفلت ذلك الملف ببساطة. والبيانات الوصفية للكتالوج وPE لم يُتحقق منها وقد تكون غائبة عن المجموعة. وتعتمد فحوص استبدال ملفات إمكانية الوصول (accessibility) على بيانات وصفية مرجعية مناسبة للتوقيعات؛ ويجب ألا يؤدي غياب أدلة الكتالوج إلى وسم كل ملف تنفيذي لإمكانية الوصول.

تُسجَّل التغطية لكل فحص، بما في ذلك الفحوص التي ليس لها أي نتائج. وتعني complete أن المصدر المجمّع المنطبق قد قُرئ؛ ولا تثبت أن المجموعة كاملة أو أن الحاسوب لا يحتوي على آليات استمرارية أخرى. وتفسّر partial وnot_collected وfailed وdisabled حدود ذلك. احتفظ بـ --coverage Coverage.csv وسجل المحلل مع نتائجك.

يستخدم هذا المنفَذ تنسيقات CSV/JSON/JSONL الخاصة بـ Juntei. ولا يستدعي برنامج Python الأصلي، ولا يستعلم خدمات الإثراء عبر الإنترنت، ولا يعيد إنتاج واجهة HTML/XLSX الخاصة بالمشروع الأصلي.

مزيد من التفاصيل