diff --git a/Get-UserLogonActivity.ps1 b/Get-UserLogonActivity.ps1 index 29882b3..8f6da8b 100644 --- a/Get-UserLogonActivity.ps1 +++ b/Get-UserLogonActivity.ps1 @@ -119,6 +119,21 @@ Function Get-EventDataValueFromList { Return $null } +Function Get-UserDataEventXmlValue { + Param( + [Parameter(Mandatory=$true)] + [xml]$EventXml, + + [Parameter(Mandatory=$true)] + [string]$Name + ) + + $Data = $EventXml.Event.UserData.EventXML.ChildNodes | Where-Object { $_.Name -eq $Name } | Select-Object -First 1 + If ($null -eq $Data) { Return $null } + + Return [string]$Data.'#text' +} + Function Test-UserLogonActivityUser { Param( [AllowNull()] @@ -211,12 +226,14 @@ Function New-UserLogonActivityRecord { [string]$User, [Parameter(Mandatory=$true)] - [ValidateSet('logon', 'logoff', 'unlock', 'lock', 'sleep', 'wake', 'shutdown', 'restart', 'power on')] + [ValidateSet('logon', 'logoff', 'unlock', 'lock', 'remote logon', 'session disconnect', 'session reconnect', 'screensaver start', 'screensaver dismiss', 'sleep', 'wake', 'shutdown', 'restart', 'power on')] [string]$Activity, [Parameter(Mandatory=$true)] [string]$Source, + [string]$Details = '', + [int]$SourcePriority = 50, [switch]$AllowSystemUser @@ -230,6 +247,7 @@ Function New-UserLogonActivityRecord { User = $User Activity = $Activity Source = $Source + Details = $Details SourcePriority = $SourcePriority TimeCreated = $TimeCreated } @@ -266,13 +284,34 @@ Function ConvertTo-SecurityUserActivity { $Activity = $null $Source = $null $SourcePriority = 20 + $Details = '' Switch ($Event.Id) { 4624 { - If ($LogonType -ne '7') { Return $null } - $Activity = 'unlock' - $Source = 'Security 4624 type 7' - $SourcePriority = 30 + Switch ($LogonType) { + '7' { + $Activity = 'unlock' + $Source = 'Security 4624 type 7' + $SourcePriority = 30 + } + '10' { + $Activity = 'remote logon' + $Source = 'Security 4624 type 10' + $SourcePriority = 20 + + $IpAddress = Get-EventDataValue -EventXml $EventXml -Name 'IpAddress' + $WorkstationName = Get-EventDataValue -EventXml $EventXml -Name 'WorkstationName' + $DetailsParts = @() + + If (-not [string]::IsNullOrWhiteSpace($IpAddress) -and $IpAddress -ne '-') { $DetailsParts += "Address=${IpAddress}" } + If (-not [string]::IsNullOrWhiteSpace($WorkstationName) -and $WorkstationName -ne '-') { $DetailsParts += "Workstation=${WorkstationName}" } + + $Details = $DetailsParts -join '; ' + } + Default { + Return $null + } + } } 4800 { $Activity = 'lock' @@ -282,12 +321,53 @@ Function ConvertTo-SecurityUserActivity { $Activity = 'unlock' $Source = 'Security 4801' } + 4802 { + $Activity = 'screensaver start' + $Source = 'Security 4802' + } + 4803 { + $Activity = 'screensaver dismiss' + $Source = 'Security 4803' + } Default { Return $null } } - New-UserLogonActivityRecord -TimeCreated $Event.TimeCreated -User (Format-UserName -DomainName $DomainName -UserName $UserName) -Activity $Activity -Source $Source -SourcePriority $SourcePriority + New-UserLogonActivityRecord -TimeCreated $Event.TimeCreated -User (Format-UserName -DomainName $DomainName -UserName $UserName) -Activity $Activity -Source $Source -Details $Details -SourcePriority $SourcePriority +} + +Function ConvertTo-TerminalServicesUserActivity { + Param( + [Parameter(Mandatory=$true)] + [object]$Event + ) + + $EventXml = [xml]$Event.ToXml() + $User = Get-UserDataEventXmlValue -EventXml $EventXml -Name 'User' + $SessionID = Get-UserDataEventXmlValue -EventXml $EventXml -Name 'SessionID' + $Address = Get-UserDataEventXmlValue -EventXml $EventXml -Name 'Address' + $DetailsParts = @() + + If ([string]::IsNullOrWhiteSpace($User)) { Return $null } + If (-not [string]::IsNullOrWhiteSpace($SessionID)) { $DetailsParts += "Session=${SessionID}" } + If (-not [string]::IsNullOrWhiteSpace($Address) -and $Address -ne '-') { $DetailsParts += "Address=${Address}" } + + Switch ($Event.Id) { + 24 { + $Activity = 'session disconnect' + $Source = 'TermSvc 24' + } + 25 { + $Activity = 'session reconnect' + $Source = 'TermSvc 25' + } + Default { + Return $null + } + } + + New-UserLogonActivityRecord -TimeCreated $Event.TimeCreated -User $User -Activity $Activity -Source $Source -Details ($DetailsParts -join '; ') -SourcePriority 20 } Function ConvertTo-PowerUserActivity { @@ -430,7 +510,7 @@ Function Write-UserLogonActivityOutput { [object[]]$ActivityEvents ) - $Rows = @($ActivityEvents | Select-Object Date,Time,User,Activity,Source) + $Rows = @($ActivityEvents | Select-Object Date,Time,User,Activity,Source,Details) If ($Rows.Count -eq 0) { Write-Output 'No matching user logon activity events found.' @@ -449,16 +529,21 @@ $WinlogonFilter = @{ $SecurityFilter = @{ LogName = 'Security' - Id = @(4800, 4801) + Id = @(4800, 4801, 4802, 4803) } -# Security 4624 type 7 is unlock authentication evidence. Query it separately so it cannot -# crowd out 4800/4801 workstation lock/unlock events in latest-event mode. +# Security 4624 type 7 is unlock authentication evidence and type 10 is RDP evidence. +# Query 4624 separately so it cannot crowd out 4800/4801 workstation lock/unlock events. $UnlockAuthFilter = @{ LogName = 'Security' Id = 4624 } +$TerminalServicesFilter = @{ + LogName = 'Microsoft-Windows-TerminalServices-LocalSessionManager/Operational' + Id = @(24, 25) +} + $PowerFilters = @( @{ LogName = 'System' @@ -503,6 +588,8 @@ If ($UseDateRange) { $SecurityFilter.EndTime = $EndDateTime.LocalDateTime $UnlockAuthFilter.StartTime = $StartDateTime.LocalDateTime $UnlockAuthFilter.EndTime = $EndDateTime.LocalDateTime + $TerminalServicesFilter.StartTime = $StartDateTime.LocalDateTime + $TerminalServicesFilter.EndTime = $EndDateTime.LocalDateTime ForEach ($PowerFilter in $PowerFilters) { $PowerFilter.StartTime = $StartDateTime.LocalDateTime $PowerFilter.EndTime = $EndDateTime.LocalDateTime @@ -522,6 +609,10 @@ If ($UseDateRange) { Add-UserLogonActivityRecord -ActivityEvents $ActivityEvents -ActivityEvent (ConvertTo-SecurityUserActivity -Event $Event) } + ForEach ($Event in (Get-UserLogonActivityWinEvent -FilterHashtable $TerminalServicesFilter -LogDescription 'Terminal Services Local Session Manager event log')) { + Add-UserLogonActivityRecord -ActivityEvents $ActivityEvents -ActivityEvent (ConvertTo-TerminalServicesUserActivity -Event $Event) + } + ForEach ($PowerFilter in $PowerFilters) { ForEach ($Event in (Get-UserLogonActivityWinEvent -FilterHashtable $PowerFilter -LogDescription 'System power event log')) { Add-UserLogonActivityRecord -ActivityEvents $ActivityEvents -ActivityEvent (ConvertTo-PowerUserActivity -Event $Event) @@ -542,6 +633,7 @@ Else { $WinlogonEvents = @(Get-UserLogonActivityWinEvent -FilterHashtable $WinlogonFilter -MaxEvents $SearchLimit -LogDescription 'System Winlogon event log') $SecurityEvents = @(Get-UserLogonActivityWinEvent -FilterHashtable $SecurityFilter -MaxEvents $SearchLimit -LogDescription 'Security event log') $UnlockAuthEvents = @(Get-UserLogonActivityWinEvent -FilterHashtable $UnlockAuthFilter -MaxEvents $SearchLimit -LogDescription 'Security unlock-authentication event log') + $TerminalServicesEvents = @(Get-UserLogonActivityWinEvent -FilterHashtable $TerminalServicesFilter -MaxEvents $SearchLimit -LogDescription 'Terminal Services Local Session Manager event log') $PowerEvents = @() $PowerFiltersMayHaveMoreEvents = $false @@ -557,6 +649,10 @@ Else { Add-UserLogonActivityRecord -ActivityEvents $ActivityEvents -ActivityEvent (ConvertTo-SecurityUserActivity -Event $Event) } + ForEach ($Event in $TerminalServicesEvents) { + Add-UserLogonActivityRecord -ActivityEvents $ActivityEvents -ActivityEvent (ConvertTo-TerminalServicesUserActivity -Event $Event) + } + ForEach ($PowerFilter in $PowerFilters) { $CurrentPowerEvents = @(Get-UserLogonActivityWinEvent -FilterHashtable $PowerFilter -MaxEvents $SearchLimit -LogDescription 'System power event log') $PowerEvents += $CurrentPowerEvents @@ -572,7 +668,7 @@ Else { $OutputEvents = @(Get-UniqueUserLogonActivity -ActivityEvents $ActivityEvents | Sort-Object -Property TimeCreated -Descending | Select-Object -First $ActivityLimit) - If ($OutputEvents.Count -ge $ActivityLimit -or (($WinlogonEvents.Count -lt $SearchLimit) -and ($SecurityEvents.Count -lt $SearchLimit) -and ($UnlockAuthEvents.Count -lt $SearchLimit) -and -not $PowerFiltersMayHaveMoreEvents) -or $SearchLimit -ge $MaxSearchLimit) { + If ($OutputEvents.Count -ge $ActivityLimit -or (($WinlogonEvents.Count -lt $SearchLimit) -and ($SecurityEvents.Count -lt $SearchLimit) -and ($UnlockAuthEvents.Count -lt $SearchLimit) -and ($TerminalServicesEvents.Count -lt $SearchLimit) -and -not $PowerFiltersMayHaveMoreEvents) -or $SearchLimit -ge $MaxSearchLimit) { Break }