Fix event log query - use FilterHashtable instead of XPath, better error handling
This commit is contained in:
@@ -50,52 +50,48 @@ Write-Host ""
|
||||
|
||||
$StartDate = (Get-Date).AddDays(-$DaysBack)
|
||||
|
||||
# Build XPath filter for Event ID 4624 (Successful Logon)
|
||||
$LogonTypeFilter = ($LogonTypes | ForEach-Object { "Data[@Name='LogonType']=$_" }) -join " or "
|
||||
$XPath = @"
|
||||
*[System[
|
||||
EventID=4624
|
||||
and TimeCreated[@SystemTime >= '$($StartDate.ToUniversalTime().ToString("o"))']
|
||||
]
|
||||
and EventData[
|
||||
($LogonTypeFilter)
|
||||
]
|
||||
]
|
||||
"@
|
||||
|
||||
try {
|
||||
Write-Host "Retrieving logon events from Security log..." -ForegroundColor Yellow
|
||||
|
||||
$Events = Get-WinEvent -LogName Security -FilterXPath $XPath -ErrorAction Stop |
|
||||
Where-Object {
|
||||
$xml = [xml]$_.ToXml()
|
||||
$targetUser = ($xml.Event.EventData.Data | Where-Object { $_.Name -eq 'TargetUserName' }).'#text'
|
||||
$targetDomain = ($xml.Event.EventData.Data | Where-Object { $_.Name -eq 'TargetDomainName' }).'#text'
|
||||
# Filter out computer accounts and system accounts
|
||||
$targetUser -notmatch '\$$' -and
|
||||
$targetUser -notin @('SYSTEM', 'LOCAL SERVICE', 'NETWORK SERVICE', 'DWM-1', 'DWM-2', 'UMFD-0', 'UMFD-1') -and
|
||||
$targetDomain -ne 'Window Manager' -and
|
||||
$targetDomain -ne 'Font Driver Host'
|
||||
# Use hashtable filter - more reliable than XPath for date filtering
|
||||
$FilterHash = @{
|
||||
LogName = 'Security'
|
||||
ID = 4624
|
||||
StartTime = $StartDate
|
||||
}
|
||||
|
||||
Write-Host "Found $($Events.Count) logon events. Processing..." -ForegroundColor Yellow
|
||||
$Events = Get-WinEvent -FilterHashtable $FilterHash -ErrorAction Stop
|
||||
|
||||
Write-Host "Found $($Events.Count) total 4624 events. Filtering..." -ForegroundColor Yellow
|
||||
|
||||
$UserLogons = @{}
|
||||
$ProcessedCount = 0
|
||||
|
||||
foreach ($Event in $Events) {
|
||||
$xml = [xml]$Event.ToXml()
|
||||
|
||||
$LogonType = [int]($xml.Event.EventData.Data | Where-Object { $_.Name -eq 'LogonType' }).'#text'
|
||||
|
||||
# Skip if not a logon type we want
|
||||
if ($LogonType -notin $LogonTypes) { continue }
|
||||
|
||||
$Username = ($xml.Event.EventData.Data | Where-Object { $_.Name -eq 'TargetUserName' }).'#text'
|
||||
$Domain = ($xml.Event.EventData.Data | Where-Object { $_.Name -eq 'TargetDomainName' }).'#text'
|
||||
$Workstation = ($xml.Event.EventData.Data | Where-Object { $_.Name -eq 'WorkstationName' }).'#text'
|
||||
$LogonType = ($xml.Event.EventData.Data | Where-Object { $_.Name -eq 'LogonType' }).'#text'
|
||||
$LogonTime = $Event.TimeCreated
|
||||
|
||||
# Filter out computer accounts and system accounts
|
||||
if ($Username -match '\$$') { continue }
|
||||
if ($Username -in @('SYSTEM', 'LOCAL SERVICE', 'NETWORK SERVICE', 'DWM-1', 'DWM-2', 'DWM-3', 'UMFD-0', 'UMFD-1', 'UMFD-2', 'ANONYMOUS LOGON', '-')) { continue }
|
||||
if ($Domain -in @('Window Manager', 'Font Driver Host', 'NT AUTHORITY')) { continue }
|
||||
if ([string]::IsNullOrWhiteSpace($Username)) { continue }
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($Workstation)) {
|
||||
$Workstation = "Unknown"
|
||||
}
|
||||
|
||||
$UserKey = "$Domain\$Username"
|
||||
$ProcessedCount++
|
||||
|
||||
# Keep only the most recent logon for each user
|
||||
if (-not $UserLogons.ContainsKey($UserKey) -or $LogonTime -gt $UserLogons[$UserKey].LogonTime) {
|
||||
@@ -108,16 +104,22 @@ try {
|
||||
2 { "Interactive" }
|
||||
10 { "RDP" }
|
||||
11 { "Cached" }
|
||||
default { $LogonType }
|
||||
default { "Type $LogonType" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Processed $ProcessedCount matching logon events." -ForegroundColor Yellow
|
||||
|
||||
$Results = $UserLogons.Values | Sort-Object Domain, Username
|
||||
|
||||
if ($Results.Count -eq 0) {
|
||||
Write-Host "`nNo user logon events found in the specified time period." -ForegroundColor Yellow
|
||||
Write-Host "`nNo user logon events found matching criteria." -ForegroundColor Yellow
|
||||
Write-Host "This could mean:"
|
||||
Write-Host " - No interactive/RDP logons in the last $DaysBack days"
|
||||
Write-Host " - Audit policy may not be logging logon events"
|
||||
Write-Host " - Try increasing -DaysBack value"
|
||||
return
|
||||
}
|
||||
|
||||
@@ -133,10 +135,19 @@ try {
|
||||
# Display summary table
|
||||
$Results | Format-Table -AutoSize
|
||||
|
||||
} catch [System.Diagnostics.Eventing.Reader.EventLogNotFoundException] {
|
||||
Write-Host "`nError: Security event log not accessible. Ensure you're running on a DC with appropriate permissions." -ForegroundColor Red
|
||||
} catch [System.UnauthorizedAccessException] {
|
||||
Write-Host "`nError: Access denied. Run as Administrator with permissions to read Security logs." -ForegroundColor Red
|
||||
} catch {
|
||||
} catch [System.Exception] {
|
||||
if ($_.Exception.Message -match "No events were found") {
|
||||
Write-Host "`nNo logon events (Event ID 4624) found in the last $DaysBack days." -ForegroundColor Yellow
|
||||
Write-Host "`nPossible causes:" -ForegroundColor Cyan
|
||||
Write-Host " 1. Audit policy not enabled - Run: auditpol /get /category:`"Logon/Logoff`""
|
||||
Write-Host " 2. Security log was cleared recently"
|
||||
Write-Host " 3. Try a larger -DaysBack value"
|
||||
Write-Host ""
|
||||
Write-Host "To enable logon auditing:" -ForegroundColor Cyan
|
||||
Write-Host " auditpol /set /subcategory:`"Logon`" /success:enable"
|
||||
} elseif ($_.Exception.Message -match "Access is denied") {
|
||||
Write-Host "`nError: Access denied. Run PowerShell as Administrator." -ForegroundColor Red
|
||||
} else {
|
||||
Write-Host "`nError: $($_.Exception.Message)" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user