-
Notifications
You must be signed in to change notification settings - Fork 276
Fixed Get-LogWinEvent, updated README.MD #200
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
dmoore44
wants to merge
18
commits into
davehull:master
Choose a base branch
from
dmoore44:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 8 commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
9914b5b
Update Get-LogWinEvent.ps1
dmoore44 48762bf
Update Get-LogWinEvent.ps1
dmoore44 53248a4
Update Get-LogWinEvent.ps1
dmoore44 79a700e
Update Get-LogWinEvent.ps1
dmoore44 f70d235
Update README.md
dmoore44 998ab5c
Update README.md
dmoore44 b499bbb
Update README.md
dmoore44 ed257f1
Update README.md
dmoore44 ff6c50e
Create Install-PowerForensics.ps1
dmoore44 aed4eee
Create Get-ForAlternateDataStreams.ps1
dmoore44 0b8c2e5
Create Get-ForAttrDef.ps1
dmoore44 374961c
Create Get-ForFileRecord.ps1
dmoore44 cefa1e8
Create Get-ForFileRecordIndex.ps1
dmoore44 48b3e86
Create Get-ForFileSlack.ps1
dmoore44 0b513f6
Create Get-ForMftSlack.ps1
dmoore44 85a335f
Update Modules.conf
dmoore44 f6705c3
Create Get-
dmoore44 61ea7ff
Rename Get- to Get-ForUsnJrnl.ps1
dmoore44 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,30 +1,190 @@ | ||
| <# | ||
| <# | ||
| .SYNOPSIS | ||
| Get-LogWinEvent | ||
| .PARAMETER LogName | ||
| A required parameter, that names the event log to acquire data from. | ||
| To see a list of common lognames run: | ||
| Get-WinEvent -ListLog | Select LogName | ||
|
|
||
| When used with Kansa.ps1, parameters must be positional. Named params | ||
| are not supported. | ||
| Get-LogWinEvent | ||
| .PARAMETER Params | ||
| A required parameter. I'll call this a pseudo parameter. This is due to the fact that you, the user, is really providing 3 parameters | ||
| worth of information that later gets parsed out in to separate parameters. | ||
|
|
||
| The format for this parameter follows this syntax: log name(s) [separated by a pipe if you want to specify more than one]-days ago-event IDs [separated | ||
| by a pipe if you want to specify more than one]. | ||
|
|
||
| Note: when used with Kansa.ps1, parameters must be positional. Named params are not supported. | ||
|
|
||
| .EXAMPLE | ||
| Single log, no additional filtering: | ||
| Get-LogWinEvent.ps1 Security | ||
|
|
||
| .EXAMPLE | ||
| Get-LogWinEvent.ps1 Security | ||
| Multiple logs, over the past 7 days, with specified Event IDs | ||
| Get-LogWinEvent.ps1 Security|System-7-4625|4634|4798|267|507 | ||
| .EX | ||
| .NOTES | ||
| When passing specific modules with parameters via Kansa.ps1's | ||
| -ModulePath parameter, be sure to quote the entire string, like shown | ||
| here: | ||
| .\kansa.ps1 -Target localhost -ModulePath ".\Modules\Log\Get-LogWinEvent.ps1 Security" | ||
| When passing specific modules with parameters via Kansa.ps1's -ModulePath parameter, be sure to quote the entire string, like shown | ||
| here: | ||
| .\kansa.ps1 -Target localhost -ModulePath ".\Modules\Log\Get-LogWinEvent.ps1 Security" | ||
|
|
||
| Thanks to Jeff Hicks for providng the Convert-EventLogRecord function, which allows for enhanced event log collections! | ||
| Original blog post found here: https://jdhitsolutions.com/blog/powershell/7193/better-event-logs-with-powershell/ | ||
|
|
||
| Next line is required by Kansa for proper handling of this script's | ||
| output. | ||
| OUTPUT TSV | ||
| #> | ||
|
|
||
| [CmdletBinding()] | ||
| Param( | ||
| [Parameter(Mandatory=$True,Position=0)] | ||
| [String]$LogName | ||
| ) | ||
| [CmdletBinding()] | ||
| Param( | ||
| [Parameter(Mandatory=$True,Position=0)] | ||
| [String]$Params | ||
| ) | ||
|
|
||
| $unparsedLogSelection = ($params -split "-")[0] | ||
| $daysAgo = ($params -split "-")[1] | ||
| $unparsedEventIDs = ($params -split "-")[2] | ||
|
|
||
| # At a minimum, the user needs to specify at least one log name. If a valid log name is not specified, | ||
| # The script fails. | ||
| [String[]]$LogName = $unparsedLogSelection -split "\|" | ||
|
|
||
| # Add a check to see if $daysAgo is populated - technically, it is an optional parameter. | ||
| # If the user declined to specify, set $daysAgo to $null and search through all the logs. | ||
| if ($daysAgo -eq $null) { | ||
| $daysAgo = $null | ||
| } | ||
| else { | ||
| [int]$daysAgo = $daysAgo | ||
| } | ||
|
|
||
| # Add a check to see if we need to populate $EventIDs. It too is an optional patameter. | ||
| # If the user declined to specify a list of event ids, set the parameter to $null and get all of the | ||
| # event ids for the specified log(s). | ||
| if ($unparsedEventIDs -eq $null) { | ||
| $EventIDs = $null | ||
| } | ||
| else { | ||
| [String[]]$EventIDs = $unparsedEventIDs -split "\|" | ||
| } | ||
|
|
||
| Function Convert-EventLogRecord { | ||
|
|
||
| [cmdletbinding()] | ||
| [alias("clr")] | ||
|
|
||
| Param( | ||
| [Parameter(Position = 0, Mandatory, ValueFromPipeline)] | ||
| [ValidateNotNullorEmpty()] | ||
| [System.Diagnostics.Eventing.Reader.EventLogRecord[]]$LogRecord | ||
| ) | ||
|
|
||
| Begin { | ||
| Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)" | ||
| } #begin | ||
|
|
||
| Process { | ||
| foreach ($record in $LogRecord) { | ||
| Write-Verbose "[PROCESS] Processing event id $($record.ID) from $($record.logname) log on $($record.machinename)" | ||
| Write-Verbose "[PROCESS] Creating XML data" | ||
| [xml]$r = $record.ToXml() | ||
|
|
||
| $h = [ordered]@{ | ||
| LogName = $record.LogName | ||
| RecordType = $record.LevelDisplayName | ||
| TimeCreated = $record.TimeCreated | ||
| ID = $record.Id | ||
| } | ||
|
|
||
| if ($r.Event.EventData.Data.Count -gt 0) { | ||
| Write-Verbose "[PROCESS] Parsing event data" | ||
| if ($r.Event.EventData.Data -is [array]) { | ||
| <# | ||
| I only want to enumerate with the For loop if the data is an array of objects | ||
| If the data is just a single string like Foo, then when using the For loop, | ||
| the data value will be the F and not the complete string, Foo. | ||
| #> | ||
| for ($i = 0; $i -lt $r.Event.EventData.Data.count; $i++) { | ||
|
|
||
| $data = $r.Event.EventData.data[$i] | ||
| #test if there is structured data or just text | ||
| if ($data.name) { | ||
| $Name = $data.name | ||
| $Value = $data.'#text' | ||
| } | ||
| else { | ||
| Write-Verbose "[PROCESS] No data property name detected" | ||
| $Name = "RawProperties" | ||
| #data will likely be an array of strings | ||
| [string[]]$Value = $data | ||
| } | ||
|
|
||
| if ($h.Contains("RawProperties")) { | ||
| Write-Verbose "[PROCESS] Appending to RawProperties" | ||
| $h.RawProperties += $value | ||
| } | ||
| else { | ||
| Write-Verbose "[PROCESS] Adding $name" | ||
| $h.add($name, $Value) | ||
| } | ||
| } #for data | ||
| } #data is an array | ||
| else { | ||
| $data = $r.Event.EventData.data | ||
| if ($data.name) { | ||
| $Name = $data.name | ||
| $Value = $data.'#text' | ||
| } | ||
| else { | ||
| Write-Verbose "[PROCESS] No data property name detected" | ||
| $Name = "RawProperties" | ||
| #data will likely be an array of strings | ||
| [string[]]$Value = $data | ||
| } | ||
|
|
||
| if ($h.Contains("RawProperties")) { | ||
| Write-Verbose "[PROCESS] Appending to RawProperties" | ||
| $h.RawProperties += $value | ||
| } | ||
| else { | ||
| Write-Verbose "[PROCESS] Adding $name" | ||
| $h.add($name, $Value) | ||
| } | ||
| } | ||
| } #if data | ||
| else { | ||
| Write-Verbose "[PROCESS] No event data to process" | ||
| } | ||
|
|
||
| $h.Add("Message", $record.Message) | ||
| $h.Add("Keywords", $record.KeywordsDisplayNames) | ||
| $h.Add("Source", $record.ProviderName) | ||
| $h.Add("Computername", $record.MachineName) | ||
|
|
||
| Write-Verbose "[PROCESS] Creating custom object" | ||
| New-Object -TypeName PSObject -Property $h | ||
| } #foreach record | ||
| } #process | ||
|
|
||
| End { | ||
| Write-Verbose "[END ] Ending: $($MyInvocation.Mycommand)" | ||
| } #end | ||
| } #end Convert-EventLogRecord | ||
|
|
||
| If ($DaysAgo -eq $null) { | ||
| $StartDate = $($(Get-WinEvent -LogName Security -Oldest -MaxEvents 1).TimeCreated) | ||
| $EndDate = Get-Date | ||
| $Span = $(New-TimeSpan -Start $StartDate -End $EndDate).Days | ||
| } # end If | ||
| Else {$Span = $DaysAgo} # end else | ||
|
|
||
| $StartTime = (Get-Date).AddDays(-$Span) | ||
|
|
||
| Get-WinEvent -LogName $LogName | ||
| if ($EventIDs.Count -eq 0) { | ||
| ForEach ($log in $LogName) { | ||
| Get-WinEvent -FilterHashtable @{ Logname=$LogName; StartTime=$StartTime} -EA SilentlyContinue | Convert-EventLogRecord | ||
| } # end ForEach ($log in LogName) | ||
| } # end If | ||
| else { | ||
| ForEach ($log in $LogName) { | ||
| ForEach ($id in $EventIDs) { | ||
| Get-WinEvent -FilterHashtable @{ Logname=$LogName; StartTime=$StartTime; ID=$id} -EA SilentlyContinue | Convert-EventLogRecord | ||
| } # end inner ForEach ($id in $EventIDs) | ||
| } # end outter ForEach ($log in LogName) | ||
| } # end else | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not trying to nitpick, but it looks like the event ids here are mostly from the security event log. I know they are just examples, but examples would be better if they were correct. If I'm wrong, my apologies.
I have not tested this syntax yet. Have you? How does the code determine that the pipe separated values are event logs v event ids?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No - you're correct. Those event IDs are mostly from the security log - I was pulling IDs from memory when writing the example, and those are just happen to be ones I query for the most.
I have tested the syntax and it works as expected. I specify in the comments that the "params" parameter follows an exacting format: "The format for this parameter follows this syntax: log name(s) [separated by a pipe if you want to specify more than one]-days ago-event IDs [separated by a pipe if you want to specify more than one]."
There are no explicit checks to ensure proper ordering of data passed to the "params" parameter. Params is explicitly cast as a string in its declaration statement and then immediately split in the appropriately type cast variables. Beyond that, there is no checking that a given log name is valid (that, I think would be rather un do-able given the number of event log collections available), or that the data passed in is entered in the correct order.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So if a user passes in multiple logs (e.g. Security, System, etc.) and a string of event IDs, does the code look in each log for all the given event IDs?