Загрузка данных
<#
.SYNOPSIS
Находит события в журнале Security, в которых фигурирует указанная учётная запись.
.DESCRIPTION
Скрипт ищет события по имени пользователя (или SID) в полях SubjectUserName, TargetUserName,
AccountName, MemberName (для имени) или SubjectUserSid, TargetUserSid, AccountSid, MemberSid (для SID).
Результат можно ограничить по времени и максимальному количеству записей.
.PARAMETER Identity
Имя учётной записи (например, 'Admin' или 'DOMAIN\Admin') или SID (например, 'S-1-5-21-...').
.PARAMETER LogName
Имя журнала (по умолчанию 'Security').
.PARAMETER MaxEvents
Максимальное количество возвращаемых событий (по умолчанию 1000; установите 0 для отключения лимита).
.PARAMETER StartTime
Начальная дата/время для фильтрации событий (опционально).
.PARAMETER EndTime
Конечная дата/время для фильтрации событий (опционально).
.EXAMPLE
.\Find-SecurityEventsByAccount.ps1 -Identity "Admin"
Находит все события (до 1000) с участием пользователя 'Admin'.
.EXAMPLE
.\Find-SecurityEventsByAccount.ps1 -Identity "S-1-5-21-123456789-123456789-123456789-500" -MaxEvents 0 -StartTime (Get-Date).AddDays(-1)
Находит все события за последние сутки с участием указанного SID (без ограничения количества).
.NOTES
Автор: Скрипт сгенерирован по запросу.
Версия: 1.0
#>
param(
[Parameter(Mandatory=$true, Position=0)]
[string]$Identity,
[string]$LogName = 'Security',
[int]$MaxEvents = 1000,
[datetime]$StartTime,
[datetime]$EndTime,
[switch]$Verbose
)
# Функция для построения XPath-запроса
function Build-XPathFilter {
param(
[string]$Identity,
[bool]$IsSID
)
# Поля для имени пользователя
$nameFields = @('SubjectUserName', 'TargetUserName', 'AccountName', 'MemberName')
# Поля для SID
$sidFields = @('SubjectUserSid', 'TargetUserSid', 'AccountSid', 'MemberSid')
$fields = if ($IsSID) { $sidFields } else { $nameFields }
$conditions = @()
# Экранирование одинарных кавычек в Identity (замена ' на ' в XPath, но проще использовать concat)
# Для простоты предполагаем, что Identity не содержит кавычек, либо используем двойные кавычки в XPath.
# В XPath строки можно заключать в одинарные или двойные кавычки.
# Используем одинарные, а внутри экранируем, заменяя ' на ' (но это не всегда работает).
# Лучше использовать concat, но для простоты предположим, что в Identity нет апострофов.
$escapedIdentity = $Identity -replace "'", "'"
foreach ($field in $fields) {
$conditions += "Data[@Name='$field']='$escapedIdentity'"
}
if ($conditions.Count -eq 0) {
throw "Нет полей для поиска."
}
# Собираем условие через OR
$conditionString = $conditions -join ' or '
# XPath-запрос: все события, где в EventData есть хотя бы одно совпадение
$xpath = "*[EventData[$conditionString]]"
return $xpath
}
# Проверяем, является ли Identity SID
$isSID = $Identity -match '^S-1-\d+(-\d+)*$'
# Формируем XPath
try {
$xpathFilter = Build-XPathFilter -Identity $Identity -IsSID $isSID
} catch {
Write-Error "Ошибка построения XPath: $_"
exit 1
}
# Параметры для Get-WinEvent
$getWinEventParams = @{
LogName = $LogName
FilterXPath = $xpathFilter
ErrorAction = 'Stop'
}
if ($MaxEvents -gt 0) {
$getWinEventParams.MaxEvents = $MaxEvents
}
if ($StartTime) {
$getWinEventParams.StartTime = $StartTime
}
if ($EndTime) {
$getWinEventParams.EndTime = $EndTime
}
if ($Verbose) {
Write-Verbose "Используемый XPath: $xpathFilter"
Write-Verbose "Поиск в журнале: $LogName"
}
# Выполняем запрос
try {
$events = Get-WinEvent @getWinEventParams
} catch {
Write-Error "Не удалось получить события из журнала '$LogName': $_"
exit 1
}
# Проверяем, найдены ли события
if ($events.Count -eq 0) {
Write-Host "Событий с участием '$Identity' не найдено." -ForegroundColor Yellow
exit 0
}
# Выводим результаты в удобном виде
$events | ForEach-Object {
[PSCustomObject]@{
TimeCreated = $_.TimeCreated
Id = $_.Id
Level = $_.LevelDisplayName
Message = $_.Message -replace "`r`n", " " -replace "`n", " " # убираем переносы для компактности
}
} | Sort-Object TimeCreated -Descending | Format-Table -AutoSize -Wrap
# Дополнительно выводим общее количество найденных событий
Write-Host "Найдено событий: $($events.Count)" -ForegroundColor Green