Перейти до змісту

Persistence Hunter

Закріплення дає змогу програмі знову запускатися після перезавантаження, входу користувача, запланованого тригера або іншої події. Зловмисник може використовувати для цього звичайну конфігурацію Windows. Багато легітимних програм використовують точно такі самі механізми, тому знайдений запис закріплення — це відправна точка для аналізу.

juntei persistence-hunter — це нативний порт на 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 обробляються паралельно. Завантажені кущі реєстру хоста спільно використовуються в режимі лише для читання, а кешовані метадані того самого корисного навантаження ініціалізуються один раз. Хости завантажуються по одному, щоб не множити обсяг пам'яті для кущів у всій збірці. Результати, охоплення, вибір часових позначок і порядок попереджень залишаються однаковими за різної кількості потоків.

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, зіставлені з відповідними реєстраціями класів користувача/машини
Папки автозавантаження, профілі PowerShell, шаблони Office, параметри Terminal Файли та команди, що запускаються тригерами користувача або системи
WMI OBJECTS.DATA Екземпляри споживачів подій і прив'язки фільтрів до споживачів
BITS qmgr.db або qmgr*.dat Відновлені команди сповіщень і SID власників
$MFT і відповідні файли EVTX Незалежне зіставлення часових позначок
Виконувані файли, DLL і файли каталогів, на які є посилання Хеші SHA256 та описові метадані PE/сертифікатів

Журнали транзакцій реєстру відтворюються, якщо вони доступні. --no-logs зчитує кущі в зібраному вигляді; невідтворений «брудний» кущ може не містити нещодавніх змін, і про це повідомляється у звіті про охоплення. Для перевірок активної системи використовується поточний набір керування. Перевірка бекдору DSRM додатково досліджує ControlSet001, ControlSet002 і CurrentControlSet, якщо вони є; перш ніж описувати цей параметр як активний, звірте наведений нею шлях із SYSTEM\\Select. Інші історичні набори керування можна дослідити за допомогою окремих команд парсерів реєстру.

Зчитування кущів мають спільний бюджет вхідних даних 1 ГіБ на комп'ютер. Машинні кущі обробляються раніше за кущі користувачів; вхідні дані або журнали транзакцій, що не вміщуються в бюджет, називаються у звіті про часткове охоплення. Інші читабельні кущі та перевірки на основі файлів продовжують виконуватися. Ідентичність куща встановлюють лише канонічні розташування кущів або явно передані експорти; копія в тимчасовому каталозі користувача не може замінити справжній кущ цього користувача. Вихідний системний диск, записаний у SOFTWARE, зіставляється із зібраним системним томом, тож монтування вихідного тому C: під іншою літерою диска з доказами не призводить до втрати метаданих корисного навантаження.

auto-parse також запускає пошук і зберігає persistence/PersistenceHunter.csv (або .json/.jsonl) у каталозі кожного комп'ютера, поруч із PersistenceHunter-logs.txt. Його результати також потрапляють до необов'язкової хронології SIEM -j <FILE>. Автоматичний аналіз використовує --min-severity info, щоб зберегти повну інвентаризацію конфігурації, зокрема записи, що відповідають правилам дозволу.

Реєстрації COM і тригери активації

Перевірка scheduled_task_files вибирає суб'єкта кожної дії за допомогою 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, який зазвичай існує лише в пам'яті й не зберігається разом із кущами реєстру. Дубльований CLSID користувача приховує дочірні елементи машинного CLSID. Групові суб'єкти використовують машинних кандидатів COM і зберігають це обмеження в описі результату; звичайний груповий суб'єкт сам по собі не робить охоплення частковим і не займає записів у зведенні помилок.

Механізм розв'язання переходить за InprocServer32 і LocalServer32, використовує керовані шляхи CodeBase (зокрема підключі версій) і зіставляє LocalService з AppID із ImagePath зібраної служби SYSTEM. Асоціації AppID з іменами виконуваних файлів зберігаються, але базове ім'я не встановлює повного шляху до виконуваного файлу. Локальні URL-адреси CodeBase file: декодуються; віддалені URL-адреси записуються без звернення до них. Для відсутніх реєстрацій CLSID зберігається з ResolutionStatus: unresolved_com_class, порожніми полями шляху/хешу та невідомим значенням Exists.

Перевірка start_menu_com зчитує URL-адреси з XML файлів .library-ms у меню «Пуск» кожного користувача та збирає папки з іменами CLSID, зокрема порожні каталоги. Вона повідомляє шлях тригера, CLSID, сервер-кандидат і походження з реєстру. Збирання лише файлів не може зберегти порожній каталог, а відсутність кущів користувачів унеможливлює повний пошук реєстрацій для кожного користувача. Символьні посилання не відстежуються. Це кандидати конфігурації: архітектура, підвищення привілеїв, 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: перевірки на кшталт lookaround і зворотні посилання не підтримуються. Невідомі ідентифікатори перевірок, неприпустимі вирази та невідомі поля профілю спричиняють помилку, а не непомітне послаблення політики.

Поля виводу

CSV — формат файлу за замовчуванням. Використовуйте -t json для зручних для читання об'єктів JSON або -t jsonl для компактного виводу з одним об'єктом на рядок. Без -o явно вказаний -t записує в stdout лише дані; попередження про охоплення виводяться в stderr. Без жодного з цих параметрів Juntei виводить підсумок і до 30 кандидатів.

Поля Як їх інтерпретувати
Comp, CheckID, Technique, MitreID Який комп'ютер і механізм закріплення описує рядок
Path, Value Розташування в реєстрі, файл, завдання або відновлений запис та його налаштований вміст
Description, References Чому механізм важливий і де прочитати більше
AccessGained Звичайна сфера дії механізму (USER або SYSTEM; BITS також може вказувати LOCAL_SERVICE/NETWORK_SERVICE); не доказ того, що конкретна команда отримала ці привілеї
Severity, PolicyReason Класифікація за профілем, пояснення відповідної політики та будь-які застереження щодо часткового збігу або неперевіреного підписувача
SourceFile, RecordStatus Точне зібране джерело, його шлях, що починається з вхідних даних у переданому вигляді (./HOST/... з auto-parse), і контекст розподілу/відтворення/відновлення; простежуйте за ним до вихідних доказів
KeyLastWrite Часова позначка ключа реєстру. Вона не датує окреме значення
LastChange, ChangeSource, ChangeEvidence Незалежно зіставлений час зміни, підтвердження з джерела і чи вдалося зіставлення
ResolvedPath, ResolutionStatus, Exists Шлях до корисного навантаження та результат офлайн-розв'язання; незібрані докази мають невідомий стан, а не false
SHA256 SHA256 зібраних байтів корисного навантаження, якщо їх можна прочитати
Signer, SignerStatus Описові метадані вбудованого сертифіката/каталогу та їхня доступність; довіра до сертифіката й дійсність підпису не перевіряються
IsLolbin, Launcher Чи є налаштований засіб запуску або корисне навантаження у вбудованому списку LOLBAS, а також засіб запуску, використаний для опосередкованого корисного навантаження
IsBuiltin, IsInOS-Directory Контекст для поширених команд Windows і системних каталогів; жодне з цих полів не встановлює легітимності

Команда rundll32.exe може називати корисне навантаження у вигляді DLL. Juntei зберігає засіб запуску, розв'язуючи шлях до корисного навантаження та обчислюючи його хеш. Посилання за межі зібраного комп'ютера, відсутній диск, неоднозначний збіг без урахування регістру або нерозгорнута змінна середовища не замінюються файлом із комп'ютера аналітика.

Часові позначки та обмеження

Засіб пошуку не використовує час зміни скопійованих файлів у віртуальній машині аналітика як часові позначки атаки. Якщо доступно, він зіставляє записи в реєстр із подією Sysmon 13, встановлення завдань — із Security 4698 або Task Scheduler 106, встановлення служб — із System 7045, а конфігурацію на основі файлів — з вихідними часовими позначками $MFT. Походження відображається в ChangeSource. Подія може датувати зміну конфігурації, не доводячи, що налаштоване корисне навантаження виконувалося. Локальна подія System 6011 може підтвердити попереднє ім'я комп'ютера. Засіб пошуку відстежує перевірені ланцюжки перейменувань, прив'язані до зібраного комп'ютера, зберігаючи його поточне значення Comp і записуючи ім'я комп'ютера з вихідної події та підтвердження із запису про перейменування в ChangeSource. Непідтверджені сторонні імена, архівовані журнали, переслані журнали та інша інсталяція Windows за цим правилом не приймаються.

Зібрані ComputerName/ActiveComputerName, Hostname/NV Hostname з TCP/IP і hostname/FQDN з client-info дають псевдоніми хоста, охоплюючи відмінності DNS/NetBIOS і відкладені перейменування. Якщо зібраної ідентичності немає, єдине ім'я в основних журналах може використовуватися для датування з явним зазначенням неперевіреної ідентичності як походження і попередженням про охоплення. Кілька неперевірених імен хосту не приписуються. Відхилені імена комп'ютерів наводяться як обмеження охоплення зіставлення; їхні канали однаково позначаються як зібрані.

Використовуйте --mft <FILE>, щоб вибрати окремо зібрану MFT для одного комп'ютера. Використовуйте --no-timeline, щоб пропустити зіставлення часових позначок. NOT_RUN, NOT_APPLICABLE, NO_ARTIFACT, NO_MATCH і REJECTED пояснюють порожнє LastChange; порожнє поле не є доказом того, що запис нешкідливий.

Відновлення WMI і BITS — це обмежене вирізання (carving), а не повноцінний парсер транзакцій бази даних. Відновлені рядки або прив'язки можуть містити старі/видалені дані; ці записи потрібно підтверджувати. Самі лише схеми класів WMI не вважаються підписками. Запис TaskCache без зібраного файлу XML завдання — це розбіжність, яку слід перевірити; збірка для тріажу могла просто не включити цей файл. Метадані каталогів і PE не перевіряються і можуть бути відсутні у збірці. Перевірки заміни файлів спеціальних можливостей залежать від придатних еталонних метаданих підпису; відсутність доказів із каталогів не повинна призводити до позначення кожного виконуваного файлу спеціальних можливостей.

Охоплення записується для кожної перевірки, зокрема для перевірок без результатів. complete означає, що відповідне зібране джерело було прочитано; це не доводить, що збірка повна або що комп'ютер не має іншого закріплення. partial, not_collected, failed і disabled пояснюють обмеження. Зберігайте --coverage Coverage.csv і журнал парсера разом зі своїми результатами.

Порт використовує формати CSV/JSON/JSONL Juntei. Він не викликає програму на Python з першоджерела, не звертається до онлайн-служб збагачення даних і не відтворює інтерфейс HTML/XLSX першоджерела.

Додаткові відомості