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

Аналіз результатів Hayabusa за допомогою jq

Автор

Zach Mathis (@yamatosecurity) - 2023/03/22

Про документ

Уміння виявляти, видобувати та створювати метрики на основі важливих полів у журналах є невід'ємною навичкою для аналітиків DFIR та полювання на загрози. Результати Hayabusa зазвичай зберігаються у файли .csv, щоб імпортувати їх у програми на кшталт Excel або Timeline Explorer для аналізу часової шкали. Однак, коли існують сотні або більше однакових подій, перевіряти їх вручну стає непрактично або неможливо. У таких ситуаціях аналітики зазвичай сортують і підраховують подібні типи даних, шукаючи аномалії. Це також відоме як аналіз довгого хвоста, ранжування за стеком, частотний аналіз тощо... Цього можна досягти за допомогою Hayabusa, виводячи результати у файли .json або .jsonl, а потім аналізуючи їх за допомогою jq.

Наприклад, аналітик міг би порівняти встановлені служби на всіх робочих станціях в організації. Хоча можливо, що певна частина шкідливого програмного забезпечення могла б встановитися на кожну робочу станцію, набагато ймовірніше, що воно існуватиме лише на кількох системах. У цьому випадку служби, встановлені на всіх системах, з більшою ймовірністю є безпечними, тоді як рідкісні служби зазвичай є більш підозрілими, і їх слід періодично перевіряти.

Інший варіант використання — допомогти визначити, наскільки щось підозріле. Наприклад, аналітик міг би проаналізувати журнали невдалих входів 4625, щоб визначити, скільки разів певна IP-адреса не змогла увійти. Якщо було лише кілька невдалих входів, то ймовірно, що адміністратор просто неправильно набрав свій пароль. Однак, якщо була сотня або більше невдалих входів за короткий період часу з певної IP-адреси, то ймовірно, що ця IP-адреса є шкідливою.

Вивчення того, як користуватися jq, допоможе вам опанувати не лише аналіз журналів подій Windows, але й усіх журналів у форматі JSON. Тепер, коли JSON став дуже популярним форматом журналів і більшість хмарних провайдерів використовують його для своїх журналів, уміння розбирати їх за допомогою jq стало невід'ємною навичкою сучасного аналітика безпеки.

У цьому посібнику я спочатку поясню, як використовувати jq для тих, хто ніколи раніше ним не користувався, а потім поясню складніші способи використання разом із реальними прикладами. Я рекомендую використовувати linux, macOS або linux на Windows, щоб мати змогу поєднувати jq з іншими корисними командами, такими як sort, uniq, grep, sed тощо...

Встановлення jq

Будь ласка, зверніться до https://stedolan.github.io/jq/ та встановіть команду jq.

Про формат JSON

Журнали JSON — це список об'єктів, що містяться у фігурних дужках { }. Усередині цих об'єктів містяться пари ключ-значення, розділені двокрапками. Ключі мають бути рядками, але значення можуть бути одним із наступних: * рядок (Напр.: "string") * число (Напр.: 10) * інший об'єкт (Напр.: { xxxx }) * масив (Напр.: ["string", 10]) * булеве значення (Напр.: true, false) * null

Ви можете вкладати скільки завгодно об'єктів усередину об'єктів.

У цьому прикладі Details є вкладеним об'єктом усередині кореневого об'єкта:

{
    "Timestamp": "2016-08-19 08:06:57.658 +09:00",
    "Computer": "IE10Win7",
    "Channel": "Sec",
    "EventID": 4688,
    "Level": "info",
    "RecordID": 6845,
    "RuleTitle": "Proc Exec",
    "Details": {
        "CmdLine": "C:\\Windows\\system32\\ipconfig /release",
        "Path": "C:\\Windows\\System32\\ipconfig.exe",
        "PID": "0xcf4",
        "User": "IE10WIN7$",
        "LID": "0x3e7"
    }
}

Про формати JSON та JSONL у Hayabusa

У ранніх версіях Hayabusa використовувала традиційний формат JSON, поміщаючи всі об'єкти журналу { xxx } в один гігантський масив.

Приклад:

[
    {
        "Timestamp": "2016-08-19 08:06:57.658 +09:00",
        "Computer": "IE10Win7",
        "Channel": "Sec",
        "EventID": 4688,
        "Level": "info",
        "RecordID": 6845,
        "RuleTitle": "Proc Exec",
        "Details": {
            "CmdLine": "C:\\Windows\\system32\\ipconfig /release",
            "Path": "C:\\Windows\\System32\\ipconfig.exe",
            "PID": "0xcf4",
            "User": "IE10WIN7$",
            "LID": "0x3e7"
        }
    },
    {
        "Timestamp": "2016-08-19 11:07:47.489 +09:00",
        "Computer": "IE10Win7",
        "Channel": "Sec",
        "EventID": 4688,
        "Level": "info",
        "RecordID": 6847,
        "RuleTitle": "Proc Exec",
        "Details": {
            "CmdLine": "taskhost.exe $(Arg0)",
            "Path": "C:\\Windows\\System32\\taskhost.exe",
            "PID": "0x228",
            "User": "IE10WIN7$",
            "LID": "0x3e7"
        }
    }
]

Із цим є дві проблеми. Перша проблема полягає в тому, що запити jq стають більш громіздкими, оскільки все має починатися з додаткового .[], щоб вказати йому заглянути в цей масив. Набагато більша проблема полягає в тому, що для розбору таких журналів необхідно спочатку завантажити всі дані в масив. Це стає проблемою, якщо у вас дуже великі файли JSON і недостатньо пам'яті. Щоб зменшити необхідне використання CPU та пам'яті, формат JSONL (JSON Lines), який не поміщає все в гігантський масив, став більш популярним. Hayabusa виводить у форматах JSON та JSONL, однак формат JSON більше не зберігається всередині масиву. Єдина різниця полягає в тому, що формат JSON легше читати в текстовому редакторі або на консолі, тоді як формат JSONL зберігає кожен об'єкт JSON в одному окремому рядку. Формат JSONL буде трохи швидшим і меншим за розміром, тому є ідеальним, якщо ви збираєтеся лише імпортувати журнали в SIEM тощо, але не переглядати їх. Формат JSON є ідеальним, якщо ви також збираєтеся виконувати певну ручну перевірку.

Створення файлів результатів JSON

У поточній версії 2.x Hayabusa ви можете зберегти результати у форматі JSON за допомогою hayabusa json-timeline -d <directory> -o results.json або hayabusa json-timeline -d <directory> -J -o results.jsonl для формату JSONL.

Hayabusa використовуватиме типовий профіль standard і збереже лише мінімальну кількість даних для аналізу в об'єкті Details. Якщо ви хочете зберегти всю інформацію оригінальних полів у журналах .evtx, ви можете використати профіль all-field-info з опцією --profile all-field-info. Це збереже всю інформацію полів в об'єкт AllFieldInfo. Якщо ви хочете зберегти обидва об'єкти Details та AllFieldInfo про всяк випадок, ви можете використати профіль super-verbose.

Переваги використання Details замість AllFieldInfo

Перша перевага використання Details замість AllFieldInfo полягає в тому, що зберігаються лише важливі поля, а імена полів були скорочені, щоб заощадити місце у файлі. Недоліком є те, що існує можливість пропустити дані, які насправді були вам важливі, але були пропущені. Друга перевага полягає в тому, що Hayabusa зберігатиме поля більш однорідно, нормалізуючи імена полів. Наприклад, в оригінальних журналах Windows ім'я користувача зазвичай знаходиться в полі SubjectUserName або TargetUserName. Однак іноді ім'я користувача буде в полі AccountName, іноді цільовий користувач насправді буде в полі SubjectUserName тощо... На жаль, у журналах подій Windows є багато непослідовних імен полів. Hayabusa намагається нормалізувати ці поля, тому аналітику потрібно лише розібрати спільне ім'я замість того, щоб розуміти нескінченну кількість особливостей і розбіжностей між ідентифікаторами подій у Windows.

Ось приклад поля користувача. Hayabusa нормалізує SubjectUserName, TargetUserName, AccountName тощо... таким чином: * SrcUser (Source User): коли дія відбувається від користувача. (Зазвичай віддаленого користувача.) * TgtUser (Target User): коли дія відбувається до користувача. (Наприклад, вхід до користувача.) * User: коли дія відбувається користувачем, який наразі увійшов у систему. (Немає певного напрямку дії.)

Інший приклад — процеси. В оригінальних журналах подій Windows поле процесу позначається кількома угодами щодо найменування: ProcessName, Image, processPath, Application, WindowsDefenderProcessName тощо... Без нормалізації полів аналітику довелося б спочатку добре знати всі різні імена полів, потім видобути всі журнали з цими іменами полів, а потім об'єднати їх разом.

Аналітик може заощадити багато часу та зусиль, просто використовуючи нормалізоване єдине поле Proc, яке Hayabusa надає в об'єкті Details.

Уроки/рецепти jq

Тепер я перелічу кілька уроків/рецептів практичних прикладів, які можуть допомогти вам у вашій роботі.

1. Ручна перевірка за допомогою jq та Less у кольорі

Це одна з перших речей, яку слід зробити, щоб зрозуміти, які поля є в журналах. Ви могли б просто виконати less results.json, але кращий спосіб такий: cat results.json | jq -C | less -R

Передаючи дані до jq, він акуратно відформатує всі поля для вас, якщо вони не були акуратно відформатовані спочатку. Використовуючи опцію -C (color) з jq та опцію -R (raw output) з less, ви можете прокручувати вгору і вниз у кольорі.

2. Метрики

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

Спочатку видобуємо список ідентифікаторів подій за допомогою наступної команди:

cat results.json | jq '.EventID'

Це видобуде лише номер Event ID з кожного журналу. Після jq, в одинарних лапках, просто введіть . та ім'я поля, яке ви хочете видобути. Ви маєте побачити довгий список на кшталт цього:

4624
4688
4688
4634
1337
1
1
1
1
10
27
11
11

Тепер передайте результати командам sort та uniq -c, щоб підрахувати, скільки разів зустрічалися ідентифікатори подій:

cat results.json | jq '.EventID' | sort | uniq -c

Опція -c для uniq підрахує, скільки разів зустрічався унікальний ідентифікатор події.

Ви маєте побачити щось на кшталт цього:

 168 59
  23 6
  38 6005
  37 6006
   3 6416
 129 7
   1 7040
1382 7045
   2 770
 391 8

Ліворуч — кількість, а праворуч — Event ID. Як ви можете бачити, це не відсортовано, тому важко сказати, які ідентифікатори подій зустрічалися найчастіше.

Ви можете додати sort -n у кінці, щоб виправити це:

cat results.json | jq '.EventID' | sort | uniq -c | sort -n

Опція -n вказує sort сортувати за числом.

Ви маєте побачити щось на кшталт цього:

 400 4624
 433 5140
 682 4103
1131 4104
1382 7045
2322 1
2584 5145
7135 4625
12277 4688

Ми бачимо, що події 4688 (Створення процесу) були записані найчастіше. Другою найбільш записаною подією була 4625 (Невдалий вхід).

Якщо ви хочете надрукувати найбільш записані події вгорі, то ви можете обернути сортування за допомогою sort -n -r або sort -nr. Ви також можете просто надрукувати топ-10 найбільш записаних подій, передавши результати до head -n 10.

cat results.json | jq '.EventID' | sort | uniq -c | sort -nr | head -n 10

Це дасть вам:

12277 4688
7135 4625
2584 5145
2322 1
1382 7045
1131 4104
 682 4103
 433 5140
 400 4624
 391 8

Важливо враховувати, що EID (Event IDs) не є унікальними, тому ви можете мати абсолютно різні події з однаковим Event ID. Тому важливо також перевіряти Channel.

Ми можемо додати цю інформацію поля так:

cat results.json | jq -j ' .Channel , " " , .EventID , "\n" ' | sort | uniq -c | sort -nr | head -n 10

Ми додаємо опцію -j (join) до jq, щоб об'єднати всі поля разом, розділені комами та закінчуючи символом нового рядка \n.

Це дасть нам:

12277 Sec 4688
7135 Sec 4625
2584 Sec 5145
2321 Sysmon 1
1382 Sys 7045
1131 PwSh 4104
 682 PwSh 4103
 433 Sec 5140
 400 Sec 4624
 391 Sysmon 8

Примітка: Security скорочується до Sec, System до Sys, а PowerShell до PwSh.

Ми можемо додати назву правила так:

cat results.json | jq -j ' .Channel , " " , .EventID , " " , .RuleTitle , "\n" ' | sort | uniq -c | sort -nr | head -n 10

Це дасть нам:

9714 Sec 4688 Proc Exec
3564 Sec 4625 Logon Failure (Wrong Password)
3561 Sec 4625 Metasploit SMB Authentication
2564 Sec 5145 NetShare File Access
1459 Sysmon 1 Proc Exec
1418 Sec 4688 Susp CmdLine (Possible LOLBIN)
 789 PwSh 4104 PwSh Scriptblock
 680 PwSh 4103 PwSh Pipeline Exec
 433 Sec 5140 NetShare Access
 342 Sec 4648 Explicit Logon

Тепер ви можете вільно видобувати будь-які дані з журналів і підраховувати кількість випадків.

3. Фільтрація за певними даними

Часто вам захочеться фільтрувати за певними Event IDs, користувачами, процесами, LIDs (Logon IDs) тощо... Ви можете зробити це за допомогою select усередині запиту jq.

Наприклад, видобудемо всі події успішного входу 4624:

cat results.json | jq 'select ( .EventID == 4624 ) '

Це поверне всі об'єкти JSON для EID 4624:

{
  "Timestamp": "2021-12-12 16:16:04.237 +09:00",
  "Computer": "fs03vuln.offsec.lan",
  "Channel": "Sec",
  "Provider": "Microsoft-Windows-Security-Auditing",
  "EventID": 4624,
  "Level": "info",
  "RecordID": 1160369,
  "RuleTitle": "Logon (Network)",
  "RuleAuthor": "Zach Mathis",
  "RuleCreationDate": "2020/11/08",
  "RuleModifiedDate": "2022/12/16",
  "Status": "stable",
  "Details": {
    "Type": 3,
    "TgtUser": "admmig",
    "SrcComp": "",
    "SrcIP": "10.23.123.11",
    "LID": "0x87249a8"
  },
  "RuleFile": "Sec_4624_Info_Logon-Type-3-Network.yml",
  "EvtxFile": "../hayabusa-sample-evtx/EVTX-to-MITRE-Attack/TA0007-Discovery/T1046-Network Service Scanning/ID4624-Anonymous login with domain specified (DonPapi).evtx",
  "AllFieldInfo": {
    "AuthenticationPackageName": "NTLM",
    "ImpersonationLevel": "%%1833",
    "IpAddress": "10.23.123.11",
    "IpPort": 60174,
    "KeyLength": 0,
    "LmPackageName": "NTLM V2",
    "LogonGuid": "00000000-0000-0000-0000-000000000000",
    "LogonProcessName": "NtLmSsp",
    "LogonType": 3,
    "ProcessId": "0x0",
    "ProcessName": "-",
    "SubjectDomainName": "-",
    "SubjectLogonId": "0x0",
    "SubjectUserName": "-",
    "SubjectUserSid": "S-1-0-0",
    "TargetDomainName": "OFFSEC",
    "TargetLogonId": "0x87249a8",
    "TargetUserName": "admmig",
    "TargetUserSid": "S-1-5-21-4230534742-2542757381-3142984815-1111",
    "TransmittedServices": "-",
    "WorkstationName": ""
  }

Якщо ви хочете фільтрувати за кількома умовами, ви можете використовувати ключові слова на кшталт and, or та not.

Наприклад, пошукаймо події 4624, де тип 3 (Мережевий вхід).

cat results.json | jq 'select ( ( .EventID == 4624 ) and ( .Details.Type == 3 ) ) '

Це поверне всі об'єкти, де EventID дорівнює 4624, а вкладене поле "Details": { "Type" } дорівнює 3.

Однак є проблема. Ви можете помітити помилки, що кажуть jq: error (at <stdin>:10636): Cannot index string with string "Type". Щоразу, коли ви бачите помилку Cannot index string with string, це означає, що ви вказуєте jq вивести поле, яке не існує або має неправильний тип. Ви можете позбутися цих помилок, додавши ? у кінці поля. Це вказує jq ігнорувати помилки.

Приклад: cat results.json | jq 'select ( ( .EventID == 4624 ) and ( .Details.Type? == 3 ) ) '

Тепер, після фільтрації за певними критеріями, ми можемо використати | усередині запиту jq, щоб тепер вибрати певні поля, що цікавлять.

Наприклад, видобудемо цільове ім'я користувача TgtUser та вихідну IP-адресу SrcIP:

cat results.json | jq -j 'select ( ( .EventID == 4624 ) and ( .Details.Type? == 3 ) ) | .Details.TgtUser , " " , .Details.SrcIP , "\n" '

Знову ж таки, ми додаємо опцію -j (join) до jq, щоб вибрати кілька полів для виведення. Потім ви можете виконати sort, uniq -c тощо, як у попередніх прикладах, щоб дізнатися, скільки разів певна IP-адреса входила до користувача через мережевий вхід типу 3.

4. Збереження виводу у формат CSV

На жаль, поля в журналах подій Windows будуть повністю відрізнятися залежно від типу події, тому неможливо легко створювати розділені комами часові шкали за полями, не маючи сотень стовпців. Однак можливо створювати розділені за полями часові шкали для окремих типів подій. Двома поширеними прикладами є Security 4624 (Успішні входи) та 4625 (Невдалі входи) для перевірки на бічне переміщення та вгадування/розпилення паролів.

У цьому прикладі ми видобуваємо лише журнали Security 4624 і виводимо мітку часу, ім'я комп'ютера та всю інформацію Details. Ми зберігаємо це у файл CSV за допомогою | @csv, однак нам потрібно передати дані як масив. Ми можемо зробити це, вибравши поля, які ми хочемо вивести, як ми робили раніше, та уклавши їх у квадратні дужки [ ], щоб перетворити їх на масив.

Приклад: cat results.json | jq 'select ( (.Channel == "Sec" ) and ( .EventID == 4624 ) ) | [ .Timestamp , .Computer , .Details[]? ] | @csv ' -r

Примітки: * Щоб вибрати всі поля в об'єкті Details, ми додаємо []. * Бувають випадки, коли Details є рядком, а не масивом, і видаватиме помилки Cannot iterate over string, тому вам потрібно додати ?. * Ми додаємо опцію -r (Raw output) до jq, щоб не екранувати подвійні лапки зворотним слешем.

Результати:

"2019-03-19 08:23:52.491 +09:00","WIN-77LTAPHIQ1R.example.corp",3,"user01","","10.0.2.17","0x15e1a7"
"2019-03-19 08:23:57.397 +09:00","WIN-77LTAPHIQ1R.example.corp",3,"WIN-77LTAPHIQ1R$","","fe80::79bf:8ee2:433c:2567","0x15e25f"
"2019-03-19 09:02:04.179 +09:00","WIN-77LTAPHIQ1R.example.corp",3,"ANONYMOUS LOGON","NULL","10.0.2.17","0x17e29a"
"2019-03-19 09:02:04.210 +09:00","WIN-77LTAPHIQ1R.example.corp",3,"Administrator","","10.0.2.17","0x17e2aa"
"2019-03-19 09:02:04.226 +09:00","WIN-77LTAPHIQ1R.example.corp",3,"Administrator","","10.0.2.17","0x17e2c0"
"2019-03-19 09:02:21.929 +09:00","WIN-77LTAPHIQ1R.example.corp",3,"WIN-77LTAPHIQ1R$","","fe80::79bf:8ee2:433c:2567","0x18423d"
"2019-05-12 02:10:10.889 +09:00","IEWIN7",9,"IEUser","","::1","0x1bbdce"

Якщо ми просто перевіряємо, хто мав успішні входи, нам може не знадобитися останнє поле LID (Logon ID). Ви можете видалити будь-який непотрібний стовпець за допомогою функції del.

Приклад: cat results.json | jq 'select ( ( .Channel == "Sec" ) and ( .EventID == 4624 ) ) | [ .Timestamp , .Computer , .Details[]? ] | del( .[6] ) | @csv ' -r

Масив рахується від 0, тому щоб видалити 7-е поле, ми використовуємо 6.

Тепер ви можете зберегти файл CSV, додавши > 4624-logs.csv, а потім імпортувати його в Excel або Timeline Explorer для подальшого аналізу.

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

5. Пошук дат із найбільшою кількістю сповіщень

Hayabusa за замовчуванням повідомить вам дати, які мали найбільшу кількість сповіщень відповідно до рівнів серйозності. Однак ви можете захотіти знайти також другу, третю тощо найбільшу кількість дат зі сповіщеннями. Ми можемо зробити це за допомогою нарізання рядка мітки часу, щоб групувати за роком, місяцем або датою залежно від ваших потреб.

Приклад: cat results.json | jq ' .Timestamp | .[:10] ' -r | sort | uniq -c | sort

.[:10] вказує jq видобути лише перші 10 байтів із Timestamp.

Це дасть нам дати з найбільшою кількістю подій:

1066 2021-12-12
1093 2016-09-02
1571 2021-04-22
1750 2016-09-03
2271 2016-08-19
2932 2021-11-03
8095 2016-09-20

Якщо ви хочете дізнатися місяць із найбільшою кількістю подій, ви можете просто змінити .[:10] на .[:7], щоб видобути перші 7 байтів.

Якщо ви хочете перелічити дати з найбільшою кількістю сповіщень high, ви можете зробити це:

cat results.json | jq 'select ( .Level == "high" ) | .Timestamp | .[:10] ' -r | sort | uniq -c | sort

Ви можете продовжувати додавати умови фільтрації до функції select відповідно до імені комп'ютера, ідентифікатора події тощо залежно від ваших потреб.

6. Реконструкція журналів PowerShell

Прикрою річчю щодо журналів PowerShell є те, що журнали часто розбиваються на кілька журналів, що ускладнює їх читання. Ми можемо зробити журнали набагато легшими для читання, видобувши лише команди, які запустив зловмисник.

Наприклад, якщо у вас є журнали ScriptBlock EID 4104, ви можете видобути лише це поле, щоб створити легку для читання часову шкалу.

cat results.json | jq 'select ( .EventID == 4104) | .Timestamp[:16] , " " , .Details.ScriptBlock , "\n" ' -jr

Це призведе до часової шкали такого вигляду:

2022-12-24 10:56 ipconfig
2022-12-24 10:56 prompt
2022-12-24 10:56 pwd
2022-12-24 10:56 prompt
2022-12-24 10:56 whoami
2022-12-24 10:56 prompt
2022-12-24 10:57 cd..
2022-12-24 10:57 prompt
2022-12-24 10:57 ls

7. Пошук підозрілих мережевих з'єднань

Спочатку ви можете отримати список усіх цільових IP-адрес за допомогою наступної команди:

cat results.json | jq 'select ( .Details.TgtIP? ) | .Details.TgtIP ' -r | sort | uniq

Якщо у вас є дані аналітики загроз, ви можете перевірити, чи відомо, що будь-які з IP-адрес є шкідливими.

Ви можете підрахувати, скільки разів встановлювалося з'єднання з певною цільовою IP-адресою, за допомогою наступного:

cat results.json | jq 'select ( .Details.TgtIP? ) | .Details.TgtIP ' -r | sort | uniq -c | sort -n

Змінивши TgtIP на SrcIP, ви можете виконати таку саму перевірку аналітики загроз на шкідливі IP-адреси на основі вихідних IP-адрес.

Припустимо, що ви виявили, що зі шкідливою IP-адресою 93.184.220.29 встановлювалося з'єднання з вашого середовища. Ви можете отримати деталі про ці події за допомогою наступного запиту:

cat results.json | jq 'select ( .Details.TgtIP? == "93.184.220.29" ) '

Це дасть вам результати JSON, такі як цей:

{
  "Timestamp": "2019-07-30 06:33:20.711 +09:00",
  "Computer": "MSEDGEWIN10",
  "Channel": "Sysmon",
  "EventID": 3,
  "Level": "med",
  "RecordID": 4908,
  "RuleTitle": "Net Conn (Sysmon Alert)",
  "Details": {
    "Proto": "tcp",
    "SrcIP": "10.0.2.15",
    "SrcPort": 49827,
    "SrcHost": "MSEDGEWIN10.home",
    "TgtIP": "93.184.220.29",
    "TgtPort": 80,
    "TgtHost": "",
    "User": "MSEDGEWIN10\\IEUser",
    "Proc": "C:\\Windows\\System32\\mshta.exe",
    "PID": 3164,
    "PGUID": "747F3D96-661E-5D3F-0000-00107F248700"
  }
}

Якщо ви хочете перелічити домени, з якими було встановлено зв'язок, ви можете використати наступну команду:

cat results.json | jq 'select ( .Details.TgtHost ) ? | .Details.TgtHost ' -r | sort | uniq | grep "\."

Примітка: Я додав фільтр grep для ., щоб видалити імена хостів NETBIOS.

8. Видобування хешів виконуваних бінарних файлів

У журналах створення процесів Sysmon EID 1 sysmon можна налаштувати для обчислення хешів бінарного файлу. Аналітики безпеки можуть порівнювати ці хеші з відомими шкідливими хешами за допомогою аналітики загроз. Ви можете видобути поле Hashes за допомогою наступного:

cat results.json | jq 'select ( .Details.Hashes? ) | .Details.Hashes ' -r

Це дасть вам список хешів на кшталт цього:

MD5=E112A827FAB9F8378C76040187A6F336,SHA256=ED369187681A62247E38D930320F1CD771756D0B7B67072D8EC655EF99E14AEB,IMPHASH=8EEAA9499666119D13B3F44ECD77A729
MD5=E112A827FAB9F8378C76040187A6F336,SHA256=ED369187681A62247E38D930320F1CD771756D0B7B67072D8EC655EF99E14AEB,IMPHASH=8EEAA9499666119D13B3F44ECD77A729
MD5=E112A827FAB9F8378C76040187A6F336,SHA256=ED369187681A62247E38D930320F1CD771756D0B7B67072D8EC655EF99E14AEB,IMPHASH=8EEAA9499666119D13B3F44ECD77A729
MD5=E112A827FAB9F8378C76040187A6F336,SHA256=ED369187681A62247E38D930320F1CD771756D0B7B67072D8EC655EF99E14AEB,IMPHASH=8EEAA9499666119D13B3F44ECD77A729

Sysmon зазвичай обчислює кілька хешів, таких як MD5, SHA1 та IMPHASH. Ви можете видобути ці хеші за допомогою регулярних виразів у jq або просто використати нарізання рядка для кращої продуктивності.

Наприклад, ви можете видобути хеші MD5 та видалити дублікати за допомогою наступного:

cat results.json | jq 'select ( .Details.Hashes? ) | .Details.Hashes | .[4:36] ' -r | sort | uniq

9. Видобування журналів PowerShell

Журнали Scriptblock PowerShell (EID: 4104) зазвичай розбиваються на багато журналів, і під час виведення у формат CSV Hayabusa видаляє символи табуляції та повернення, щоб зробити вивід більш стислим. Однак найлегше аналізувати журнали powershell з оригінальним форматуванням табуляції та символів повернення та об'єднанням журналів разом. Ось приклад видобування журналів PowerShell EID 4104 з COMPUTER-A та збереження їх у файл .ps1, щоб відкрити та проаналізувати у VSCode тощо... Після видобування поля ScriptBlock ми використовуємо awk, щоб замінити \r\n та \n на символи повернення, а \t на символи табуляції.

cat results.json | jq 'select ( .EventID == 4104 and .Details.ScriptBlock? != "n/a"  and .Computer == "COMPUTER-A.domain.local" ) | .Details.ScriptBlock , "\r\n"' -j | awk '{ gsub(/\\r\\n/,"\r\n"); print; }' | awk '{ gsub(/\\t/, "\t"); print; }' | awk '{ gsub(/\\n/, "\r\n"); print; }' > 4104-PowerShell-Logs.ps1

Після того, як аналітик проаналізує журнали на наявність шкідливих команд PowerShell, йому зазвичай потрібно буде знайти, коли ці команди було запущено. Ось приклад виведення мітки часу та журналів PowerShell у файл CSV, щоб знайти час, коли було запущено команду:

cat results.json | jq ' select (.EventID == 4104 and .Details.ScriptBlock? != "n/a" and .Computer == "COMPUTER-A.domain.local") | .Timestamp, ",¦", .Details.ScriptBlock?, "¦\r\n" ' -j | awk '{ gsub(/\\r\\n/,"\r\n"); print; }' | awk '{ gsub(/\\t/,"\t"); print; }' | awk '{ gsub(/\\n/,"\r\n"); print; }' > 4104-PowerShell-Logs.csv

Примітка: Використаний роздільник рядків — ¦, оскільки одинарні та подвійні лапки часто зустрічаються в журналах PowerShell і пошкоджують вивід CSV. Коли ви імпортуєте файл CSV, вам потрібно вказати застосунку роздільник рядків ¦.