Filtering Files Based on Specific Permissions:
Checking for Write Permission for a Group:
$acl = Get-Acl -Path "C:\TestFolder" Write-Host "The group has Write access." Write-Host "The group does not have Write access."Combining Multiple Permission Checks:
Use comparison operators (==, -eq) to check for exact permission matches.
Employ the operator for bitwise comparison to check for specific permission flags within a set of permissions.
Combine multiple clauses for complex permission filtering.
Leverage PowerShell’s object manipulation capabilities for advanced permission analysis and management.
Get-Acl does not pull the Acl for HKLM\Security.
asked Dec 6, 2023 at 15:53
Get-Acl path\goes\here first tries to resolve the target item at path\goes\here (equivalent to Get-Item path\goes\here), before fetching the associated ACL from the resolved target item.
One way to work around this – and I’m sure there are other, potentially safer ways – is to use a bit of reflection to hook into the private constructor that RegistryKey.GetAccessControl() usually invokes under the hood:
# discover private constructor of [RegistrySecurity] class
$registryACLPrivateConstructor = [System.Security.AccessControl.RegistrySecurity].GetConstructors([System.Reflection.BindingFlags]'NonPublic,Instance')[0]
# prepare arguments - hive, path, and section mask
$hiveHandle = (Get-Item HKLM:\).Handle
$keyPath = 'SECURITY'
$sections = [System.Security.AccessControl.AccessControlSections]::All
# construct the ACL by invoking the private ctor
$securityACL = $registryACLPrivateConstructor.Invoke(@($hiveHandle, $keyPath, $sections))$securityACL now contains the security descriptor object corresponding to HKLM:\SECURITY
answered Dec 6, 2023 at 16:13

Mathias R. JessenMathias R. Jessen
12 gold badges164 silver badges221 bronze badges
Supporting Resources
Adjusting TOKEN PRIVILEGES in PowerShell
Privilege Constants (Authorization)
How RPC Works
Specifies the access control rights that can be applied to registry
objects.Specifies whether an AccessRule object is used to allow or deny
access.
What is Get-Acl in PowerShell?
Get-Acl stands for “Get Access Control List”. It retrieves the security descriptor of a specified resource, including information about its access rights, owner, and access control entries (ACEs). This is crucial for security and compliance checks in an IT environment.
Retrieving ACL of a File
Get-Acl -Path C:\Example.txt
This command returns the ACL of the file ‘Example.txt’.
Retrieving ACL of a Directory
Get-Acl -Path C:\ExampleFolder
Here, the ACL for ‘ExampleFolder’ is retrieved, showing all security settings and permissions.
Exporting ACL Information to a File
Get-Acl -Path C:\Example.txt | Export-Csv -Path C:\ACL_Report.csv
This script retrieves the ACL for ‘Example.txt’ and exports the details to a CSV file for further analysis or reporting.
Frequently Asked Questions
Can Get-Acl retrieve ACLs from remote computers?
Get-Acl can be used in conjunction with PowerShell remoting to retrieve ACLs from remote systems.
How can I filter specific types of permissions with Get-Acl?
Is it possible to compare ACLs of two different objects?
You can use Get-Acl to retrieve ACLs of two objects and then compare them using PowerShell comparison operators or scripts.
Can Get-Acl handle inherited permissions?
Yes, Get-Acl shows both explicit and inherited permissions for an object.
How do I modify permissions after using Get-Acl?
To modify permissions, you can use Get-Acl in conjunction with Set-Acl. First, retrieve the ACL, modify it as needed, and then apply it back to the object with Set-Acl.
Take ownership of a registry key via PowerShell
I’ve encountered a similar situation in the past and can offer a solution that worked for me, tailored to better suit your specific requirements with error handling for suppression.
PowerShell Enable-Privilege Function
Function Enable-Privilege { param ([string[]]$Privileges) try { $typeExists = [AppDomain]::CurrentDomain.GetAssemblies() | ForEach-Object {$_.GetExportedTypes() | Where-Object { $_.Name -eq "AdjPriv" }}; if ($typeExists -eq $null) { $Definition = @" using System; using System.Runtime.InteropServices; public class AdjPriv { [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr rele); [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok); [DllImport("advapi32.dll", SetLastError = true)] internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid); [StructLayout(LayoutKind.Sequential, Pack = 1)] internal struct TokPriv1Luid { public int Count; public long Luid; public int Attr; } internal const int SE_PRIVILEGE_ENABLED = 0x00000002; internal const int TOKEN_QUERY = 0x00000008; internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020; public static bool EnablePrivilege(long processHandle, string privilege) { bool retVal; TokPriv1Luid tp; IntPtr hproc = new IntPtr(processHandle); IntPtr htok = IntPtr.Zero; retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok); tp.Count = 1; tp.Luid = 0; tp.Attr = SE_PRIVILEGE_ENABLED; retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid); retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero); return retVal; } }
"@ $ProcessHandle = (Get-Process -id $pid).Handle; $type = Add-Type $definition -PassThru}; $Privileges | ForEach-Object {If($_){Try{$type[0]::EnablePrivilege($processHandle, $_)}Catch{$False}} } }catch{} };PowerShell TakeOwnership-RegistryKey Function
Note: This has HKLM level logic hard-coded into it so it’s HKLM specific.
Function TakeOwnership-RegistryKey { param ([string]$RegistryPath) Enable-Privilege @("SeTakeOwnershipPrivilege", "SeRestorePrivilege") $key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($RegistryPath, [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree, [System.Security.AccessControl.RegistryRights]::TakeOwnership) if ($key -eq $null) { Write-Host "Registry key not found: $RegistryPath"; return; } $acl = $key.GetAccessControl(); $owner = [System.Security.Principal.NTAccount]"$env:USERDOMAIN\$env:USERNAME"; $acl.SetOwner($owner); $key.SetAccessControl($acl); Write-Host "Ownership of registry key '$RegistryPath' has been taken by $env:USERNAME" -ForegroundColor Yellow;
};Execute
Note: You will not append HKLM to the value passed to the function here—omit it.
TakeOwnership-RegistryKey "SOFTWARE\Test";

