Текстовая версия выступления на PHD12
Пару слов о проблеме
При реагировании на инциденты бывает необходимо посмотреть логи Windows машины, и аналитики подготавливают утилиты для удобной фильтрации событий в журналах evtx. Это связано с тем, что способы фильтрации, предложенные Microsoft, выглядят крайне не удобно.
Live response — это область, которая занимается сбором информации с работающего компьютера, чтобы определить, произошел ли инцидент.
При проведении live response анализа, полезно быстро понять, что происходило с компьютером в последнее время.
![](https://habrastorage.org/getpro/habr/upload_files/7d8/5d4/422/7d85d4422b01612cda37beb3f9f8fa81.png)
Существуют различные инструменты для проведения live response: коммерческие, с открытым исходным кодом и встроенные возможности ОС.
Использование opensource и коммерческих инструментов связано с рядом проблем:
Утилиты могут отправлять телеметрию разработчику
Отсутствие описания анализируемых журналов и EventId
Неудобство фильтрации оснасткой eventvwr.msc
Фильтрация evtx с помощью стандартной оснастки просмотра событий (eventvwr.msc) ограничена в возможностях.
Проблемы:
отсутствует возможность вывести информацию в колонках
отсутствуют регулярные выражения и поиск подстрок
отсутствует группировка
![eventvwr.msc eventvwr.msc](https://habrastorage.org/getpro/habr/upload_files/2b9/f43/7a3/2b9f437a3179835a7dae714ce54035c1.png)
Кроме того, стандартная оснастка просмотра событий не поддерживает все функции XPath, что может создавать дополнительные проблемы при фильтрации.
![Ограничения XPath для фильтрации событий Ограничения XPath для фильтрации событий](https://habrastorage.org/getpro/habr/upload_files/88e/e5b/233/88ee5b2338893d20d82a016a060ad566.png)
Одним из основных ограничений XPath 1.0 является то, что он не поддерживает поиск по атрибутам. То есть, если вы хотите найти события, связанные с определенным EventID, вы можете воспользоваться элементом EventID, но вы не сможете использовать атрибуты, вложенных элементов для поиска событий, например: TargetUserName.
![Пример события в формате XML Пример события в формате XML](https://habrastorage.org/getpro/habr/upload_files/0a6/fb5/753/0a6fb5753c28db63fea53ebb0f40cfe0.png)
XPath, в оснастке, не поддерживает регулярные выражения и поиск подстрок, которые могут быть полезны при фильтрации журналов событий Windows. Регулярные выражения позволяют искать текстовые строки, соответствующие определенному шаблону, что может быть полезно, например, при поиске IP-адресов или имен файлов.
Таким образом, недостатки XPath для фильтрации журналов событий Windows заключаются в ограниченных возможностях поиска по атрибутам вложенных элементов, отсутствии некоторых функций сравнения, а также отсутствии поддержки регулярных выражений.
Как показано выше, узлы «Элемент» могут содержать «Атрибуты», и мы можем использовать подстановочный знак «@» для поиска узлов «Data».
Пример ниже позволяет найти все события из журнала Security c EventID = 4688. Атрибут Path в директиве Query можно опустить. Путь к журналу указывается в в атрибуте Path директивы Select.
<QueryList>
<Query Id="0" Path="Security">
<Select Path="Security">*[System[EventID=4688]]</Select>
</Query>
</QueryList>
В пример ниже добавляем использования логического оператора OR для поиска события с EventID 4688 или 4624.
<QueryList>
<Query Id="0" Path="Security">
<Select Path="Security">*[System[EventID=4688 or EventID=4624]]</Select>
</Query>
</QueryList>
В следующем примере добавим фильтрацию по разделу XML - EventData. Для объединения двух условий в одном Select используется логический оператор AND. Вторая часть запроса начинается со знака *, который означает что верхний узел может принимать любое значение, далее мы указываем путь к атрибуту значение которого хотим указать в условии EventData -> Data -> @Атрибут="значение".
<QueryList>
<Query Id="0" Path="Security">
<Select Path="Security">*[System[EventID=4688]] and
*[EventData[Data[@Name="SubjectUserName"]="hacker"]]</Select>
</Query>
</QueryList>
XPath позволяет искать значение по всем атрибутам, как в примере ниже. Структура указанные выше изменилась до EventData -> Data -> @Атрибут ="значение". Следующим запросам мы найдем все события где в атрибутах фигурировало "C:\Windows\System32\lsass.exe"
<QueryList>
<Query Id="0" Path="Security">
<Select Path="Security">*[System[EventID=4688]] and
*[EventData[Data="C:\Windows\System32\lsass.exe"]]</Select>
</Query>
</QueryList>
Оператор Suppress позволяет исключить из конечной выборки события, которые подходят под условие в нем. В примере ниже, мы найдем все события 4624, в которых LogonType=5.
<QueryList>
<Query Id="0" Path="Security">
<Select Path="Security">*[System[EventID=4624]]</Select>
<Suppress Path="Security">*[EventData[Data[@Name='LogonType']=5]]</Suppress>
</Query>
</QueryList>
В пределах одного Query мы можем указывать несколько Select-запросов, также есть возможность запрашивать события из разных журналов.
<QueryList>
<Query Id="0">
<Select Path="Security">*[System[EventID=4688]]</Select>
<Select Path="Windows PowerShell">*</Select>
</Query>
</QueryList>
В одном QueryList может быть несколько Query. Это удобно для логического разбиения запросов и их фильтрации.
<QueryList>
<Query Id="0" Path="Security">
<Select Path="Security">*[System[EventID=4688]]</Select>
</Query>
<Query Id="1" Path="Microsoft-Windows-Sysmon/Operational">
<Select Path="Microsoft-Windows-Sysmon/Operational">*</Select>
</Query>
</QueryList>
Таким образом, фильтрация evtx с помощью стандартной оснастки просмотра событий и XPath 1.0 ограничена и не всегда удобна. Для более гибкой и удобной работы с журналами событий можно использовать специализированные инструменты для анализа журналов, которые предоставляют более широкие возможности фильтрации и поиска информации.
Возможности CMD
Возможности CMD ограничены использованием двух основных утилит wevtutil и Findstr. wevtutil позволяет работать с параметрами журналов и создавать к ним запросы. Для запросов в wevtutil также используются XPath-запросы.
wevtutil.exe qe Security /q:"*[EventData[Data[@Name='TargetUserName']='User1' and Data[@Name='LogonType']=2]]" /f:text
При использовании findstr, наши возможности расширяются для поиска интересующих нас строк.
wevtutil.exe qe Security /q:"*[EventData[Data[@Name='LogonType']=11]]" /f:text | findstr "Account Name"
Возможности PowerShell
В Powershell для работы с журналами существуют два командлета Get-EventLog и Get-WinEvent. Мы рассмотри второй командлет так как он считается актуальным.
Основные возможности Get-WinEvent это использование хеш-таблиц и Xpath для фильтрации событий. Для использование хеш-таблиц используется аргумент -FilterHashtable, его можно опустить и строить запрос сразу с @{<выражение>}.
![Ограничение при создании FilterHastale Ограничение при создании FilterHastale](https://habrastorage.org/getpro/habr/upload_files/f6b/b71/818/f6bb7181865fe94981c6b00804b69127.png)
Рассмотрим несколько примеров использования командлета Get-WinEvent и построения конвейеров с ним.
Следующим примером мы выведем 1000 событий из журнала Security.
Get-WinEvent -LogName Security -MaxEvents 1000
![](https://habrastorage.org/getpro/habr/upload_files/9f6/597/f65/9f6597f65b24283e84c9d65877a735c8.png)
Тот же запрос, но используем Format-List для приведения вывода в читаемый.
Get-WinEvent -LogName Secutity -MaxEvents 10 | Format-List
![](https://habrastorage.org/getpro/habr/upload_files/963/97e/b29/96397eb29893d8ca2a80282e376773b4.png)
Используем FilterHashtable. Выведем события из журнала Security с EventId 4688.
Get-WinEvent @{logname="security";ID=4688} -MaxEvents 100 | Format-List
Для понимания дальнейших фильтров давайте посмотрим как представлено событие в Powershell, для этого выведем одно событие и воспользуемся командлетом Get-Member.
Get-WinEvent @{logname="security";ID=4688} -MaxEvents 1 | Get-Member
![](https://habrastorage.org/getpro/habr/upload_files/d2c/5e8/fe1/d2c5e8fe1e169b0ad52fc31ea6beacc1.png)
Свойство Properties - это список, который хранит основные параметры события, которые расположены в секции EventData xml-представления.
После того, как мы научились получать события из определенного журнала и по определенному EventId, давайте посмотрим каким образом мы можем получить интересующие нас данные. Давайте выведем события 4688, и отобразим время создания события и {$_.Properties[5].value}, которое хранит имя запущенного процесса. Номер элемента списка Properties соответствует номеру атрибута в секции EventData xml-представления события.
Get-WinEvent @{logname="security";ID=4688} -MaxEvents 100 |
select timecreated,{$_.Properties[5].value} | Format-List
![](https://habrastorage.org/getpro/habr/upload_files/6f5/512/cf5/6f5512cf5f0297c26cf427b62ebfcdd5.png)
Powershell позволяет нам создавать группировки, используя командлет Group-Object. Следующим запросом сгруппируем события Sysmon EventId 3 по следующим полям: процесс, адрес получателя, доменное имя получателя, порт получателя.
Get-WinEvent @{LogName="*sysmon*";ID=3} -MaxEvents 10000 |
Where-Object {$_.Properties[16].Value -ne 443} |
Group-Object {$_.Properties[4].Value},{$_.Properties[14].Value}, {$_.Properties[15].Value}, {$_.Properties[16].Value} |
Select-Object Name, Count | Sort-Object Count -Descending | Format-List
![](https://habrastorage.org/getpro/habr/upload_files/aeb/4f8/cf6/aeb4f8cf6a5e39922b55e343746fd9f5.png)
Для поиска подстрок можем воспользоваться -Match или -Like.
Get-WinEvent @{LogName="*sysmon*";ID=1} -MaxEvents 1000 |
Where-Object {$_.Properties[10].Value -Match ".*cmd.exe" } |
Select-Object {$_.Properties[10].Value} |
Format-List
![](https://habrastorage.org/getpro/habr/upload_files/535/90d/64b/53590d64bc915418e92e7a50601ee6ec.png)
Поиска событий с известным значением атрибута выполняется быстрее при использовании XPath запросов, чем конвейеров Powershell. Например: запрос ниже найдет все события, связанные с пользователем R00t1k\Vadim.
Get-WinEvent -LogName *Sysmon* -FilterXPath "*[EventData[Data[@Name='User']='LAB\vadim']]" |
Where-Object {$_.Properties[4].Value -Match ".*WINWORD.exe"} |
Format-List
![](https://habrastorage.org/getpro/habr/upload_files/95f/7d3/d0c/95f7d3d0c934c0a577e4950b3e8ac0b9.png)
Poweshell позволяет представить сообщение в виде xml, выполнив следующий код.
$eventlog = Get-WinEvent -FilterHashtable @{LogName="Security";ID=4624} -MaxEvents 1
$xml = [xml]$eventlog.ToXml()
$xml.Event.EventData.Data
![](https://habrastorage.org/getpro/habr/upload_files/f1c/116/6b8/f1c1166b868baa9e55855df19c283d64.png)
Модуль Powershell Convert-EventLogRecord преобразовывает события в структуру данных, которая позволяет обращаться к атрибутам по их имени. Конвейер для фильтрации событий с Convert-EventLogRecord будет выполняться в 2-3 раза дольше, в отличие от ковейера без его использования.
# С использованием Convert-EventLogRecord
Get-WinEvent -FilterHashtable @{LogName="Security";ID=4624} |
Convert-EventLogRecord | Where-Object LogonType -ne 5 |
Select TimeCreated, TargetUserName, LogonType
# Без использования Convert-EventLogRecord
Get-WinEvent @{LogName="Security";Id=4624} |
Where-Object {$_.Properties[8].Value -ne 5} |
Select TimeCreated, {$_.Properties[5].Value}, {$_.Properties[8].Value}
Используя командлет Out-GridView мы можем вывести события в виде таблицы.
Get-WinEvent -FilterHashtable @{LogName='Security'; ID=4624} |
Select-Object TimeCreated,
@{Name='User'; Expression={$_.Properties[5].Value}},
@{Name='LogonType'; Expression={$_.Properties[8].Value}},
@{Name='SrcIp'; Expression={$_.Properties[18].Value}} |
Out-GridView
![](https://habrastorage.org/getpro/habr/upload_files/98b/f5a/10e/98bf5a10ee6a27eff88a3ffc2b97cba1.png)
Для вывода нескольких событий в таблицу нужно учитывать, что порядковые номера атрибутов у разных EventId могут хранить разные данные.
Get-WinEvent -FilterHashtable @{LogName='Security'; ID=4624, 4688} -MaxEvents 1000 | Where-Object {$_.Properties[8].Value -ne 5} |
ForEach-Object {
if ($_.Id -eq 4624) {
$Username = $_.Properties[5].Value
$LogonType = $_.Properties[8].Value
$LogonProcess = $_.Properties[9].Value
$IpAddress = $_.Properties[18].Value
}
elseif ($_.Id -eq 4688) {
$SubjectUserName = $_.Properties[1].Value
$SubjectUserDomain = $_.Properties[2].Value
$NewProcessName = $_.Properties[5].Value
$CommandLine= $_.Properties[8].Value
$ParrentProcessName= $_.Properties[13].Value
}
[PSCustomObject]@{
Time = $_.TimeCreated
EventID = $_.Id
Username = $Username
LogonType = $LogonType
LogonProcess = $LogonProcess
IpAddress = $IpAddress
SubjectUserName = $SubjectUserName
SubjectUserDomain = $SubjectUserDomain
NewProcessName = $NewProcessName
CommandLine = $CommandLine
ParrentProcessName = $ParrentProcessName
}
} | Out-GridView
![](https://habrastorage.org/getpro/habr/upload_files/79a/a28/4c3/79aa284c364adaec9b7d8adf1d46e3ec.png)
Перед расследованием инцидентов, стоит уделить время первому этапу при реагировании - подготовка. Оказавшись в ситуации без флешки, с подготовленным софтом, Вы не растерялись и смогли понять, что происходило в журналах Windows. Во второй статье, рассмотрим утилиты, упомянутые в докладе.