Reputation: 1
After reading this question and this blog post I came up with these commands
Set-Location HKLM:\Software\Classes\cmdfile\ShellEx\PropertySheetHandlers
$am = New-Object Security.Principal.NTAccount 'BUILTIN', 'Administrators'
$ke = Get-Acl 'ShimLayer Property Page'
$ke.SetOwner($am)
Set-Acl -AclObject $ke -Path 'ShimLayer Property Page'
However when I run them I get this message
Set-Acl : Requested registry access is not allowed.
How can I change the owner of this key?
Upvotes: 2
Views: 14968
Reputation: 624
Try it out:
# group BULTIN\Users takes full control of key and all subkeys
Take-Permissions("HKLM", "SOFTWARE\test")
# group Everyone takes full control of key and all subkeys
Take-Permissions("HKLM", "SOFTWARE\test", "S-1-1-0")
# group Everyone takes full control of key WITHOUT subkeys
Take-Permissions("HKLM", "SOFTWARE\test", "S-1-1-0", $false)
Just define this function:
function Take-Permissions {
# Developed for PowerShell v4.0
# Required Admin privileges
# Links:
# http://shrekpoint.blogspot.ru/2012/08/taking-ownership-of-dcom-registry.html
# http://www.remkoweijnen.nl/blog/2012/01/16/take-ownership-of-a-registry-key-in-powershell/
# https://powertoe.wordpress.com/2010/08/28/controlling-registry-acl-permissions-with-powershell/
param($rootKey, $key, [System.Security.Principal.SecurityIdentifier]$sid = 'S-1-5-32-545', $recurse = $true)
switch -regex ($rootKey) {
'HKCU|HKEY_CURRENT_USER' { $rootKey = 'CurrentUser' }
'HKLM|HKEY_LOCAL_MACHINE' { $rootKey = 'LocalMachine' }
'HKCR|HKEY_CLASSES_ROOT' { $rootKey = 'ClassesRoot' }
'HKCC|HKEY_CURRENT_CONFIG' { $rootKey = 'CurrentConfig' }
'HKU|HKEY_USERS' { $rootKey = 'Users' }
}
### Step 1 - escalate current process's privilege
# get SeTakeOwnership, SeBackup and SeRestore privileges before executes next lines, script needs Admin privilege
$import = '[DllImport("ntdll.dll")] public static extern int RtlAdjustPrivilege(ulong a, bool b, bool c, ref bool d);'
$ntdll = Add-Type -Member $import -Name NtDll -PassThru
$privileges = @{ SeTakeOwnership = 9; SeBackup = 17; SeRestore = 18 }
foreach ($i in $privileges.Values) {
$null = $ntdll::RtlAdjustPrivilege($i, 1, 0, [ref]0)
}
function Take-KeyPermissions {
param($rootKey, $key, $sid, $recurse, $recurseLevel = 0)
### Step 2 - get ownerships of key - it works only for current key
$regKey = [Microsoft.Win32.Registry]::$rootKey.OpenSubKey($key, 'ReadWriteSubTree', 'TakeOwnership')
$acl = New-Object System.Security.AccessControl.RegistrySecurity
$acl.SetOwner($sid)
$regKey.SetAccessControl($acl)
### Step 3 - enable inheritance of permissions (not ownership) for current key from parent
$acl.SetAccessRuleProtection($false, $false)
$regKey.SetAccessControl($acl)
### Step 4 - only for top-level key, change permissions for current key and propagate it for subkeys
# to enable propagations for subkeys, it needs to execute Steps 2-3 for each subkey (Step 5)
if ($recurseLevel -eq 0) {
$regKey = $regKey.OpenSubKey('', 'ReadWriteSubTree', 'ChangePermissions')
$rule = New-Object System.Security.AccessControl.RegistryAccessRule($sid, 'FullControl', 'ContainerInherit', 'None', 'Allow')
$acl.ResetAccessRule($rule)
$regKey.SetAccessControl($acl)
}
### Step 5 - recursively repeat steps 2-5 for subkeys
if ($recurse) {
foreach($subKey in $regKey.OpenSubKey('').GetSubKeyNames()) {
Take-KeyPermissions $rootKey ($key+'\'+$subKey) $sid $recurse ($recurseLevel+1)
}
}
}
Take-KeyPermissions $rootKey $key $sid $recurse
}
Upvotes: 0
Reputation: 77846
If the administrator group has been removed from the ACL then you will end up with this error. But you can use OpenSubKey() method to Retrieves the specified subkey for read or read/write access, requesting the specified access rights.
$key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey("Software\Classes\cmdfile\ShellEx\PropertySheetHandlers",[Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree,[System.Security.AccessControl.RegistryRights]::ChangePermissions)
Once you have it then you can use GetAccessControl()
and SetAccessControl()
method to get the permission back
$acl = $key.GetAccessControl()
$key.SetAccessControl($acl)
See this post for more information.
EDIT:
One more way to set the access control of registry
$ke = Get-Acl 'HKLM:\Software\Classes\cmdfile\ShellEx\PropertySheetHandlers\ShimLayer Property Page'
$rule = New-Object System.Security.AccessControl.RegistryAccessRule ("mydomain\myusername","FullControl","Allow")
$ke.SetAccessRule($rule)
$ke |Set-Acl -Path 'HKLM:\Software\Classes\cmdfile\ShellEx\PropertySheetHandlers\ShimLayer Property Page'
Upvotes: 1
Reputation: 1
After reading these
Changing owner of key to Administrator
Set controls on files owned by TrustedInstaller
I came up with this working solution.
Function Enable-Privilege {
param($Privilege)
$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
$type[0]::EnablePrivilege($processHandle, $Privilege)
}
do {} until (Enable-Privilege SeTakeOwnershipPrivilege)
$key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey(
'Software\Classes\cmdfile\ShellEx\PropertySheetHandlers\ShimLayer Property Page',
'ReadWriteSubTree', 'TakeOwnership')
$owner = [Security.Principal.NTAccount]'Administrators'
$acl = $key.GetAccessControl()
$acl.SetOwner($owner)
$key.SetAccessControl($acl)
Upvotes: 7