'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?
Solution 1:[1]
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:
- Open the local security policy using
LsaOpenPolicy()
- Query the audit settings using
LsaQueryPolicyInformation()
- 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
Solution 2:[2]
auditpol
only returns the Advanced audit policy configuration. These settings can be found in the UI under Security Settings > Advanced Audit Policy Configuration > System Audit Policies
The legacy audit policy your screenshot shows were mostly done away with after Windows Server 2003/Windows Vista. Note the warnings in the policy properties or on the MS compatibility page:
For advanced policies, you can use /r
to get a csv-formatted table:
auditpol /get /category:'Account Logon' /r | ConvertFrom-Csv |
Format-Table 'Policy Target',Subcategory,'Inclusion Setting'
Policy Target Subcategory Inclusion Setting
------------- ----------- -----------------
System Kerberos Service Ticket Operations No Auditing
System Other Account Logon Events No Auditing
System Kerberos Authentication Service No Auditing
System Credential Validation No Auditing
For legacy audit policies:
secedit.exe /export /areas SECURITYPOLICY /cfg filename.txt
[Event Audit]
AuditSystemEvents = 0
AuditLogonEvents = 0
AuditObjectAccess = 0
AuditPrivilegeUse = 0
AuditPolicyChange = 0
AuditAccountManage = 0
AuditProcessTracking = 0
AuditDSAccess = 0
AuditAccountLogon = 0
Requires that it hasn't been disabled. Check in the registry:
Get-ItemProperty HKLM:\System\CurrentControlSet\Control\Lsa -Name SCENoApplyLegacyAuditPolicy
Solution 3:[3]
Here is a code that gives you a list of all categories and subcategories with their current audit-status. I made it a bit longer than really needed to add the local names of each object. Also see some usage-samples at the end of the code.
# getting the audit policy settings for each subcategory
# works for any OS language
cls
Remove-Variable * -ea 0
$ErrorActionPreference = 'stop'
#requires -runasadmin
$dll = [string]::Join("`r`n", '[DllImport("advapi32.dll")]', 'public static extern bool')
$auditpol = Add-Type -Name 'AuditPol' -Namespace 'Win32' -PassThru -MemberDefinition "
$dll AuditEnumerateCategories(out IntPtr catList, out uint count);
$dll AuditLookupCategoryName(Guid catGuid, out string catName);
$dll AuditEnumerateSubCategories(Guid catGuid, bool all, out IntPtr subList, out uint count);
$dll AuditLookupSubCategoryName(Guid subGuid, out String subName);
$dll AuditQuerySystemPolicy(Guid subGuid, uint count, out IntPtr policy);
$dll AuditFree(IntPtr buffer);"
Add-Type -TypeDefinition "
using System;
public struct AUDIT_POLICY_INFORMATION {
public Guid AuditSubCategoryGuid;
public UInt32 AuditingInformation;
public Guid AuditCategoryGuid;
}"
function getPolicyInfo($sub) {
# get policy info for one subcategory:
$pol = new-object AUDIT_POLICY_INFORMATION
$size = $ms::SizeOf($pol)
$ptr = $ms::AllocHGlobal($size)
$null = $ms::StructureToPtr($pol, $ptr, $false)
$null = $auditpol::AuditQuerySystemPolicy($sub, 1, [ref]$ptr)
$pol = $ms::PtrToStructure($ptr, [type][AUDIT_POLICY_INFORMATION])
$null = $ms::FreeHGlobal($ptr)
[PsCustomObject]@{
category = $pol.AuditCategoryGuid
success = [bool]($pol.AuditingInformation -band 1)
failure = [bool]($pol.AuditingInformation -band 2)
}
}
# (optional) get GUID and local name of all categories:
$ms = [System.Runtime.InteropServices.Marshal]
$count = [uint32]0
$buffer = [IntPtr]::Zero
$size = $ms::SizeOf([type][guid])
$null = $auditpol::AuditEnumerateCategories([ref]$buffer,[ref]$count)
$ptr = [int64]$buffer
$name = [System.Text.StringBuilder]::new()
$catList = @{}
foreach($id in 1..$count) {
$guid = $ms::PtrToStructure([IntPtr]$ptr,[type][guid])
$null = $auditpol::AuditLookupCategoryName($guid,[ref]$name)
$catList[$guid] = $name
$ptr += $size
}
$null = $auditpol::AuditFree($buffer)
# get all subcategories (with optional name):
$guid = [guid]::Empty
$null = $auditpol::AuditEnumerateSubCategories($guid, $true, [ref]$buffer, [ref]$count)
$ptr = [int64]$buffer
$subList = @{}
foreach($id in 1..$count) {
$guid = $ms::PtrToStructure([IntPtr]$ptr,[type][guid])
$null = $auditpol::AuditLookupSubCategoryName($guid,[ref]$name)
$pol = getPolicyInfo $guid
$data = [psCustomObject]@{
category = $catList[$pol.category]
subcategory = $name
success = $pol.success
failure = $pol.failure
}
$subList[$guid.guid] = $data
$ptr += $size
}
$null = $auditpol::AuditFree($buffer)
# listing all subCategories and their audit settings:
$subList.Values | sort category, subcategory | ft -AutoSize
# gettings the audit-settings for a given subcategory-GUID (without '{}'):
$process_creation_guid = '0CCE922B-69AE-11D9-BED3-505054503030'
$subList[$process_creation_guid]
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Mathias R. Jessen |
Solution 2 | Cpt.Whale |
Solution 3 | Carsten |