Click here to Skip to main content
15,881,588 members
Articles / All Topics

WMI, Windows Event Logs and User Privileges

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
28 Sep 2009CPOL4 min read 32.8K   1  
  Some WMI operations require that SWbemServices object explicitly gets assigned appropriate privileges.

Some WMI operations require that SWbemServices object explicitly gets assigned appropriate privileges. The list of available privileges can be found here, and they can be assigned in two ways:

  • Using the WMI moniker
  • Using SWbemPrivilege and SWbemPrivilegeSet objects from WMI scripting API

Normally you don’t need to assign any privileges for a WMI script to work properly. Take, for example this one:

' VBScript source code
Set objSWbemServices = GetObject("winmgmts:")

Set colEvents = objSWbemServices.ExecQuery _
    ("Select * From Win32_NTLogEvent " _
    & "Where LogFile = 'Application'")
          


For Each objEvent In colEvents
    WScript.Echo objEvent.Message
Next

The script connects to the local WMI service using the most basic moniker and outputs all event messages from the Application event log. No privileges are assigned in the script, but are any assigned implicitly? Here is the script to test that:

' VBScript source code

Set objSWbemServices = GetObject ("winmgmts:")

Set objSWbemPrivileges = _
       objSWbemServices.Security_.Privileges
 
WScript.Echo "WMI privilege count: " _
    & objSWbemPrivileges.Count

The output is:

WMI privilege count: 0

So there are no implicitly assigned privileges either. This is all right for the Application event log, but if you try to enumerate event from the Security event log:

' VBScript source code

Set objSWbemServices = GetObject("winmgmts:")

Set colEvents = objSWbemServices.ExecQuery _
    ("Select * From Win32_NTLogEvent " _
    & "Where LogFile = 'Security'")

WScript.Echo colEvents.Count

For Each objEvent In colEvents
    WScript.Echo objEvent.Message
Next

no events are enumerated and SWbemObjectSet.Count is 0 even if you Security event log is full of entries. To make this script work properly you need to assign the wbemPrivilegeSecurity (7) to SWbemServices – here’s how to do it using the WMI moniker:

' VBScript source code
Set objSWbemServices = GetObject("winmgmts:{(Security)}")

Set colEvents = objSWbemServices.ExecQuery _
    ("Select * From Win32_NTLogEvent " _
    & "Where LogFile = 'Security'")
    
WScript.Echo colEvents.Count
  
For Each objEvent In colEvents
    WScript.Echo objEvent.Message
Next

When added using the moniker, the privilege name is actually ‘Security’, not wbemPrivilegeSecurity. You can find other privilege names suitable for use with the moniker here (under ‘Scripting short name’).

How could you tell that getting the Security event log entries requires special privilege? It is documented here so it a good idea to read WMI class documentation when writing WMI scripts.

Interestingly enough, if you don’t assign the privilege, the script will not work, but there won’t be any errors – SWbemServices.ExecQuery will just return an empty collection.

Here is another sample script that will not work without proper privileges:

' VBScript source code

Set objSWbemServices = GetObject("winmgmts:")

Set colProcesses = objSWbemServices.ExecQuery _
    ("Select * From Win32_Process " _
    & "Where Name = 'sqlservr.exe'")
          
For Each objProcess In colProcesses
    WScript.Echo objProcess.Terminate
Next

SQL Server runs under SYSTEM account, so Win32_Process.Terminate() will return the error code 2 – ‘Access Denied’ because you are not connected to WMI as SYSTEM account (this is documented here). In this case you need to use wbemPrivilegeDebug (19). Here is the script that works:

' VBScript source code

Set objSWbemServices = GetObject("winmgmts:{(Debug)}")

Set colProcesses = objSWbemServices.ExecQuery _
    ("Select * From Win32_Process " _
    & "Where Name = 'sqlservr.exe'")
          
For Each objProcess In colProcesses
    WScript.Echo objProcess.Terminate
Next

Backing up event log files is another operation that needs special privilege – wbemPrivilegeBackup (16):

' VBScript source code

Set objSWbemServices = GetObject("winmgmts:")

Set colEventLogFiles = objSWbemServices.ExecQuery _
    ("Select * From Win32_NTEventLogFile " _
    & "Where LogFileName = 'Application'")

For Each objEventLogFile In colEventLogFiles
    WScript.Echo objEventLogFile.BackupEventLog _
        ("C:\\scripts\\Application.evt")
Next

If you run this script you will get the following error:

SWbemObjectEx: Access denied

When you use wbemPrivilegeBackup the script works:

' VBScript source code

Set objSWbemServices = GetObject("winmgmts:{(backup)}")

Set colEventLogFiles = objSWbemServices.ExecQuery _
    ("Select * From Win32_NTEventLogFile " _
    & "Where LogFileName = 'Application'")
          
For Each objEventLogFile In colEventLogFiles
    WScript.Echo objEventLogFile.BackupEventLog _
("C:\\scripts\\Application.evt")
Next

What is interesting to note here is that WMI is not consistent in reporting missing privileges: in the first case there was no error at all, in the second example Win32_Process.Terminate returned the error code that signaled the missing privilege and continued, and in the third script Win32_NTEventLogFile.BackupEventLog caused the script to crash – this is not very helpful when debugging WMI scripts.

Here is some more information that just adds to the confusion: to back up the Security log file you need both Security and Backup privileges. If you use just the Security privilege:

' VBScript source code

Set objSWbemServices = GetObject("winmgmts:{(Security)}")

Set colEventLogFiles = objSWbemServices.ExecQuery _
    ("Select * From Win32_NTEventLogFile " _
    & "Where LogFileName = 'Security'")
          
For Each objEventLogFile In colEventLogFiles
    WScript.Echo objEventLogFile.BackupEventLog _
("C:\\scripts\\Security.evt")
Next

you will get the ‘Access denied’ error, but if you use just the Backup privilege:

' VBScript source code

Set objSWbemServices = GetObject("winmgmts:{(Backup)}")

Set colEventLogFiles = objSWbemServices.ExecQuery _
    ("Select * From Win32_NTEventLogFile " _
    & "Where LogFileName = 'Security'")

For Each objEventLogFile In colEventLogFiles
    WScript.Echo objEventLogFile.BackupEventLog _
("C:\\scripts\\Security.evt")
Next

Win32_NTEventLogFile.BackupeventLog will return 5, an error code not listed in the documentation. To make it work, use both privileges:

' VBScript source code

Set objSWbemServices = GetObject _
    ("winmgmts:{(Security, Backup)}")
 
Set colEventLogFiles = objSWbemServices.ExecQuery _
    ("Select * From Win32_NTEventLogFile " _
    & "Where LogFileName = 'Security'")

For Each objEventLogFile In colEventLogFiles
WScript.Echo objEventLogFile.BackupEventLog _
        ("C:\\scripts\\Security.evt")
Next

Other way to assign privileges to WMI is by using SWbemPrivilege and SWbemPrivilegeSet objects:

' VBScript source code

Set objSWbemServices = GetObject ("winmgmts:")

objSWbemServices.Security_.Privileges.AddAsString _
    "SeSecurityPrivilege"
 
objSWbemServices.Security_.Privileges.AddAsString _
    "SeBackupPrivilege"

Set colEventLogFiles = objSWbemServices.ExecQuery _
    ("Select * From Win32_NTEventLogFile " _
    & "Where LogFileName = 'Security'")
          
For Each objEventLogFile In colEventLogFiles
    WScript.Echo objEventLogFile.BackupEventLog _
        ("C:\\scripts\\Security.evt")
Next

SWbemService has a property called Security_ which is actually SWbemSecurity object, which in turn has Privileges property. This is a SWbemPrivilegeSet object and you can use its AddAsString and Add methods to assign privileges to WMI. When using AddAsString, use the privilege name as defined here (the all start with Se***, like SeDebugPrivilege) and when using the Add method, use the the integer that represent the specific privilege (for example, for SeDebugPrivilege you would use 19).

You can use SWbemPrivilege object to list all available privileges. The above link lists 27 available privileges, and you can use a For loop to add them all:

' VBScript source code

Set objSWbemServices = GetObject ("winmgmts:")

Set colPrivileges = objSWbemServices.Security_.Privileges

For i = 1 To 27
    colPrivileges.Add i
Next

For Each objPrivilege In colPrivileges
    WScript.Echo objPrivilege.Identifier & vbTab _
    & objPrivilege.Name & vbTab _
    & objPrivilege.DisplayName
Next

and use For..Each to list information about each privilege.

.Net Framework System.Management namespace simplifies all this: there is one-size-fit-all ConnectionOptions.EnablePrivileges property which, when set to true, enables all possible privileges. Here is a C# sample:

using System;
using System.Management;
class Program
{
    static void Main()
    {
        ManagementScope scope =
            new ManagementScope();
        scope.Options.EnablePrivileges = true;
        ObjectQuery query = new ObjectQuery(
            @"Select * From Win32_NtLogEvent " +
            @"Where LogFile = 'Security'");
        ManagementObjectSearcher searcher =
            new ManagementObjectSearcher(scope, query);

        foreach (ManagementObject logEvent in searcher.Get())
        {
            Console.WriteLine(logEvent["Message"]);
        }
    }
}

Same thing for PowerShell: there is a switch called –EnableAllPrivileges for V2 that also enables all privileges (all on one line):

Get-WmiObject Win32_NTLogEvent -filter "LogFile='Security'" -EnableAllPrivileges

If this is not available, with a bit of work it is possible to use System.Management.ConnectionOptions, just like in C#:

$Searcher = New-Object System.Management.ManagementObjectSearcher
$Searcher.Scope.Options.EnablePrivileges = $true
$Searcher.Query = "Select * From Win32_NTLogEvent Where LogFile = 'Security'"

foreach($Event in $Searcher.Get())
{
    $Event.EventCode
    $Event.TimeGenerated
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Systems / Hardware Administrator
Bosnia and Herzegovina Bosnia and Herzegovina
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --