Garacesh Posted November 13, 2014 Posted November 13, 2014 Working on my "Who vandalised this laptop?" script again as I realised it would still report back our accounts and test users (Resulting in confused teachers wondering who the SpencerP account was.. Sorry guize, but Pootis isn't a student here..) so I'm trying to make it ignore a series of 8 accounts. Our 4 IT staff accounts, the 2 test pupils and the 2 test staff.. $IgnoreList = ("Acc1", "Acc2", .... "Acc8") foreach ($event in Get-WinEvent -ComputerName ($ComputerName + "." + $env:USERDNSDOMAIN) -FilterHashtable @{ProviderName="Microsoft-Windows-Security-Auditing"; ID="4624"; Data="C:\Windows\System32\winlogon.exe"} -MaxEvents ($MaxEvents) | [color="#FF0000"]Where-Object {$IgnoreList -inotmatch $_.Message}[/color]) { [indent][array]$Logins += (($event.timecreated).ToString("dd/MM/yyyy, HH:mm:ss") + ($($event.message -split "`r`n")[12]) + "`n`r")[/indent] } I've tried all sorts to compare.. $_.Message to the items inside $IgnoreList but I can only seem to get it working if $IgnoreList contains only one item. I don't think you can include a ForEach or ForEach-Object in conjuction with a Where-Object Because usernames are variable length, substrings won't work AFAIK as they need explicitly set lengths (I.E. $_.Message.SubString(36..50)) Though I know it will work, I don't really want to use 8 iterations of ($._Message -inotmatch "Acc1") -and ($_.Message -inotmatch "Acc2") -and... etc Am I going to be stuck with lots of -and comparators and have to do it one by one, or is there a better way..?
jamesb Posted November 13, 2014 Posted November 13, 2014 (edited) If you can get the SID of the users instead of username, maybe: Where-Object {$IgnoreList -notcontains $_.UserID}) might help? Edited November 13, 2014 by jamesb
Garacesh Posted November 13, 2014 Author Posted November 13, 2014 (edited) If you can get the SID of the users instead of username, maybe: Where-Object {$IgnoreList -notcontains $_.UserID}) might help? How would I go about trying SID's? Would those be the S-1-5-#-####(etc) string? I have tried -notcontains, but the issue is that at current, $_.Message is: An account was successfully logged on. Subject: Security ID: S-1-5-18 Account Name: MachineName$ Account Domain: Domain Logon ID: 0x3e7 Logon Type: 2 New Logon: Security ID: S-1-5-21-1184608939-106713722-1776120411-34238 Account Name: Username Account Domain: Domain Logon ID: 0x7e349 Logon GUID: {00000000-0000-0000-0000-000000000000} Process Information: Process ID: 0x290 Process Name: C:\Windows\System32\winlogon.exe Network Information: Workstation Name: MachineName Source Network Address: 127.0.0.1 Source Port: 0 Detailed Authentication Information: Logon Process: User32 Authentication Package: Negotiate Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a [...] if no session key was requested. So unfortunately -notcontains doesn't do me any good as $_.Message is more than just a username. I did attempt to make each username " Account Name: Username" rather than just the username, but it interprets $_.Message as all one item, therefore $_.Message[12] produces the character 'a' rather than line 13. Edited November 13, 2014 by Garacesh
jamesb Posted November 13, 2014 Posted November 13, 2014 SID is the S-blah blah number, and unique to each user. If you use $_.UserID rather than $_.Message to identify the events then it should check whether the SID is in your ignore list rather than trying to hunt down a string in a string. So you script ends up as: $IgnoreList = ("Acc1", "Acc2", .... "Acc8")foreach ($event in Get-WinEvent -ComputerName ($ComputerName + "." + $env:USERDNSDOMAIN) -FilterHashtable @{ProviderName="Microsoft-Windows-Security-Auditing"; ID="4624"; Data="C:\Windows\System32\winlogon.exe"} -MaxEvents ($MaxEvents) | Where-Object {$IgnoreList -notcontains [b]$_.UserID[/b]}) { [array]$Logins += (($event.timecreated).ToString("dd/MM/yyyy, HH:mm:ss") + ($($event.message -split "`r`n")[12]) + "`n`r") } -inotmatch will match (or not in this case) two strings, but doesn't handle arrays. -notcontains will check whether an item is in an array - in this case the UserIDs you want to ignore should be in the $IgnoreList array. It saves you needing a second loop, which is the only other option I can see. If you'd prefer to use usernames I can find a snippet that'll convert SIDs to usernames, or vice-versa.
Garacesh Posted November 13, 2014 Author Posted November 13, 2014 No, no, Username's aren't a requirement.. It just seemed the logical thing to check against since Line 13 is the only thing that gets pulled out of the event message (user account: $user) and matched with the appropriate timestamp ($_.TimeCreated) I'll give SID's a bash tomorrow. Thanks a lot!
Garacesh Posted November 14, 2014 Author Posted November 14, 2014 $_.UserID doesn't appear to be working.. Setting $MaxEvents at 1.. Get-WinEvent -ComputerName ($ComputerName + "." + $env:USERDNSDOMAIN) -FilterHashtable @{ProviderName="Microsoft-Windows-Security-Auditing"; ID="4624"; Data="C:\Windows\System32\winlogon.exe"} -MaxEvents ($MaxEvents).UserID ought to return just the SID of the last user, right? It's returning a null result. (Quite literally.. If I $Value = (Get-Wi...) etc and then $value -eq $null the result is True) It should work though, right? The Technet page does list UserID as a valid property.
jamesb Posted November 14, 2014 Posted November 14, 2014 Get-WinEvent -ComputerName ($ComputerName + "." + $env:USERDNSDOMAIN) -FilterHashtable @{ProviderName="Microsoft-Windows-Security-Auditing"; ID="4624"; Data="C:\Windows\System32\winlogon.exe"} -MaxEvents ($MaxEvents).UserID ought to return just the SID of the last user, right? It's returning a null result. (Quite literally.. If I $Value = (Get-Wi...) etc and then $value -eq $null the result is True) I'm confused... I think you've misplaced a bracket or two. Currently you're trying to put -MaxEvents $MaxEvents.UserID if your code is actually the above - and $MaxEvents, being just a number, won't have a user ID. Try: (Get-WinEvent -ComputerName ($ComputerName + "." + $env:USERDNSDOMAIN) -FilterHashtable @{ProviderName="Microsoft-Windows-Security-Auditing"; ID="4624"; Data="C:\Windows\System32\winlogon.exe"} -MaxEvents ($MaxEvents)).UserID
Garacesh Posted November 14, 2014 Author Posted November 14, 2014 Sorry! I typed out that command instead of copy-paste. I have been using brackets. PS M:\> (Get-WinEvent -ComputerName ($ComputerName + "." + $env:USERDNSDOMAIN) -FilterHashtable @{ProviderName="Microsof t-Windows-Security-Auditing"; ID="4624"; Data="C:\Windows\System32\winlogon.exe"} -MaxEvents ($MaxEvents)) TimeCreated ProviderName Id Message ----------- ------------ -- ------- 14/11/2014 12:09:47 Microsoft-Windows-Security... 4624 An account was successfull... PS M:\> (Get-WinEvent -ComputerName ($ComputerName + "." + $env:USERDNSDOMAIN) -FilterHashtable @{ProviderName="Microsof t-Windows-Security-Auditing"; ID="4624"; Data="C:\Windows\System32\winlogon.exe"} -MaxEvents ($MaxEvents)).UserID PS M:\>
Garacesh Posted November 17, 2014 Author Posted November 17, 2014 Sorry to doublepost/bump - I realised I haven't elaborated on the last post. Setting $MaxEvents as 1 and $ComputerName as a valid event that I know we've logged in as.. (Get-WinEvent -ComputerName ($ComputerName + "." + $env:USERDNSDOMAIN) -FilterHashtable @{ProviderName="Microsoft-Windows-Security-Auditing"; ID="4624"; Data="C:\Windows\System32\winlogon.exe"} -MaxEvents ($MaxEvents)) gets me TimeCreated ProviderName Id Message ----------- ------------ -- ------- 14/11/2014 12:09:47 Microsoft-Windows-Security... 4624 An account was successfull... as expected. The general WinEvent of somebody logging on. That's fine. If I wrap the whole thing in brackets and append .UserID, I get nothing.. Literally, nothing. If I -eq $Null the result is True.. But the Technet page for Get-WinEvent lists UserID as a valid property.. Perhaps it's only valid for the -FilterHashTable @{}?
jaminben Posted November 17, 2014 Posted November 17, 2014 (edited) Not sure if the below will help you out in anyway but its what I wrote along time ago and use occasionally.... it looks like your going for a more advanced version than mine. #---------------------------------------------- # Creatation Date: 02/03/2013 # Edited Date: 04/03/2013 # Created By: Jaminben # Version: 1.03 #---------------------------------------------- [string]$workingDirectory = Split-Path $MyInvocation.MyCommand.Path [string]$outFile = $workingDirectory + "\Computer_Users.csv" [int]$limitResults = 0 Write-Host "Created By: Jaminben`nVersion: 1.03" $computerName = read-host "`n`nEnter Computer Name" $limitResults = read-host "`nEnter Number Of Results To Display" Function getUsers { $UserProperty = @{n="User";e={(New-Object System.Security.Principal.SecurityIdentifier $_.ReplacementStrings[1]).Translate([system.Security.Principal.NTAccount])}} $TypeProperty = @{n="Action";e={if($_.EventID -eq 7001) {"Logon"} else {"Logoff"}}} $TimeProperty = @{n="Time";e={$_.TimeGenerated}} $netLogs = Get-EventLog -newest $limitResults System -Source Microsoft-Windows-Winlogon -ComputerName $computerName | select $UserProperty, $TypeProperty, $TimeProperty $netLogs.GetEnumerator() | Sort-Object Time -descending | Export-Csv $outFile -NoTypeInformation $netLogs.GetEnumerator() | Sort-Object Time -descending | Format-Table -autosize } Function checkConection { param($InputObject = $null) BEGIN {$status = $False} PROCESS { if((Test-Connection $InputObject -Quiet -count 1)) { $status = $True }else{ $status = $False } } END {return $status} } Function validName{ if (checkConection $computerName) { Write-Host "`nResponse OK" -ForegroundColor DarkGreen Write-Host "`nGathering EventLog Information..." Write-Host "`nPlease Wait A Moment...`n" getUsers }else{ Write-Host "`nResponse failed - Host Not Found" -ForegroundColor red } } if ($computerName -eq [string]::empty -or $limitResults -eq [string]::empty){ Write-Host "`nYou've Entered An Invalid Value" -ForegroundColor red }else{ validName } Write-Host "`n`nFinished..." Write-Host "`nPress any key to quit..." $x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") Edited November 17, 2014 by jaminben
Garacesh Posted November 17, 2014 Author Posted November 17, 2014 (edited) Oh, wow.. That looks so much 'cleaner' than my script.. Get-WinEvent doesn't work in Powershell V3 (unless you're En-US locale), but Get-ADUser doesn't work in Powershell V2.. So I have a Powershell V3 script that is fed parameters (ComputerName, MaxEvents, DamagedPart, RepairStatus, Email) so it uses Get-ADUser to make sure the e-mail address is a valid one, then passes all those parameters to a Powershell V2 script that runs Get-WinEvent (etc) and emails the result off to the member of staff specified (and CC to myself) It's so kludgy I'm surprised it actually works.. Edit: If I put UserID="AccName" into the -FilterHashTable @{} settings I get "Get-WinEvent : No events were found that match the specified selection criteria.".. Which makes no sense as I know the account used has logged in (It's logged in right now, actually..) If I use the full AccName.domain.local I get "Get-WinEvent : Some or all identity references could not be translated." Edit 2: Ref: Technet page.. "-- The UserID key can take a valid security identifier (SID) or a domain account name that can be used to construct a valid System.Security.Principal.NTAccount object." Edit 3: Same result applies if I use a full SID instead of a login name.. "Get-WinEvent : No events were found that match the specified selection criteria." Edited November 17, 2014 by Garacesh
jamesb Posted November 17, 2014 Posted November 17, 2014 I think the reason is that you can't select the property for a collection using .UserID - that'll only work on individual WinEvent objects. If instead of .UserID you try putting | Select -Property UserID you should get something back.
Garacesh Posted November 17, 2014 Author Posted November 17, 2014 (edited) I think the reason is that you can't select the property for a collection using .UserID - that'll only work on individual WinEvent objects. If instead of .UserID you try putting | Select -Property UserID you should get something back. Makes sense.. But nada. PS M:\> (Get-WinEvent -ComputerName ($ComputerName + "." + $env:USERDNSDOMAIN) -FilterHashtable @{ProviderName="Microsof t-Windows-Security-Auditing"; ID="4624"; Data="C:\Windows\System32\winlogon.exe"} -MaxEvents ($MaxEvents)) | Select -Pro perty UserID UserId ------ PS M:\> Edit: (Get-WinEvent -Com... etc).Property does work, it seems.. It looks like the problem is with UserID specifically. PS M:\> (Get-WinEvent -ComputerName ($ComputerName + "." + $env:USERDNSDOMAIN) -FilterHashtable @{ProviderName="Microsof t-Windows-Security-Auditing"; ID="4624"; Data="C:\Windows\System32\winlogon.exe"} -MaxEvents ($MaxEvents)).LogName Security PS M:\> (Get-WinEvent -ComputerName ($ComputerName + "." + $env:USERDNSDOMAIN) -FilterHashtable @{ProviderName="Microsof t-Windows-Security-Auditing"; ID="4624"; Data="C:\Windows\System32\winlogon.exe"} -MaxEvents ($MaxEvents)).ProviderName Microsoft-Windows-Security-Auditing PS M:\> Edit 2: When using .Property, LogName, ProviderName, Keywords, ID and Level all work.. Path, StartTime, EndTime, UserID and Data do not.. Edit 3: Further progress! Not using -FilterHashTable @{} does return a UserID (Get-WinEvent -ComputerName ($ComputerName + "." + $env:USERDNSDOMAIN) -MaxEvents ($MaxEvents)) | Select -Property UserID UserId ------ S-1-5-18 PS M:\> (Get-WinEvent -ComputerName ($ComputerName + "." + $env:USERDNSDOMAIN) -MaxEvents ($MaxEvents)).UserID BinaryLength AccountDomainSid Value ------------ ---------------- ----- 12 S-1-5-18 PS M:\> However, finding S-1-5-18 in HKLM\Software\Microsoft\Windows NT\CurrentVersion\ProfileList\ shows that it's the %systemroot%\system32\config\systemprofile account.. So I need to filter through events to not include those. I could use the hashtable, but if that's breaking the UserID flag (somehow?) I might have to add the 3 'service' accounts to the IgnoreList too. Edit 4: I might have broken it, or I might have made progress. Not sure. Adding those 3 service accounts to the ignore list and running the script without a hashtable (with MaxEvents a 5) results in.. 17/11/2014, 16:03:26 Account Name: MyAccount 17/11/2014, 16:03:26 SeDebugPrivilege 17/11/2014, 16:02:53 17/11/2014, 16:02:35 Logon GUID: {STRINGST-RING-STRI-NGST-RINGSTRINGST} 17/11/2014, 16:02:35 So it hasn't ignored my account like it should have done, but it has ignored the service accounts and the other tech who has also logged onto this machine but it hasn't gotten far enough to see any other logons as it isn't filtering the events with the hashtable anymore. It's also returned garbage. More work is required. Edited November 17, 2014 by Garacesh
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now