Fix TrustedInstaller-owned registry key write via token privileges
- 03-system-registry.ps1: replace .NET OpenSubKey approach with proper P/Invoke that enables SeTakeOwnershipPrivilege and SeRestorePrivilege before attempting to take ownership of TrustedInstaller-owned keys (e.g. HKLM\...\Communications\ConfigureChatAutoInstall) - Remove SYSTEM scheduled task fallback (not needed with token approach) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d853df0aa4
commit
3a3513c3bc
1 changed files with 44 additions and 9 deletions
|
|
@ -11,11 +11,41 @@ function Write-Log {
|
|||
Add-Content -Path $LogFile -Value $line -Encoding UTF8
|
||||
}
|
||||
|
||||
Add-Type -TypeDefinition @"
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
public class RegPrivilege {
|
||||
[DllImport("advapi32.dll", ExactSpelling=true, SetLastError=true)]
|
||||
static extern bool AdjustTokenPrivileges(IntPtr htok, bool disAll, ref TokPriv1Luid newState, int len, IntPtr prev, IntPtr relen);
|
||||
[DllImport("kernel32.dll", ExactSpelling=true)]
|
||||
static extern IntPtr GetCurrentProcess();
|
||||
[DllImport("advapi32.dll", ExactSpelling=true, SetLastError=true)]
|
||||
static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);
|
||||
[DllImport("advapi32.dll", SetLastError=true)]
|
||||
static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);
|
||||
[StructLayout(LayoutKind.Sequential, Pack=1)]
|
||||
struct TokPriv1Luid { public int Count; public long Luid; public int Attr; }
|
||||
const int TOKEN_QUERY = 0x8;
|
||||
const int TOKEN_ADJUST = 0x20;
|
||||
const int SE_PRIVILEGE_ENABLED = 2;
|
||||
public static bool Enable(string privilege) {
|
||||
IntPtr htok = IntPtr.Zero;
|
||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST | TOKEN_QUERY, ref htok)) return false;
|
||||
TokPriv1Luid tp; tp.Count = 1; tp.Luid = 0; tp.Attr = SE_PRIVILEGE_ENABLED;
|
||||
if (!LookupPrivilegeValue(null, privilege, ref tp.Luid)) return false;
|
||||
return AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
"@ -ErrorAction SilentlyContinue
|
||||
|
||||
function Grant-RegWriteAccess {
|
||||
param([string]$Path)
|
||||
# Grants Administrators FullControl on a registry key that has restricted ACL.
|
||||
# Required for keys owned by TrustedInstaller or with locked-down ACL.
|
||||
# Grants Administrators FullControl on a TrustedInstaller-owned registry key.
|
||||
# Enables SeTakeOwnershipPrivilege + SeRestorePrivilege to override ACL.
|
||||
try {
|
||||
[RegPrivilege]::Enable("SeTakeOwnershipPrivilege") | Out-Null
|
||||
[RegPrivilege]::Enable("SeRestorePrivilege") | Out-Null
|
||||
|
||||
$hive = $Path -replace '^(HKLM|HKCU|HKU|HKCR|HKCC):\\.*', '$1'
|
||||
$subkey = $Path -replace '^(HKLM|HKCU|HKU|HKCR|HKCC):\\', ''
|
||||
$rootKey = switch ($hive) {
|
||||
|
|
@ -23,17 +53,22 @@ function Grant-RegWriteAccess {
|
|||
"HKCU" { [Microsoft.Win32.Registry]::CurrentUser }
|
||||
"HKCR" { [Microsoft.Win32.Registry]::ClassesRoot }
|
||||
}
|
||||
$rights = [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree
|
||||
$regRights = [System.Security.AccessControl.RegistryRights]::TakeOwnership
|
||||
$key = $rootKey.OpenSubKey($subkey, $rights, $regRights)
|
||||
|
||||
# Take ownership (requires SeTakeOwnershipPrivilege)
|
||||
$key = $rootKey.OpenSubKey($subkey,
|
||||
[Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree,
|
||||
[System.Security.AccessControl.RegistryRights]::TakeOwnership)
|
||||
if ($key) {
|
||||
$acl = $key.GetAccessControl([System.Security.AccessControl.AccessControlSections]::None)
|
||||
$acl.SetOwner([System.Security.Principal.NTAccount]"BUILTIN\Administrators")
|
||||
$key.SetAccessControl($acl)
|
||||
$key.Close()
|
||||
}
|
||||
# Re-open with ChangePermissions to grant full control
|
||||
$key = $rootKey.OpenSubKey($subkey, $rights, [System.Security.AccessControl.RegistryRights]::ChangePermissions)
|
||||
|
||||
# Grant FullControl to Administrators (requires ChangePermissions)
|
||||
$key = $rootKey.OpenSubKey($subkey,
|
||||
[Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree,
|
||||
[System.Security.AccessControl.RegistryRights]::ChangePermissions)
|
||||
if ($key) {
|
||||
$acl = $key.GetAccessControl()
|
||||
$rule = New-Object System.Security.AccessControl.RegistryAccessRule(
|
||||
|
|
@ -41,12 +76,12 @@ function Grant-RegWriteAccess {
|
|||
[System.Security.AccessControl.RegistryRights]::FullControl,
|
||||
[System.Security.AccessControl.InheritanceFlags]"ContainerInherit,ObjectInherit",
|
||||
[System.Security.AccessControl.PropagationFlags]::None,
|
||||
[System.Security.AccessControl.AccessControlType]::Allow
|
||||
)
|
||||
[System.Security.AccessControl.AccessControlType]::Allow)
|
||||
$acl.SetAccessRule($rule)
|
||||
$key.SetAccessControl($acl)
|
||||
$key.Close()
|
||||
}
|
||||
Write-Log " ACL fixed for $Path" -Level INFO
|
||||
}
|
||||
catch {
|
||||
Write-Log " Grant-RegWriteAccess failed for $Path - $_" -Level WARN
|
||||
|
|
|
|||
Loading…
Reference in a new issue