/// <summary> /// Reset ACL /// </summary> public static void SetGracePeriodRegistryKeyPermission(RegistrySecurity rs) { Privileges.SetPrivilege("SeTakeOwnershipPrivilege"); Privileges.SetPrivilege("SeBackupPrivilege"); Privileges.SetPrivilege("SeRestorePrivilege"); var key = Registry.LocalMachine.OpenSubKey(TimeBombRegistryKeyName, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.ChangePermissions | RegistryRights.TakeOwnership); if (key == null) { return; // FIXME: should throw exception here } key.SetAccessControl(rs); key.Close(); }
/// <summary> /// Bypass ACL by allowing Administrator to write to the key /// Returns the old ACL /// </summary> public static RegistrySecurity SetGracePeriodRegistryKeyPermission() { Privileges.SetPrivilege("SeTakeOwnershipPrivilege"); Privileges.SetPrivilege("SeBackupPrivilege"); Privileges.SetPrivilege("SeRestorePrivilege"); var sid = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null); var account = sid.Translate(typeof(NTAccount)) as NTAccount; RegistrySecurity oldRs; // compatibility hell(?) // https://docs.microsoft.com/en-us/windows/win32/winprog64/registry-redirector?redirectedfrom=MSDN // https://stackoverflow.com/questions/2464358/why-is-opensubkey-returning-null-on-my-windows-7-64-bit-system/16698274 // var registryLocalMachine = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64); var registryLocalMachine = Registry.LocalMachine; // first, back up old ACL using (RegistryKey rk = registryLocalMachine.OpenSubKey(TimeBombRegistryKeyName, false)) { oldRs = rk?.GetAccessControl(AccessControlSections.All); } // then get owner using (RegistryKey rk = registryLocalMachine.OpenSubKey(TimeBombRegistryKeyName, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.TakeOwnership)) { RegistrySecurity rs = rk?.GetAccessControl(AccessControlSections.All); rs?.SetOwner(account ?? throw new InvalidOperationException()); rk?.SetAccessControl(rs ?? throw new InvalidOperationException()); } using (RegistryKey rk = registryLocalMachine.OpenSubKey(TimeBombRegistryKeyName, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.ChangePermissions)) { RegistrySecurity rs = rk?.GetAccessControl(AccessControlSections.All); Debug.Assert(account != null, nameof(account) + " != null"); RegistryAccessRule rar = new RegistryAccessRule( account.ToString(), RegistryRights.FullControl, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow); rs?.AddAccessRule(rar); rk?.SetAccessControl(rs ?? throw new InvalidOperationException()); } return(oldRs); }