Automating Export for Windows Events Logs with PowerShell

I like to say cybersecurity is like an onion. It has many layers. In technical terms, we might say there are many vectors to protect, monitor and analyze. One common area is monitoring for activity with your Windows domain controllers. In Windows, the Event Viewer is the most common starting point for any activity analysis. The three core logs (Application, System and Security) provide details on information, warnings, errors and critical events. You can also configure Windows to log relevant cybersecurity activities like permission elevations and file deletions. The common issue we see is that the logs do not hold enough history for most auditing requirements. While you can increase the log sizes in Windows, this is not recommended. It will increase disk and performance demands on your servers. Also, Event Viewer is not a robust search and analysis tool. The best approach is to export your events. In this article, I take a straightforward approach to get the event logs exported to CSV files. The CSV format is much easier to work with than the proprietary EVTX Windows format. This approach does not require purchasing any software and relies solely on PowerShell. Once you have your logs exported, you can keep them as long as required and use the logs with other tools for analysis and reporting.

Objective

Easily export the three main Event logs from Windows to CSV files.

  1. Application Log: Contains events logged by applications or programs, providing information about application errors, warnings, and informational events.

  2. System Log: Records events logged by Windows system components, including driver failures, system errors, and other critical system events.

  3. Security Log: Tracks security-related events such as login attempts, resource access, and changes to security settings, useful for auditing and monitoring security.

Overview of Steps

From the server or workstation, the first few steps must be done as local or domain Administrator.

  1. Add the account name that will be running the scripts to the local security group Event Log Readers. It is not recommended to use an Administrator or Domain Admin account.

NOTE: If you have to do this for several computers in a domain, a GPO could be used.

2. Using an Administrator PowerShell session, run the following commands:

$acl = Get-Acl HKLM:\SYSTEM\CurrentControlSet\Services\EventLog\Security 
$rule = New-Object System.Security.AccessControl.RegistryAccessRule ("BUILTIN\Event Log Readers", "ReadKey", "Allow") 
$acl.SetAccessRule($rule) 
Set-Acl HKLM:\SYSTEM\CurrentControlSet\Services\EventLog\Security $acl 
    

3. Confirm your PowerShell environment will allow running scripts. See Set-ExecutionPolicy (Microsoft.PowerShell.Security) - PowerShell | Microsoft Learn

Then, login with the user account for configuration the scheduled task to run the script.

  1. Create a local folder to hold the script and downloaded files. Set folder permissions as needed. Verify sufficient disk space is available.

  2. Create the script (see below for details).

  3. Create the scheduled task. The frequency for running will vary based on your environment, activity and Event Log size settings.

Advanced Tips:

  • Use PowerShell to empty the logs after downloading

  • Enhance the script to offload the exported scripts to another storage location for protection

  • Import the scripts to another program or dashboard for review and alerting

    Exporting Event Logs

    Method 1 - Keeping it Simple

    The Get-WinEvent PowerShell command is your tool for this task. If you just want to get the task done, here are your three lines of code:

# Export Application log errors, warnings, and critical events to CSV 
Get-WinEvent -LogName Application -FilterXPath "*[System[(Level=1 or Level=2 or Level=3)]]" | Export-Csv "application_logs.csv" -NoTypeInformation 

# Export System log errors, warnings, and critical events to CSV 
Get-WinEvent -LogName System -FilterXPath "*[System[(Level=1 or Level=2 or Level=3)]]" | Export-Csv "system_logs.csv" -NoTypeInformation 

# Export Security log audit successes and failures to CSV 
Get-WinEvent -LogName Security -FilterXPath "*[System[(Keywords='0x8020000000000000' or Keywords='0x8010000000000000')]]" | Export-Csv security_logs.csv" -NoTypeInformation 

Method 2 - Getting a Little Fancy

This version gives you a variable at the beginning to set your target export folder. It also creates a daily export log file tracking the export times.

        # Define the folder location for CSV files 

        $folderPath = "C:\EventLogs" 
        
         
        
        # Ensure the folder exists 
        
        if (-not (Test-Path -Path $folderPath)) { 
        
        / / New-Item -Path $folderPath -ItemType Directory 
        
        } 
        
         
        
        # Define the log file name with the current date 
        
        $logFileName = "ExpLog_$(Get-Date -Format 'yyyy-MM-dd').txt" 
        
        $logFilePath = Join-Path -Path $folderPath -ChildPath $logFileName 
        
         
        
        # Function to write to the execution log 
        
        function Write-Log { 
        
        / / param ( 
        
        / / / / [string]$message 
        
        / / ) 
        
        / / $timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss' 
        
        / / $logMessage = "$timestamp - $message" 
        
        / / Add-Content -Path $logFilePath -Value $logMessage 
        
        } 
        
         
        
        # Function to export logs and handle errors 
        
        function Export-Log { 
        
        / / param ( 
        
        / / / / [string]$logName, 
        
        / / / / [string]$filterXPath, 
        
        / / / / [string]$outputPath 
        
        / / ) 
        
        / / Write-Log "Starting export for $logName log" 
        
        / / $startTime = Get-Date 
        
        / / try { 
        
        / / / / $events = Get-WinEvent -LogName $logName -FilterXPath $filterXPath -ErrorAction Stop 
        
        / / / / if ($events.Count -eq 0) { 
        
        / / / / / / Write-Log "No events found for $logName log." 
        
        / / / / } else { 
        
        / / / / / / $events | Export-Csv -Path $outputPath -NoTypeInformation 
        
        / / / / / / Write-Log "Exported $logName log to $outputPath." 
        
        / / / / } 
        
        / / } catch { 
        
        / / / / Write-Log "No events found for $logName log." 
        
        / / } 
        
        / / $endTime = Get-Date 
        
        / / Write-Log "Completed export for $logName log. Start time: $startTime, End time: $endTime" 
        
        } 
        
         
        
        # Export Application log errors, warnings, and critical events to CSV 
        
        Export-Log -logName "Application" -filterXPath "*[System[(Level=1 or Level=2 or Level=3)]]" -outputPath "$folderPath\application_logs.csv" 
        
         
        
        # Export System log errors, warnings, and critical events to CSV 
        
        Export-Log -logName "System" -filterXPath "*[System[(Level=1 or Level=2 or Level=3)]]" -outputPath "$folderPath\system_logs.csv" 
        
         
        
        # Export Security log audit successes and failures to CSV 
        
        Export-Log -logName "Security" -filterXPath "*[System[(Keywords='0x8020000000000000' or Keywords='0x8010000000000000')]]" -outputPath "$folderPath\security_logs.csv" 
        
         
        
        # Export Setup log events to CSV 
        
        Export-Log -logName "Setup" -filterXPath "*[System[(Level=1 or Level=2 or Level=3)]]" -outputPath "$folderPath\setup_logs.csv" 
        
         
        
        # Export ForwardedEvents log events to CSV 
        
        Export-Log -logName "ForwardedEvents" -filterXPath "*[System[(Level=1 or Level=2 or Level=3)]]" -outputPath "$folderPath\forwarded_events_logs.csv"  

What’s Next?

Capturing of the event logs is just the beginning and minimum action required for auditing. Here are some ideas on how to make this even better:

  • Use Get-WinEvent to make sure all computers have a good minimum log size so events are not lost. You can query the log size in PowerShell using “(Get-WinEvent -ListLog Security).FileSize / 1MB” 

  • Enhance the script to write your own event into each log at the export execution. Then, read for that event to know where to begin exporting each time.

  • Enhance the script to also export the Setup and ForwardedEvents logs. The Setup log captures events related to the installation and configuration of software and system components. The ForwardedEvents log aggregates events forwarded from multiple sources.

  • Import your CSV files into PowerBI or another data analysis tool/program for intelligent review. It is important to establish baselines and identify suspicious events.

  • Consider using the exports files with a SIEM or other security monitoring tool.

I hope this article was helpful. Stay safe and keep improving your cybersecurity resilience!

Previous
Previous

Enhancing Cyber Incident Reporting with CISA's New Services Portal 

Next
Next

How’s Your Hygiene? Poor Password Hygiene Leaves Your Organization Vulnerable to Cybersecurity Attacks.