Tag Archives: Get-WinEvent

Retrieve Certificate from Event log binary data

As I was looking into some errors in my event log I found that I had a number of certificate errors in the event log. In order to investigate this further I wanted to take a look at the certificate in the event log. There are a number of tools available to extract this from the event log but I wanted to be able to automate this in the future so I settled on writing this in PowerShell.

I had the following events in my system event log:

Event

The interesting portion is what is stored in the XML, specifically EventData – Binary:

XMLView

In order to retrieve this event using PowerShell we can run the following code:

1
Get-WinEvent -FilterHashtable @{'Logname' = 'System' ; 'Id' = 36882} -MaxEvents 1

Get-WinEvent

In order to retrieve the binary data we can run the following code:

1
2
3
4
5
([xml](Get-WinEvent -FilterHashtable @{
        'Logname' = 'System'
        'Id' = 36882
    } -MaxEvents 1).ToXml()
).Event.Eventdata.Binary

The binary data is encoded as pairs of hexadecimal numbers, so this needs to be converted before we can write this to disk. In order to do this we split the string into pairs of two and then do a conversion using the ToByte method of the System.Convert class:

1
2
3
4
5
6
7
8
9
10
(
    ([xml](Get-WinEvent -FilterHashtable @{
            'Logname' = 'System'
            'Id'      = 36882
        } -MaxEvents 1).ToXml()
    ).Event.Eventdata.Binary -split '(..)' |
    Where-Object {$_} | ForEach-Object {
        [system.convert]::ToByte($_,16)
    }
)

Now that we have PowerShell output an array of bytes we are ready to write the output of the event log to file. Because we know this should be a certificate all we have to do is write this to a .cer file and we will have a working certificate:

1
2
3
4
5
6
7
8
9
10
11
12
13
[System.IO.File]::WriteAllBytes("$env:USERPROFILE\desktop\EventCert.cer",
    (
        (
            [xml](Get-WinEvent -FilterHashtable @{
                'Logname' = 'System'
                'Id'      = 36882
            } -MaxEvents 1).ToXml()
        ).Event.Eventdata.Binary -split '(..)' |
        Where-Object {$_} | ForEach-Object {
            [system.convert]::ToByte($_,16)
        }
    )
)

Now the following functional certificate will be available on the desktop:

EventCert

So there we have it, in this article we have identified the event that contains a certificate that. Afterwards we went into the xml of this event and retrieved the binary eventdata, converted this to a byte array and then wrote this to file.

Share

PSBlogweek: PowerShell logging in the Windows Event log

This post is part of the #PSBlogWeek PowerShell blogging series. #PSBlogWeek is a regular event where anyone interested in writing great content about PowerShell is welcome to volunteer for. The purpose is to pool our collective PowerShell knowledge together over a 5-day period and write about a topic that anyone using PowerShell may benefit from. #PSBlogWeek is a Twitter hashtag so feel free to stay up to date on the topic on Twitter at the #PSBlogWeek hashtag. For more information on #PSBlogWeek or if you’d like to volunteer for future sessions, contact Adam Bertram (@adbertram) on Twitter.

Once you’re done getting schooled on everything this post has to offer head on over to the powershell.org announcement for links to the other four past and upcoming #PSBlogWeek articles this week!


An important part of PowerShell scripting is error handling, one of the main differences between a script and a one-liner for me personally is error handling and dealing with exceptions that might occur. For more information on error handling please refer to the previous PSBlogWeek articles where Boe Prox dives into use Try-Catch in order to catch specific errors.

When moving your scripts from into a production environment logging becomes more important, initially using plain text files for logging might be an appropriate solution. Another option however is writing logging information to the Windows Event Log. This has the benefit of being the centralized location where most logging takes place.

Writing to the event log is relatively simple, the Write-EventLog cmdlet can be used for this purpose:

PSBlogWeek2015-1

By taking a look at the error message we see that the PowerShell event source is not registered with the application log, in order to resolve this, we can write to the Windows PowerShell event log instead:

1
Write-EventLog -LogName 'Windows PowerShell' -Source PowerShell -EventId 12345 -EntryType Information -Message 'Script started'

PSBlogWeek2015-2

Notice how the command now successfully executes without the error message, this is because it is important for the script

Alternatively, it is also possible to specify a custom event provider, and register this to the correct event log as such:

1
2
New-EventLog -Source AwesomeScript -LogName 'Windows PowerShell'
Write-EventLog -LogName 'Windows PowerShell' -Source AwesomeScript -EventId 12345 -EntryType Information -Message 'Script started'

PSBlogWeek2015-3

It is also possible to create an entire separate event log for your script logging, also by using the New-EventLog cmdlet:

1
2
3
4
New-EventLog -LogName 'Scripts' -Source 'Your Script'
Write-EventLog -LogName 'Scripts' -Source 'Your Script' -EventId 12345 -EntryType Information -Message 'Script started'
New-EventLog -LogName 'Scripts' -Source 'Your Script2'
Write-EventLog -LogName 'Scripts' -Source 'Your Script2' -EventId 12345 -EntryType Information -Message 'Script started'

PSBlogWeek2015-4

To build upon this, it would be possible to create a script that logs when the script starts, executes an action, when an error occurs and when the script ends.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
begin {
    $EventHashInformation = @{
        LogName   = 'Scripts'
        Source    = 'Your Script'
        EventId   = 30000
        EntryType = 'Information'
    }
    $EventHashWarning     = @{
        LogName   = 'Scripts'
        Source    = 'Your Script'
        EventId   = 40000
        EntryType = 'Warning'   
    }
    Write-EventLog @EventHashInformation -Message 'Script started'
}
 
process {
    try {
        Get-CimInstance -ClassName Win32_Bios -ErrorAction Stop
        Write-EventLog @EventHashInformation -Message 'Successfully queried Win32_Bios'
    } catch {
        Write-EventLog @EventHashWarning -Message 'Error occurred while  queried Win32_Bios'
    }
}
 
end {
    Write-EventLog @EventHashInformation -Message 'Script finished'
}

PSBlogWeek2015-5

Using this method of logging allows for a dynamic form of logging where information such as the timestamp are automatically added to the information. A nice feature of using the event log is that it also allows for exporting the information directory to xml, for example:

1
2
3
Get-WinEvent -FilterHashtable @{
    LogName = 'Scripts'
} | ForEach-Object {$_.ToXml()}

PSBlogWeek2015-6

Because this type of logging can quickly fill up the event logs it is important to set the limits and the type of logging the event logs can do. In order to verify the current configuration, we can use the Get-EventLog cmdlet:

1
2
Get-EventLog -List | Where-Object {$_.LogDisplayName -eq 'Scripts'} |
Select-Object -Property Log,MaximumKilobytes,MinimumRetentionDays,OverFlowAction

PSBlogWeek2015-7

From this we gather that the Minimum retention of this log should be seven days and that only events older than 7 days will be discarded. If the event log is at the maximum size and there are no events older than 7 days to be discarded the latest event will be discarded and will not be written to the script. For more information on this subject please refer to the following MSDN article:
OverflowAction

Member name                                                                                                             Description 
DoNotOverwrite Indicates that existing entries are retained when the event log is full and new entries are discarded.
OverwriteAsNeeded Indicates that each new entry overwrites the oldest entry when the event log is full.
OverwriteOlder Indicates that new events overwrite events older than specified by the MinimumRetentionDays property value when the event log is full. New events are discarded if the event log is full and there are no events older than specified by the MinimumRetentionDays property value.

Based on the information in the article, we decide to increase the maximum size of log to 20 MB and to allow overwriting as needed, this is also referred to as circular logging:

1
2
3
Limit-EventLog -Maximumsize 20MB -Logname Scripts -OverflowAction OverwriteAsNeeded
Get-EventLog -List | Where-Object {$_.LogDisplayName -eq 'Scripts'} |
Select-Object -Property Log,MaximumKilobytes,MinimumRetentionDays,OverFlowAction

PSBlogWeek2015-8

With the information provided in this article you will be able to:

  • How to write information to the event log
  • How to register an event source to an event log
  • How to create a new event log
  • How to configure an existing event log

I hope this was informative and do not forget to read through the other #PSBlogWeek posts:

Links in this Article
Twitter #PSBlogWeek
#PSBlogWeek Announcement on PowerShell.org
MSDN Article: OverflowAction
Adam Bertram Blog
June Blender Sapien Blog
Jason Wasser Blog
Thom Schumacher Blog
Adam Platt Blog
Matt Johnson Blog

Share

Quicktip: Use Windows Defender to scan a file or folder

As I was experimenting with the new PowerShell 5.0 cmdlets for Windows Defender I noticed that there is no parameter for starting a custom scan. As a workaround I used the mpcmdrun.exe tool to initiate the scan. For example the following code will execute a custom scan on C:\Temp:

1
& "$($env:programfiles)\Windows Defender\mpcmdrun.exe" -Scan -ScanType 3 -File 'C:\Temp'

MPCMDRun

This allows for scanning a custom folder, and the results will be displayed to the console. The results are also logged in the Windows Defender Operational log, if logging for Windows Defender has not been disabled. Using the Get-WinEvent cmdlet we can get this information from the eventlog.

1
2
Get-WinEvent -LogName 'Microsoft-Windows-Windows Defender/Operational' |
Select-Object -First 2 -ExpandProperty Message

MPCMDRun-EventLog

For more information on this topic have a look at the following resources:

Windows Defender
Security-Malware-Windows-Defender
Run (and Automate) Windows Defender from the Command Line
Share