powershellaudit-logging

Using powershell to get the "Audit Policy" security setting value


I am trying to use Powershell (auditpol) to query the security setting values of the Audit Policy items. So far with all the auditpol commands, I only able to get the subcategories value instead.

auditpol /get /category:*

So far I could only get the list of the 9 items without the success/failure/no auditing values using:

auditpol /list/category

Could there be a command/flag that I might have left out for auditpol or is there any other command for me to retrieve the policies and its relevant security setting values?

Policy and values that I would like to query.


Solution

  • As you've found, auditpol only manages the settings that are in effect when the "Advanced Audit Policy Configuration" feature is enabled.

    To query the "classic" audit policy, you will need to use the LSA Policy Win32 API to:

    1. Open the local security policy using LsaOpenPolicy()
    2. Query the audit settings using LsaQueryPolicyInformation()
    3. Translate the results to something readable.

    The following example uses Add-Type to compile a C# type that in turn does all of the above:

    $AuditPolicyReader = Add-Type -TypeDefinition @'
    using System;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Linq;
    using System.Collections.Generic;
    
    public class AuditPolicyReader
    {
        [Flags()]
        public enum AuditPolicySetting
        {
            Unknown =  -1,
            None    = 0x0,
            Success = 0x1,
            Failure = 0x2
        }
    
        [StructLayout(LayoutKind.Sequential)]
        private struct LSA_UNICODE_STRING
        {
            public UInt16 Length;
            public UInt16 MaximumLength;
            public IntPtr Buffer;
        }
    
        [StructLayout(LayoutKind.Sequential)]
        private struct LSA_OBJECT_ATTRIBUTES
        {
            public int Length;
            public IntPtr RootDirectory;
            public LSA_UNICODE_STRING ObjectName;
            public UInt32 Attributes;
            public IntPtr SecurityDescriptor;
            public IntPtr SecurityQualityOfService;
        }
    
        public struct POLICY_AUDIT_EVENTS_INFO
        {
            public bool AuditingMode;
            public IntPtr EventAuditingOptions;
            public Int32 MaximumAuditEventCount;
        }
    
        [DllImport("advapi32.dll")]
        static extern uint LsaQueryInformationPolicy(IntPtr PolicyHandle, uint InformationClass, out IntPtr Buffer);
    
        [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)]
        static extern uint LsaOpenPolicy(ref LSA_UNICODE_STRING SystemName, ref LSA_OBJECT_ATTRIBUTES ObjectAttributes, uint DesiredAccess, out IntPtr PolicyHandle);
    
        [DllImport("advapi32.dll", SetLastError = true)]
        static extern uint LsaClose(IntPtr ObjectHandle);
    
        public static Dictionary<string, AuditPolicySetting> GetClassicAuditPolicy()
        {
            // Create dictionary to hold the audit policy settings (the key order here is important!!!)
            var settings = new Dictionary<string, AuditPolicySetting>
            {
                {"System", AuditPolicySetting.Unknown},
                {"Logon", AuditPolicySetting.Unknown},
                {"Object Access", AuditPolicySetting.Unknown},
                {"Privilige Use", AuditPolicySetting.Unknown},
                {"Detailed Tracking", AuditPolicySetting.Unknown},
                {"Policy Change", AuditPolicySetting.Unknown},
                {"Account Management", AuditPolicySetting.Unknown},
                {"Directory Service Access", AuditPolicySetting.Unknown},
                {"Account Logon", AuditPolicySetting.Unknown},
            };
    
            // Open local machine security policy
            IntPtr polHandle;
            LSA_OBJECT_ATTRIBUTES aObjectAttributes = new LSA_OBJECT_ATTRIBUTES();
            aObjectAttributes.Length = 0;
            aObjectAttributes.RootDirectory = IntPtr.Zero;
            aObjectAttributes.Attributes = 0;
            aObjectAttributes.SecurityDescriptor = IntPtr.Zero;
            aObjectAttributes.SecurityQualityOfService = IntPtr.Zero;
    
            var systemName = new LSA_UNICODE_STRING();
            uint desiredAccess = 2; // we only need the audit policy, no need to request anything else
            var res = LsaOpenPolicy(ref systemName, ref aObjectAttributes, desiredAccess, out polHandle);
            if (res != 0)
            {
                if(res == 0xC0000022)
                {
                    // Access denied, needs to run as admin
                    throw new UnauthorizedAccessException("Failed to open LSA policy because of insufficient access rights");
                }
                throw new Exception(string.Format("Failed to open LSA policy with return code '0x{0:X8}'", res));
            }
            try
            {
                // now that we have a valid policy handle, we can query the settings of the audit policy
                IntPtr outBuffer;
                uint policyType = 2; // this will return information about the audit settings
                res = LsaQueryInformationPolicy(polHandle, policyType, out outBuffer);
                if (res != 0)
                {
                    throw new Exception(string.Format("Failed to query LSA policy information with '0x{0:X8}'", res));
                }
    
                // copy the raw values returned by LsaQueryPolicyInformation() to a local array;
                var auditEventsInfo = Marshal.PtrToStructure<POLICY_AUDIT_EVENTS_INFO>(outBuffer);
                var values = new int[auditEventsInfo.MaximumAuditEventCount];                
                Marshal.Copy(auditEventsInfo.EventAuditingOptions, values, 0, auditEventsInfo.MaximumAuditEventCount);
    
                // now we just need to translate the provided values into our settings dictionary
                var categoryIndex = settings.Keys.ToArray();
                for (int i = 0; i < values.Length; i++)
                {
                    settings[categoryIndex[i]] = (AuditPolicySetting)values[i];
                }
    
                return settings;
            }
            finally
            {
                // remember to release policy handle
                LsaClose(polHandle);
            }
        }
    }
    '@ -PassThru |Where-Object Name -eq AuditPolicyReader
    

    Now we can call GetClassicAuditPolicy() (remember to run this from an elevated prompt):

    PS ~> $AuditPolicyReader::GetClassicAuditPolicy()
    Key                                 Value
    ---                                 -----
    System                               None
    Logon                    Success, Failure
    Object Access                        None
    Privilige Use                        None
    Detailed Tracking                    None
    Policy Change                     Success
    Account Management       Success, Failure
    Directory Service Access             None
    Account Logon                        None