add usage window

This commit is contained in:
2026-07-08 11:27:51 -04:00
parent cce2950d10
commit ac85a06003
+169 -5
View File
@@ -193,6 +193,28 @@ Function Resolve-UserLogonActivitySid {
}
}
Function Get-UserLogonActivityKey {
Param(
[AllowNull()]
[object]$Sid,
[AllowNull()]
[string]$User
)
$SidString = ([string]$Sid).Trim()
If (-not [string]::IsNullOrWhiteSpace($SidString) -and $SidString -ne '-') {
Return $SidString.ToUpperInvariant()
}
$UserString = ([string]$User).Trim()
If (-not [string]::IsNullOrWhiteSpace($UserString)) {
Return $UserString.ToUpperInvariant()
}
Return ''
}
Function Get-UserLogonActivitySidFromEvent {
Param(
[Parameter(Mandatory=$true)]
@@ -234,6 +256,8 @@ Function New-UserLogonActivityRecord {
[string]$Details = '',
[string]$UserKey = '',
[int]$SourcePriority = 50,
[switch]$AllowSystemUser
@@ -241,6 +265,11 @@ Function New-UserLogonActivityRecord {
If (-not $AllowSystemUser -and -not (Test-UserLogonActivityUser -UserName $User)) { Return $null }
$ResolvedUserKey = $UserKey
If ([string]::IsNullOrWhiteSpace($ResolvedUserKey)) {
$ResolvedUserKey = Get-UserLogonActivityKey -Sid $null -User $User
}
[PSCustomObject]@{
Date = $TimeCreated.ToString('yyyy-MM-dd')
Time = $TimeCreated.ToString('HH:mm:ss')
@@ -248,6 +277,7 @@ Function New-UserLogonActivityRecord {
Activity = $Activity
Source = $Source
Details = $Details
UserKey = $ResolvedUserKey
SourcePriority = $SourcePriority
TimeCreated = $TimeCreated
}
@@ -265,10 +295,11 @@ Function ConvertTo-WinlogonUserActivity {
Default { Return $null }
}
$User = Resolve-UserLogonActivitySid -Sid (Get-UserLogonActivitySidFromEvent -Event $Event)
$UserSid = Get-UserLogonActivitySidFromEvent -Event $Event
$User = Resolve-UserLogonActivitySid -Sid $UserSid
If ([string]::IsNullOrWhiteSpace($User)) { Return $null }
New-UserLogonActivityRecord -TimeCreated $Event.TimeCreated -User $User -Activity $Activity -Source $Source -SourcePriority 10
New-UserLogonActivityRecord -TimeCreated $Event.TimeCreated -User $User -Activity $Activity -Source $Source -UserKey (Get-UserLogonActivityKey -Sid $UserSid -User $User) -SourcePriority 10
}
Function ConvertTo-SecurityUserActivity {
@@ -280,6 +311,7 @@ Function ConvertTo-SecurityUserActivity {
$EventXml = [xml]$Event.ToXml()
$UserName = Get-EventDataValueFromList -EventXml $EventXml -Names @('TargetUserName', 'SubjectUserName')
$DomainName = Get-EventDataValueFromList -EventXml $EventXml -Names @('TargetDomainName', 'SubjectDomainName')
$UserSid = Get-EventDataValueFromList -EventXml $EventXml -Names @('TargetUserSid', 'SubjectUserSid')
$LogonType = Get-EventDataValue -EventXml $EventXml -Name 'LogonType'
$Activity = $null
$Source = $null
@@ -334,7 +366,8 @@ Function ConvertTo-SecurityUserActivity {
}
}
New-UserLogonActivityRecord -TimeCreated $Event.TimeCreated -User (Format-UserName -DomainName $DomainName -UserName $UserName) -Activity $Activity -Source $Source -Details $Details -SourcePriority $SourcePriority
$User = Format-UserName -DomainName $DomainName -UserName $UserName
New-UserLogonActivityRecord -TimeCreated $Event.TimeCreated -User $User -Activity $Activity -Source $Source -Details $Details -UserKey (Get-UserLogonActivityKey -Sid $UserSid -User $User) -SourcePriority $SourcePriority
}
Function ConvertTo-TerminalServicesUserActivity {
@@ -367,7 +400,7 @@ Function ConvertTo-TerminalServicesUserActivity {
}
}
New-UserLogonActivityRecord -TimeCreated $Event.TimeCreated -User $User -Activity $Activity -Source $Source -Details ($DetailsParts -join '; ') -SourcePriority 20
New-UserLogonActivityRecord -TimeCreated $Event.TimeCreated -User $User -Activity $Activity -Source $Source -Details ($DetailsParts -join '; ') -UserKey (Get-UserLogonActivityKey -Sid $null -User $User) -SourcePriority 20
}
Function ConvertTo-PowerUserActivity {
@@ -478,12 +511,22 @@ Function Get-UniqueUserLogonActivity {
ForEach ($ActivityEvent in (@($ActivityEvents) | Where-Object { $null -ne $_ } | Sort-Object -Property TimeCreated,User,Activity,SourcePriority)) {
$IsDuplicate = $false
$ActivityEventKey = [string]$ActivityEvent.UserKey
If ([string]::IsNullOrWhiteSpace($ActivityEventKey)) {
$ActivityEventKey = Get-UserLogonActivityKey -Sid $null -User $ActivityEvent.User
}
For ($Index = 0; $Index -lt $UniqueEvents.Count; $Index++) {
$UniqueEvent = $UniqueEvents[$Index]
$UniqueEventKey = [string]$UniqueEvent.UserKey
If ([string]::IsNullOrWhiteSpace($UniqueEventKey)) {
$UniqueEventKey = Get-UserLogonActivityKey -Sid $null -User $UniqueEvent.User
}
If (
$UniqueEvent.User -eq $ActivityEvent.User -and
$UniqueEventKey -eq $ActivityEventKey -and
$UniqueEvent.Activity -eq $ActivityEvent.Activity -and
[Math]::Abs(($UniqueEvent.TimeCreated - $ActivityEvent.TimeCreated).TotalSeconds) -le 5
) {
@@ -520,6 +563,125 @@ Function Write-UserLogonActivityOutput {
Write-Output (($Rows | Format-Table -AutoSize | Out-String -Width 240).TrimEnd())
}
Function Get-PossibleUseWindow {
Param(
[AllowNull()]
[object[]]$ActivityEvents
)
$OpenWindows = @{}
$UseWindows = New-Object System.Collections.Generic.List[object]
$OpeningActivities = @('logon', 'unlock', 'remote logon', 'session reconnect', 'screensaver dismiss')
$ImpliedClosureDescriptions = @{
'unlock' = 'implied prior lock before'
'session reconnect' = 'implied prior disconnect before'
'screensaver dismiss' = 'implied prior screensaver before'
}
ForEach ($ActivityEvent in (@($ActivityEvents) | Where-Object { $null -ne $_ } | Sort-Object -Property TimeCreated)) {
$User = [string]$ActivityEvent.User
$UserKey = [string]$ActivityEvent.UserKey
$Activity = [string]$ActivityEvent.Activity
$Source = [string]$ActivityEvent.Source
If ([string]::IsNullOrWhiteSpace($UserKey)) {
$UserKey = Get-UserLogonActivityKey -Sid $null -User $User
}
If ($Activity -in @('sleep', 'shutdown', 'restart')) {
ForEach ($OpenUserKey in @($OpenWindows.Keys)) {
$OpenWindow = $OpenWindows[$OpenUserKey]
$UseWindows.Add([PSCustomObject]@{
StartTime = $OpenWindow.StartTime
Start = $OpenWindow.StartTime.ToString('yyyy-MM-dd HH:mm:ss')
End = $ActivityEvent.TimeCreated.ToString('yyyy-MM-dd HH:mm:ss')
User = $OpenWindow.User
StartedBy = $OpenWindow.StartedBy
EndedBy = "${Activity} / ${Source}"
}) | Out-Null
$OpenWindows.Remove($OpenUserKey)
}
Continue
}
If ([string]::IsNullOrWhiteSpace($User) -or $User -eq 'SYSTEM' -or $User -eq 'NT AUTHORITY\SYSTEM') {
Continue
}
If ($Activity -in $OpeningActivities) {
If ($OpenWindows.ContainsKey($UserKey) -and $ImpliedClosureDescriptions.ContainsKey($Activity)) {
$OpenWindow = $OpenWindows[$UserKey]
$UseWindows.Add([PSCustomObject]@{
StartTime = $OpenWindow.StartTime
Start = $OpenWindow.StartTime.ToString('yyyy-MM-dd HH:mm:ss')
End = "before $($ActivityEvent.TimeCreated.ToString('yyyy-MM-dd HH:mm:ss'))"
User = $OpenWindow.User
StartedBy = $OpenWindow.StartedBy
EndedBy = "$($ImpliedClosureDescriptions[$Activity]) ${Activity} / ${Source}"
}) | Out-Null
$OpenWindows.Remove($UserKey)
}
If (-not $OpenWindows.ContainsKey($UserKey)) {
$OpenWindows[$UserKey] = [PSCustomObject]@{
StartTime = $ActivityEvent.TimeCreated
User = $User
StartedBy = "${Activity} / ${Source}"
}
}
}
ElseIf ($Activity -in @('logoff', 'lock', 'session disconnect')) {
If ($OpenWindows.ContainsKey($UserKey)) {
$OpenWindow = $OpenWindows[$UserKey]
$UseWindows.Add([PSCustomObject]@{
StartTime = $OpenWindow.StartTime
Start = $OpenWindow.StartTime.ToString('yyyy-MM-dd HH:mm:ss')
End = $ActivityEvent.TimeCreated.ToString('yyyy-MM-dd HH:mm:ss')
User = $OpenWindow.User
StartedBy = $OpenWindow.StartedBy
EndedBy = "${Activity} / ${Source}"
}) | Out-Null
$OpenWindows.Remove($UserKey)
}
}
}
ForEach ($OpenUserKey in @($OpenWindows.Keys)) {
$OpenWindow = $OpenWindows[$OpenUserKey]
$UseWindows.Add([PSCustomObject]@{
StartTime = $OpenWindow.StartTime
Start = $OpenWindow.StartTime.ToString('yyyy-MM-dd HH:mm:ss')
End = 'open through returned events'
User = $OpenWindow.User
StartedBy = $OpenWindow.StartedBy
EndedBy = 'not closed in returned events'
}) | Out-Null
}
Return $UseWindows
}
Function Write-PossibleUseWindowOutput {
Param(
[AllowNull()]
[object[]]$ActivityEvents
)
$UseWindows = @(Get-PossibleUseWindow -ActivityEvents $ActivityEvents | Sort-Object -Property StartTime)
If ($UseWindows.Count -eq 0) {
Write-Output ''
Write-Output 'Possible use windows inferred from returned events: none'
Return
}
$Rows = @($UseWindows | Select-Object Start,End,User,StartedBy,EndedBy)
Write-Output ''
Write-Output 'Possible use windows inferred from returned events:'
Write-Output (($Rows | Format-Table -AutoSize | Out-String -Width 240).TrimEnd())
}
# Winlogon 7001/7002 tracks user session logon/logoff more reliably than Security 4624/4634.
$WinlogonFilter = @{
LogName = 'System'
@@ -621,6 +783,7 @@ If ($UseDateRange) {
$OutputEvents = @(Get-UniqueUserLogonActivity -ActivityEvents $ActivityEvents | Sort-Object -Property TimeCreated)
Write-UserLogonActivityOutput -ActivityEvents $OutputEvents
Write-PossibleUseWindowOutput -ActivityEvents $OutputEvents
}
Else {
$ActivityLimit = 15
@@ -676,4 +839,5 @@ Else {
} While ($true)
Write-UserLogonActivityOutput -ActivityEvents $OutputEvents
Write-PossibleUseWindowOutput -ActivityEvents $OutputEvents
}