In part 1, we looked at PowerShell get winevent to work with the event log: Get-WinEvent. In part 2 we looked at 10 practical examples of using Get-WinEvent to perform threat hunting using event log data, using -FilterHashTable, the PowerShell pipeline, and -FilterXPath.
In this article we’ll look at using a third-party script to make the data in the Get-WinEventMessage property much more easily accessible.
Paul Masek (SANS Advisor Board member and threat hunting fan) reached out after my part 1 article to share a third-party script that makes working with the Get-WinEventMessage property data much easier: Convert-EventLogRecords.
Get-WinEvent is a powerful cmdlet, and once you get the hang of building filter hash tables (see part 2 of this series) you can quickly interrogate event logs for a lot of data. However, the data in the event log Message property is not nearly as easily accessible.
For example, let’s look at event ID 4624 in the Security event log, An account was successfully logged on:
When we access the Message property in the pipeline, it appears as if it were unstructured data: just a big string blob with indentations and newlines. However, this data is actually an XML structure with lots of elements that are individually accessible, just not as Get-WinEvent properties.
Let’s dig into the Message property for the event ID 4624 event, declaring a variable $logonEvent:
Next, let’s convert the $logonEvent variable into XML format:
Here we declare a new variable for ease-of-access called $xml. The value stored in $xml is the result of calling the ToXml() method on the $logonEvent variable for the 4624 event ID.
To see a list of available methods on a variable, use Get-Member (e.g., $logonEvent | Get-Member -MemberType Method).
With the $xml variable declared, we can start to interrogate the data and look at the available properties. You can start just by entering the variable name:
This output indicates there is a member object called Event. We can access this object using dot notation:
This reveals that $xml.Event has three member objects: xmlns, System, and EventData. We can continue to interrogate the data by using dot notation to access the EventData object:
Which reveals a Data object:
Accessing $xml.Event.EventData.Data displays lots of new parameters accessible by name instead of just one large string. This is the data that can be accessed using XmlPath notation (e.g., *[EventData[Data[@Name=’ProcessName’]). But, as Paul pointed out to me, there is an easier way.
Convert-EventLogRecord is a PowerShell function written by @JeffHicks, available as part of his PSScriptTools project. Using Convert-EventLogRecord allows us to easily use Get-WinEvent, taking the individual XML data elements in the Message property and make them individually accessible on the pipeline.
TL/DR: It makes the event log data much more easily accessible.
To use this function, first make a location where you can store PowerShell scripts. I’ll make a directory called C:\Tools. Then, change to the directory and download the Convert-EventLogRecord.ps1 script, as shown here:
You can use the mkdir, cd, and iwr aliases instead of typing out these commands..I’m trying to get in the habit of typing full command names for clarity in documentation.
Next, import the script for use. To use the script on Windows 10, you’ll need to change the PowerShell ExecutionPolicy. On Twitter advice, change the policy to RemoteSigned to block browser-downloaded PowerShell scripts, but not local scripts like those downloaded with Invoke-WebRequest (again, I think PowerShell execution policies are silly; more on that another time):
Next, import the Convert-EventLogRecord.ps1 into the PowerShell session namespace using Import-Module:
Perfect! Now you have access to Convert-EventLogRecord as a function in PowerShell. Let’s take a look at the properties available for the 4624 event with and without it. First, here are the properties available using Get-WinEvent with a filter for event ID 4624:
Here is the same event, this time using Convert-EventLogRecord:
When we add Convert-EventLogRecord to the pipeline, it takes the elements in the Message parameter and makes them accessible as properties. This allows us to retrieve specific information elements such as TargetUserName:
Since these added Message data elements are properties, we can reference them in the pipeline using Where-Object too:
Let’s break down this command step-by-step:
Convert-EventLogRecord makes accessing the data in the Message property a lot easier, but it can be detrimental to performance if used with lots of event data. Each event returned in the pipeline has the XML data extracted and added as custom properties to the object. This isn’t a lot of overhead, but if you send all events to Convert-EventLogRecord for filtering then you may be in for some waiting.
To avoid unnecessary performance detriment, remember this rule:
Filter hash table first; Convert-EventLogRecord if you must.
For example, let’s say you want to see the Security event logs with event ID 4799 (A security-enabled local group membership was enumerated.) where the process name enumerating the group is not svchost.exe. You could use Convert-EventLogRecord to query both the event ID and the process name in the pipeline:
This took NNN seconds. I took a nap while it was running and came back. This example violates the rule: filter hash table first. We can rewrite this query using a filter hash table for the event ID, then use Convert-EventLogRecord and Where-Object for the properties we can’t access in the filter hash table:
Only 18 seconds on my system, a huge improvement. Remember:
Filter hash table first; Convert-EventLogRecord if you must.
In this article we looked we looked at some of the challenges in accessing the data elements embedded within the event log Message property, and how the Convert-EVentLogRecord function makes accessing that data much easier, giving you a lot more flexibility in building a pipeline to query the event log.
We have one last article in this short series: optimizing the Windows event log configuration. Stay tuned!
-Joshua Wright
Return to Getting Started With PowerShell
Joshua Wright is the author of SANS SEC504: Hacker Tools, Techniques, and Incident Handling, a faculty fellow for the SANS Institute, and a senior technical director at Counter Hack.