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
Перше сканування¶
Доказами може бути змонтований том Windows, збірка Velociraptor або каталог, що містить
кілька зібраних комп'ютерів. Під час аналізу комп'ютери розглядаються окремо, і кожен результат містить
Comp. Екранування імен файлів у збірці декодується під час розв'язання шляхів Windows.
Для одного куща:
Один кущ не може забезпечити перевірки, яким потрібен інший кущ або докази з файлової системи. Прочитайте звіт про охоплення, перш ніж вважати порожній результат значущим.
Перелічіть ідентифікатори перевірок та їх зіставлення з 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 для однопотокового сканування:
Виявлення доказів, незалежні перевірки, метадані корисного навантаження та джерела хронології 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. Щоб переглянути повну інвентаризацію, зокрема
записи, що відповідають вбудованому списку дозволу:
Використовуйте всі рівні серйозності під час перевірки неповних збірок
Широке правило дозволу може частково збігатися з командою зловмисника, навіть якщо її підписувач відсутній
або інший. Першоджерело класифікує часткові збіги як 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 першоджерела.