• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1124
  • Last Modified:

C# wmi security logs

Hi, I am using c# WMI to iterate through the application, security and system eventlogs.  This all works fine apart from I cannot enumerate the Security log (I am a local admin on the computer) I use the win32_nteventlog.  How do I get all the events inside the security log?  Thanks.
0
AlistairDyer
Asked:
AlistairDyer
  • 3
  • 2
1 Solution
 
grayeCommented:
Reading from the Event Logs requries a privilege that is not enabled by default (even for administrators).   You'll have to write a small routine to enable the SeSecurityPrivilege on the current thread.

Here is an example that does precisely that.  (Sorry, it's written in VB.Net, but I'd bet it'd be trivial to convert)

Imports System.Runtime.InteropServices
Public Class SetSeSecurityPrivilege

    <StructLayout(LayoutKind.Sequential, Pack:=4)> _
    Private Structure LUID_AND_ATTRIBUTES
        Dim Luid As Long
        Dim Attributes As Integer
    End Structure

    <StructLayout(LayoutKind.Sequential, Pack:=4)> _
    Private Structure TOKEN_PRIVILEGES
        Dim PrivilegeCount As Integer
        Dim Privilege1 As LUID_AND_ATTRIBUTES
    End Structure

    'BOOL OpenProcessToken(
    '  HANDLE ProcessHandle,
    '  DWORD DesiredAccess,
    '  PHANDLE TokenHandle
    ');
    Private Declare Function OpenProcessToken Lib "advapi32.dll" ( _
        ByVal ProcessHandle As IntPtr, _
        ByVal DesiredAccess As Integer, _
        ByRef TokenHandle As IntPtr _
    ) As Boolean

    'BOOL LookupPrivilegeValue(
    '  LPCTSTR lpSystemName,
    '  LPCTSTR lpName,
    '  PLUID lpLuid
    ');

    Private Declare Auto Function LookupPrivilegeValue Lib "advapi32.dll" ( _
        ByVal lpSystemName As String, _
        ByVal lpName As String, _
        ByRef lpLuid As Long _
    ) As Boolean

    'BOOL AdjustTokenPrivileges(
    '  HANDLE TokenHandle,
    '  BOOL DisableAllPrivileges,
    '  PTOKEN_PRIVILEGES NewState,
    '  DWORD BufferLength,
    '  PTOKEN_PRIVILEGES PreviousState,
    '  PDWORD ReturnLength
    ');
    Private Declare Function AdjustTokenPrivileges Lib "advapi32.dll" ( _
        ByVal TokenHandle As IntPtr, _
        ByVal DisableAllPrivileges As Boolean, _
        ByRef NewState As TOKEN_PRIVILEGES, _
        ByVal BufferLength As Integer, _
        ByVal PreviousState As IntPtr, _
        ByVal ReturnLength As IntPtr _
    ) As Boolean

    Private Const TOKEN_QUERY As Integer = &H8
    Private Const TOKEN_ADJUST_PRIVILEGES As Integer = &H20
    Private Const SE_SECURITY_NAME As String = "SeSecurityPrivilege"
    Private Const SE_PRIVILEGE_ENABLED As Integer = &H2
    '
    ' Set the privileges for reading the Security Logs
    '
    Public Function SetPrivileges() As Boolean
        Dim hProc, hToken As IntPtr
        Dim luid_Security As Long
        Dim tp As New TOKEN_PRIVILEGES

        ' Get the current process's token
        hProc = Process.GetCurrentProcess().Handle
        hToken = IntPtr.Zero
        If Not OpenProcessToken(hProc, TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY, hToken) Then
            Return False
        End If

        ' Get the LUIDs for the Security privilege
        luid_Security = 0
        If Not LookupPrivilegeValue(Nothing, SE_SECURITY_NAME, luid_Security) Then
            Return False
        End If

        tp.PrivilegeCount = 1
        tp.Privilege1.Luid = luid_Security
        tp.Privilege1.Attributes = SE_PRIVILEGE_ENABLED

        ' Enable the privileges
        If Not AdjustTokenPrivileges(hToken, False, tp, 0, IntPtr.Zero, IntPtr.Zero) Then
            Return False
        End If

        Return True
    End Function
End Class
0
 
AlistairDyerAuthor Commented:
So there is no way to query the security log through WMI?  You have to use a token? I have managed to get the security log from WMI using VB6.0 without an issue...  there must be an easier way of getting the log than this?
0
 
grayeCommented:
Huh?  Sure, there's a way to read the security log through WMI with a managed application!

All you have to do is adjust a security token before you connect via WMI.  After you've performed that little feat of magic, your existing code to read the event logs will now work for the Security log file.  There's nothing else to do.

Did you need help translating the example to C#?
0
 
AlistairDyerAuthor Commented:
Yes please :)
0
 
grayeCommented:
Okey dokey....

Here is the class in C#.   You'd use it like this:

            SetSeSecurityPrivilege setPriv = new SetSeSecurityPrivilege();
            setPriv.SetPrivileges();

            // perform the connection to WMI here...

-------------------------------------------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;

public class SetSeSecurityPrivilege
{
    [StructLayout(LayoutKind.Sequential, Pack = 4)]
    private struct LUID_AND_ATTRIBUTES
    {
        public long Luid;
        public int Attributes;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 4)]
    private struct TOKEN_PRIVILEGES
    {
        public int PrivilegeCount;
        public LUID_AND_ATTRIBUTES Privilege1;
    }

    [System.Runtime.InteropServices.DllImport("advapi32.dll")]
    private static extern bool OpenProcessToken(IntPtr ProcessHandle, int DesiredAccess, ref IntPtr TokenHandle);
   
    [System.Runtime.InteropServices.DllImport("advapi32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    private static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, ref long lpLuid);
   
    [System.Runtime.InteropServices.DllImport("advapi32.dll")]
    private static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, bool DisableAllPrivileges, ref TOKEN_PRIVILEGES NewState, int BufferLength, IntPtr PreviousState, IntPtr ReturnLength);
   
    private const int TOKEN_QUERY = 8;
    private const int TOKEN_ADJUST_PRIVILEGES = 32;
    private const string SE_SECURITY_NAME = "SeSecurityPrivilege";
    private const int SE_PRIVILEGE_ENABLED = 2;

    public bool SetPrivileges()
    {
        IntPtr hProc;
        IntPtr hToken;
        long luid_Security;    
        TOKEN_PRIVILEGES tp = new TOKEN_PRIVILEGES();

        // get the process token
        hProc = Process.GetCurrentProcess().Handle;
        hToken = IntPtr.Zero;
        if (!(OpenProcessToken(hProc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref hToken)))
        {
            return false;
        }
       
        // lookup the ID for the privilege we want to enable
        luid_Security = 0;
        if (!(LookupPrivilegeValue(null, SE_SECURITY_NAME, ref luid_Security)))
        {
            return false;
        }
       
        tp.PrivilegeCount = 1;
        tp.Privilege1.Luid = luid_Security;
        tp.Privilege1.Attributes = SE_PRIVILEGE_ENABLED;
       
        // enable the privilege
        if (!(AdjustTokenPrivileges(hToken, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero)))
        {
            return false;
        }
        return true;
    }
}
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

  • 3
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now