Windows & Linux · Windows Event Log Analysis Using PowerShell

Windows Event Log Analysis Using PowerShell

Platform: Windows Server 2022 (GUI or Core)

Focus: Security & System logs without Event Viewer

View this project on GitHub

Lab Objective

This lab demonstrates how to enumerate, query, filter, and export Windows Event Logs using PowerShell. A practice that can come in handy in scenarios where you're troubleshooting a server and GUI access is limited or unavailable, and you need to quickly evaluate something.

Lab Environment Setup

  • Windows Server 2022 (local VM)
  • Administrator PowerShell session
  • No dependency on Event Viewer GUI

Event Log Operations with PowerShell

This lab demonstration is being performed on a Windows Server 2022 Evaluation version installed on a Hyper-V VM instance, with remote access via RDP protocol, to work with some Windows event logs using the Get-WinEvent cmdlet between these two elevated PowerShell sessions.

Get-WinEvent is a PowerShell cmdlet that provides direct, scriptable access to Windows Event Logs, enabling administrators to perform efficient log analysis, troubleshooting, and incident response without relying on the Event Viewer GUI.

PowerShell sessions overview

1. Enumerating Available Windows Event Logs

Get-WinEvent -ListLog *

This command enumerates every Windows Event Log available on the system, returning high-level metadata about each log rather than individual events.

Providing a complete inventory of available Windows Event Logs, allowing administrators to identify where meaningful data exists before querying individual events.

Get-WinEvent -ListLog * output

2. Reviewing Recent System Activity

Get-WinEvent -LogName System -MaxEvents 50

This command retrieves the 50 most recent events from the System event log, displaying them directly in the PowerShell console.

Outputting the most recent system-level events, providing immediate visibility into service activity, updates, and core OS behavior.

Recent system events output

This output exposes system uptime and time adjustments, helping confirm system stability and maintain accurate timelines during troubleshooting and incident response.

System uptime and time adjustment events

3. Filtering System Events by Time Window (Native Engine)

Get-WinEvent -FilterHashtable @{
  LogName   = 'System'
  StartTime = (Get-Date).AddHours(-24)
}

This command retrieves only System log events that occurred within the last 24 hours, using PowerShell's native event filtering engine instead of post-processing results.

PowerShell's native event filtering engine allows administrators to query Windows Event Logs efficiently by filtering events at the source, reducing resource usage and enabling scalable, automation-friendly log analysis.

Time-filtered system events

Here it shows the Windows update service started downloading an update.

Windows update download event

4. Detecting Failed Authentication Attempts (Security Event ID 4625)

Get-WinEvent -FilterHashtable @{
  LogName = 'Security'
  Id      = 4625
}

This command identifies failed authentication attempts by querying Security Event ID 4625, a key indicator used for detecting unauthorized access and credential misuse.

Failed authentication events 4625

5. Monitoring Successful Logons (Security Event ID 4624)

Get-WinEvent -FilterHashtable @{
  LogName = 'Security'
  Id      = 4624
}

This command queries successful authentication events (Event ID 4624), providing visibility into who and what is actively logging on to the system.

Successful logon events 4624

6. Pipeline-Based Event Filtering (Post-Query Analysis)

Get-WinEvent -LogName Security | Where-Object { $_.Id -eq 4625 } | Select-Object TimeCreated, Id, Message

This command demonstrates pipeline-based filtering to isolate failed authentication events (Event ID 4625).

Pipeline-based event filtering output

7. Identifying High-Frequency System Events (Event ID Pattern Analysis)

Get-WinEvent -LogName System -MaxEvents 100 | Group-Object Id | Sort-Object Count -Descending | Select-Object -First 10

This command groups recent system events by Event ID and ranks them by frequency, helping identify dominant system behaviors and recurring activity patterns.

Event ID frequency analysis

8. Reconstructing System Startup and Shutdown History

Get-WinEvent -FilterHashtable @{
  LogName   = 'System'
  Id        = 6005,6006,6008
  StartTime = (Get-Date).AddDays(-14)
}

This command reconstructs system startup and shutdown activity by correlating Event IDs 6005, 6006, and 6008 over a defined time window.

Startup and shutdown history

9. Validating Service Stability via Crash Event Analysis

Get-WinEvent -FilterHashtable @{
  LogName   = 'System'
  Id        = 7031,7034
  StartTime = (Get-Date).AddDays(-3)
}

This command checks the System event log for recent service crashes (Event IDs 7031 and 7034) within the last three days. The absence of results indicates that no services terminated unexpectedly during this period, suggesting stable service operation.

Service crash event analysis

10. Comparing Failed vs Successful Authentication Activity

Get-WinEvent -FilterHashtable @{
  LogName   = 'Security'
  Id        = 4625
  StartTime = (Get-Date).AddHours(-1)
}
Get-WinEvent -FilterHashtable @{
  LogName   = 'Security'
  Id        = 4624
  StartTime = (Get-Date).AddHours(-1)
}

These commands compare failed and successful authentication events within the last hour. The absence of Event ID 4625 indicates no failed logon attempts during this period, while multiple Event ID 4624 entries confirm normal authentication activity.

This contrast helps validate system security and rule out brute-force or credential misuse attempts.

Failed vs successful authentication comparison

11. Tracking Privilege Assignment During Authentication

Get-WinEvent -FilterHashtable @{
  LogName   = 'Security'
  Id        = 4672
  StartTime = (Get-Date).AddHours(-1)
}

This command retrieves security events indicating when elevated privileges were assigned during a logon. Event ID 4672 is generated when an account logs in with administrative or special rights. Monitoring these events helps identify privileged access, validate administrative activity, and detect potential unauthorized elevation attempts.

Privilege assignment events 4672

12. Validating Service Stability (No Abnormal Terminations Detected)

Get-WinEvent -LogName System |
  Where-Object { $_.Id -in 7031,7034 } |
  Select-Object TimeCreated, Id, Message

This command searches the System event log for service crash and abnormal termination events (7031 and 7034). The absence of output indicates that no services have failed or exited unexpectedly, helping confirm system stability during routine health checks.

Service stability validation output

13. Reconstructing Recent Authentication Activity

Get-WinEvent -LogName Security | Where-Object { $_.TimeCreated -gt (Get-Date).Date.AddHours(-8) } | Select-Object TimeCreated, Id, Message

This command builds a chronological view of recent security activity by filtering Security event logs to the last eight hours. By displaying logon (4624), privilege assignment (4672), and logoff (4634) events together, it helps reconstruct user and system authentication activity and validate normal administrative behavior.

Recent authentication activity timeline

14. Using Negative Evidence to Validate Authentication Security

Get-WinEvent -FilterHashtable @{
  LogName   = 'Security'
  Id        = 4625
  StartTime = (Get-Date).AddDays(-1)
} | Export-Csv FailedLogons.csv -NoTypeInformation

This command attempts to export failed authentication events (Event ID 4625) from the Security log over the last 24 hours into a CSV file for reporting or investigation. In this case, no events were found, indicating no failed logon attempts occurred during the selected timeframe. This confirms a healthy authentication state and demonstrates how PowerShell can be used to generate audit-ready evidence—even when no issues are present.

Export failed logons to CSV output

Troubleshooting & Incident Scenarios

1. System Startup & Shutdown Timeline Reconstruction

Get-WinEvent -FilterHashtable @{
  LogName   = 'System'
  Id        = 6005,6006,6008
  StartTime = (Get-Date).AddDays(-7)
}

This command queries the System event log for startup, shutdown, and unexpected shutdown events over the past 7 days. By correlating Event IDs 6005, 6006, and 6008, administrators can quickly reconstruct system reboot timelines and distinguish between clean shutdowns and abnormal terminations.

System startup and shutdown timeline

2. Investigating Recent System Activity During Live Troubleshooting

Get-WinEvent -LogName System |
Where-Object {
  $_.TimeCreated -lt (Get-Date) -and
  $_.TimeCreated -gt (Get-Date).AddMinutes(-15)
}

This command filters the System event log to display only events generated within the last 15 minutes. By focusing on a narrow time window, administrators can quickly identify recent service state changes and system activity during live troubleshooting or incident investigation.

Recent 15-minute system activity

3. Ruling Out Service-Level Crashes as a Root Cause

Get-WinEvent -FilterHashtable @{
  LogName   = 'System'
  Id        = 7031,7034
  StartTime = (Get-Date).AddDays(-3)
}

This command queries the System event log for service crash and abnormal termination events (7031 and 7034) over the past three days. The absence of results confirms that no services failed unexpectedly during this period, indicating system stability and ruling out service-level crashes as a root cause.

Service crash root cause ruling out

4. Reviewing Authentication Activity Outside Normal Business Hours

Get-WinEvent -LogName Security |
Where-Object {
  $_.TimeCreated.Hour -lt 6 -or
  $_.TimeCreated.Hour -gt 20
}

This query filters the Windows Security event log to identify authentication and privilege-related activity occurring outside of normal business hours. By focusing on late-night and early-morning events, this approach highlights off-hours logons and privileged sessions that may warrant closer review during incident investigations or audit scenarios.

After-hours authentication activity

5. Reviewing Scheduled Task Activity Over the Last 24 Hours

Get-WinEvent -FilterHashtable @{
  LogName   = 'Microsoft-Windows-TaskScheduler/Operational'
  StartTime = (Get-Date).AddDays(-1)
}

This query examines the Task Scheduler Operational log to identify scheduled task activity over the last 24 hours. It provides visibility into task execution, completion, failures, and updates, including the processes launched and the security context under which they ran. Task Scheduler is a common mechanism for both legitimate automation and malicious persistence, making this log a valuable source for behavioral analysis and incident investigations.

Scheduled task execution log

6. Detecting System Instability Through Error and Critical Events

Get-WinEvent -LogName System |
Where-Object { $_.LevelDisplayName -in 'Error','Critical' } |
Select TimeCreated, Id, Message

This query filters the System event log to surface only Error and Critical events, providing a focused view of serious operating system issues. It highlights unexpected shutdowns, reboot anomalies, service failures, time synchronization events, and firmware-related security messages. This type of analysis is useful for diagnosing system instability, identifying power or hardware issues, and validating system health during incident response or troubleshooting.

Error and critical system events

7. Detecting Noisy and Recurring System Events

Get-WinEvent -LogName System |
Group-Object Id |
Sort Count -Descending |
Select -First 10

This command summarizes the System event log by grouping events based on Event ID and ranking them by frequency. It provides a high-level view of the most common system activities, allowing administrators to identify normal operational patterns, noisy events, and frequently occurring service state changes. This technique is useful for establishing a system baseline and prioritizing which event types deserve closer investigation.

Recurring event pattern recognition

8. Validating Administrative Logon Activity

Get-WinEvent -FilterHashtable @{
  LogName   = 'Security'
  Id        = 4672
  StartTime = (Get-Date).AddDays(-1)
}

This query retrieves Security log events where special privileges were assigned during logon. Event ID 4672 indicates that a user or process received elevated rights such as administrative or system-level privileges. Monitoring this event is critical for detecting privileged access, validating administrative activity, and identifying potential privilege escalation during security investigations.

Administrative logon activity audit

9. Collecting System Error Events for Troubleshooting

Get-WinEvent -LogName System |
Where-Object { $_.LevelDisplayName -eq 'Error' } |
Export-Csv SystemErrors.csv -NoTypeInformation

This command filters the System event log to extract only Error-level events and exports the results to a CSV file. This approach allows administrators to create a structured report of system failures for documentation, troubleshooting, and trend analysis. Exporting logs in this format supports incident response workflows and enables easy sharing with stakeholders.

System error events exported to CSV
← Back to Home