Implementing Passive Windows Event Log Monitoring with Real-time Alerting


3 views

Traditional Windows Event Log monitoring solutions often require active polling or manual inspection, creating unnecessary overhead. What developers truly need is a lightweight, event-driven approach that triggers notifications only when specific events occur.

The most efficient passive monitoring solution leverages Windows Event Forwarding (WEF):

# Configure source computer (Forwarding)
wecutil qc /quiet
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\EventLog\EventForwarding\SubscriptionManager" -Name "1" -Value "Server=http://your-server:5985/wsman/SubscriptionManager/WEC"

Create a subscription that filters for specific events:

<QueryList>
  <Query Id="0" Path="Security">
    <Select Path="Security">
      *[System[(EventID=4624 or EventID=4625)]] 
    </Select>
  </Query>
</QueryList>

For local monitoring without WEF setup:

$query = @"
<QueryList>
  <Query Id="0" Path="Application">
    <Select Path="Application">
      *[System[(Level=2)]] 
    </Select>
  </Query>
</QueryList>
"@

$watcher = New-Object System.Diagnostics.Eventing.Reader.EventLogWatcher($query)
Register-ObjectEvent -InputObject $watcher -EventName "EventRecordWritten" -Action {
    param($sender, $eventArgs)
    $event = $eventArgs.EventRecord
    Send-MailMessage -To "admin@domain.com" -Subject "Critical Event $($event.Id)" -Body $event.Message
}

For high-volume scenarios, consider Event Tracing for Windows (ETW):

logman create trace "MyEventMonitor" -ow -o "C:\logs\events.etl" -p "Microsoft-Windows-Security-Auditing" 0x8000000000000000 -nb 16 16 -bs 1024 -ets

For modern environments, consider Azure Monitor or AWS CloudWatch Logs Agent:

# Azure Monitor agent configuration
{
  "EventLogs": {
    "WindowsEventLogs": [
      {
        "Name": "Security",
        "Levels": "1,2,3"
      }
    ]
  }
}

Most Windows Event Log monitoring solutions require either:

  • Manual log inspection (inefficient for enterprise environments)
  • Scheduled polling (resource-intensive and introduces latency)
  • Complex SIEM setups (overkill for simple alerting needs)

Windows actually provides built-in mechanisms for passive monitoring:

1. Event Viewer Subscriptions

Basic setup using Windows Event Collector (WEC):

# PowerShell command to create subscription
$FilterXML = @'
<QueryList>
  <Query Id="0" Path="Security">
    <Select Path="Security">*[System[(EventID=4624)]]</Select>
  </Query>
</QueryList>
'@

New-WinEventSubscription -SubscriptionName "FailedLogonAlert" -SubscriptionType SourceInitiated -Query $FilterXML -Credential $Cred

2. Windows Event Forwarding with Custom Actions

Configure forwarding and add notification actions:

# Registry modification for custom action
reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\EventCollector\Subscriptions\{SubscriptionID}" /v "CustomAction" /t REG_SZ /d "C:\Scripts\SendAlert.bat" /f

For more control, create a C# service using System.Diagnostics.Eventing:

using System;
using System.Diagnostics.Eventing.Reader;

class EventMonitor
{
    static void Main()
    {
        var query = new EventLogQuery("Security", PathType.LogName);
        var watcher = new EventLogWatcher(query);
        
        watcher.EventRecordWritten += (sender, e) => 
        {
            if (e.EventRecord.Id == 4625) // Failed logon
            {
                SendAlert($"Failed logon attempt: {e.EventRecord.Properties[5].Value}");
            }
        };
        
        watcher.Enabled = true;
        Console.WriteLine("Monitoring started...");
        Console.ReadLine();
    }
    
    static void SendAlert(string message)
    {
        // Implement your notification logic here
        Console.WriteLine($"[ALERT] {DateTime.Now}: {message}");
    }
}

A lightweight approach combining PowerShell and Windows Task Scheduler:

# Create an event filter and action
$trigger = New-ScheduledTaskTrigger -AtLogOn
$action = New-ScheduledTaskAction -Execute "Powershell.exe" -Argument @"
-Command "& {
    $query = '*[System[(EventID=4625)]]'
    Register-ObjectEvent -InputObject (New-Object System.Diagnostics.Eventing.Reader.EventLogQuery('Security', [System.Diagnostics.Eventing.Reader.PathType]::LogName, $query)) 
                         -EventName EventRecordWritten 
                         -SourceIdentifier 'SecurityAlert' 
                         -Action {
                             Send-MailMessage -To 'admin@domain.com' 
                                             -Subject 'Failed Logon Attempt' 
                                             -Body $EventArgs.EventRecord.ToXml()
                         }
}"
"@

Register-ScheduledTask -TaskName "SecurityEventMonitor" -Trigger $trigger -Action $action -RunLevel Highest

For environments where custom coding isn't practical:

  • NXLog Community Edition - Lightweight log forwarder with alerting
  • Winlogbeat - Ships events to Elasticsearch/Logstash
  • EventSentry Light - Free version with basic alerting

The effectiveness depends on your alert delivery method:

Method Latency Reliability
Email Moderate Depends on mail server
SMS Gateway Low High (paid services)
Webhook Very Low Depends on endpoint
Windows Toast Low Only for logged-in users

When implementing passive monitoring:

  • Use dedicated monitoring accounts with least privilege
  • Secure notification channels (HTTPS for webhooks, SMTPS for email)
  • Rotate credentials/certificates regularly
  • Consider encrypting sensitive event data in transit