diff --git a/Get-UserLastLogonComputer.ps1 b/Get-UserLastLogonComputer.ps1 new file mode 100644 index 0000000..6a5f7a9 --- /dev/null +++ b/Get-UserLastLogonComputer.ps1 @@ -0,0 +1,142 @@ +#Requires -Modules ActiveDirectory +<# +.SYNOPSIS + Exports a list of users and the last PC they logged into. + +.DESCRIPTION + Queries Domain Controller security event logs for interactive logon events (4624) + to determine which computer each user last authenticated from. + +.PARAMETER OutputPath + Path for the output CSV file. Defaults to current directory. + +.PARAMETER DaysBack + Number of days of event logs to search. Default is 7. + +.PARAMETER LogonTypes + Array of logon types to include. Default is 2 (Interactive) and 10 (RemoteInteractive/RDP). + +.EXAMPLE + .\Get-UserLastLogonComputer.ps1 + +.EXAMPLE + .\Get-UserLastLogonComputer.ps1 -OutputPath "C:\Reports" -DaysBack 30 + +.NOTES + Must be run on a Domain Controller with appropriate permissions to read Security logs. + Logon Type 2 = Interactive (console) + Logon Type 10 = RemoteInteractive (RDP) + Logon Type 11 = CachedInteractive +#> + +[CmdletBinding()] +param( + [Parameter()] + [string]$OutputPath = (Get-Location).Path, + + [Parameter()] + [int]$DaysBack = 7, + + [Parameter()] + [int[]]$LogonTypes = @(2, 10, 11) +) + +$Timestamp = Get-Date -Format "yyyyMMdd_HHmmss" +$CsvFile = Join-Path $OutputPath "UserLastLogonComputer_$Timestamp.csv" + +Write-Host "`nQuerying security event logs for the last $DaysBack days..." -ForegroundColor Cyan +Write-Host "Looking for logon types: $($LogonTypes -join ', ')" -ForegroundColor Cyan +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' + } + + Write-Host "Found $($Events.Count) logon events. Processing..." -ForegroundColor Yellow + + $UserLogons = @{} + + foreach ($Event in $Events) { + $xml = [xml]$Event.ToXml() + + $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 + + if ([string]::IsNullOrWhiteSpace($Workstation)) { + $Workstation = "Unknown" + } + + $UserKey = "$Domain\$Username" + + # Keep only the most recent logon for each user + if (-not $UserLogons.ContainsKey($UserKey) -or $LogonTime -gt $UserLogons[$UserKey].LogonTime) { + $UserLogons[$UserKey] = [PSCustomObject]@{ + Domain = $Domain + Username = $Username + Computer = $Workstation.ToUpper() + LogonTime = $LogonTime + LogonType = switch ($LogonType) { + 2 { "Interactive" } + 10 { "RDP" } + 11 { "Cached" } + default { $LogonType } + } + } + } + } + + $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 + return + } + + # Export to CSV + $Results | Select-Object Domain, Username, Computer, LogonTime, LogonType | + Export-Csv -Path $CsvFile -NoTypeInformation -Encoding UTF8 + + Write-Host "`n===== Results =====" -ForegroundColor Green + Write-Host "Total users found: $($Results.Count)" + Write-Host "Output saved to: $CsvFile" + Write-Host "" + + # 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 { + Write-Host "`nError: $($_.Exception.Message)" -ForegroundColor Red +}