Hey, Scripting Guy! Question

Hey, Scripting Guy! How can I scan the event logs of my servers and return only information about unsuccessful logons?

-- LC

SpacerHey, Scripting Guy! AnswerScript Center

Hey, LC. We’ll assume that you have enabled security auditing on your servers. If you haven’t, that’s step one. What you’ll want to do is - at a minimum - audit for logon event failures. That way every time someone tries - and fails - to log on to the computer, an event with a specific event code will be written to the Security event log. For member servers and workstations, the event code is 529; for domain controllers, the event code is 675. For our example, we’ll use event code 529, simply because you referenced “servers” in your question rather than “domain controllers.”

Note. There might be other event codes of interest to you as well; needless to say, the Scripting Guys are not security experts. For the sake of simplicity, though, we’ll focus on 529 and 675, both of which represent “unknown user name or bad password” events. However, its’ easy enough to modify the WQL query we’ll be using to check for additional event codes.

Budding crime scene investigators out there might have already spotted an important clue: unsuccessful logons are reported in the Security event log, and each one is branded with the same event code: 529. That suggests a solution to our problem: to get back information about unsuccessful logons, all we need to do is query the Security event log for all events that have an event code of 529.

In other words:

strComputer = "."
Set objWMIService = GetObject("winmgmts:{(Security)}\\" & strComputer & "\root\cimv2")

Set colEvents = objWMIService.ExecQuery _
        ("Select * from Win32_NTLogEvent Where Logfile = 'Security' and " _
            & "EventCode = '529'")

For Each objEvent in colEvents
    Wscript.Echo "Category: " & objEvent.Category
    Wscript.Echo "Computer Name: " & objEvent.ComputerName
    Wscript.Echo "Event Code: " & objEvent.EventCode
    Wscript.Echo "Message: " & objEvent.Message
    Wscript.Echo "Record Number: " & objEvent.RecordNumber
    Wscript.Echo "Source Name: " & objEvent.SourceName
    Wscript.Echo "Time Written: " & objEvent.TimeWritten
    Wscript.Echo "Event Type: " & objEvent.Type
    Wscript.Echo "User: " & objEvent.User

Elementary, my dear Watson. The only thing out of the ordinary occurs when we connect to the WMI service. To do that, we must include the (Security) privilege (enclosed in square braces), like so:

Set objWMIService = GetObject("winmgmts:{(Security)}\\" & strComputer & "\root\cimv2")

You need to include this privilege in your script any time you want to access the Security event log. On top of that you (or at least your user account) must already possess the right to access the Security event log; including the privilege in the script won’t magically bestow this right on you. On the other hand, leaving the privilege out of the script will prevent you from accessing the Security event log, regardless of any rights, privileges, and permissions your user account might have.

After making the connection we simply select all instances of the Win32_NTLogEvent class where the Logfile is equal to Security and the EventCode is equal to 529. That returns a collection of unsuccessful logon events, which we proceed to echo back to the screen.

This particular script returns a list of all the unsuccessful logon events. It’s possible that you might want to retrieve those events only for a specified time period (for example, only unsuccessful logons from yesterday or for last week). Likewise, you might want to set up a monitoring system that would allow for instant notification any time such an event occurred. That sort of things lies a bit outside the scope of this column, but for more information and for sample scripts you might take a look at the Logs chapter in the Microsoft Windows 2000 Scripting Guide.