2

我有一个 Powershell 脚本,它更改了通常由 TrustedInstaller 拥有的注册表值。基本工作流程是:

  1. 尝试打开密钥进行编辑

    1. 如果失败,请尝试打开密钥以获得权限

      1. 如果失败,请尝试打开获取所有权的密钥
      2. 使用备份 ACLif ($backupAcl -eq $null) { $backupAcl = $key.GetAccessControl(); }
      3. 获取 ACL 的工作副本$acl = $key.GetAccessControl();
      4. 将所有者设置为$acl.SetOwner($me);
      5. 打开权限更改密钥
    2. 使用备份 ACLif ($backupAcl -eq $null) { $backupAcl = $key.GetAccessControl(); }

    3. 获取 ACL 的工作副本$acl = $key.GetAccessControl();
    4. 应用权限$acl.AddAccessRule($rule); $acl.SetAccessControl($acl);
    5. 打开密钥进行编辑
  2. 更改我需要更改的值$key.SetValue(...)

  3. 恢复之前对权限所做的任何更改。

我用来恢复权限的代码如下:

$key = [Microsoft.Win32.Registry]::ClassesRoot.OpenSubKey($subKeyName, $regOpenMode, $regTakeOwnChangePerms);

Write-Host "Setting permissions to:"
Format-List -InputObject $aclBackup;

$key.SetAccessControl($aclBackup);

Write-Host "Permissions set to:"
Format-List -InputObject $key.GetAccessControl();

$key.Close();

...但是,它实际上从未将 ACL 设置回原来的状态。

除此之外,脚本工作正常——ACL 设置为更改值所需的值(所以我知道我可以更改 ACL)并且值本身已更改(所以我知道我已经更改了 ACL) .

但回归永远不会发生。不会引发任何异常——它永远不会发生。

为什么不?以及如何将 ACL 恢复到脚本启动时的状态?

4

2 回答 2

1

我得到了它。看来您不能以这种方式重用ObjectSecurity对象,所以我不得不使用该方法序列化备份 ACLGetSecurityDescriptorBinaryForm()并使用该方法再次反序列化它SetSecurityDescriptorBinaryForm(...)

但是,一旦我这样做了,我得到了另一个错误 - The security identifier is not allowed to be the owner of this object

我必须通过请求系统权限来克服这个问题SeRestorePrivilege,我使用Enable-Privelege来自http://social.technet.microsoft.com/Forums/en/winserverpowershell/thread/e718a560-2908-4b91-ad42-d392e7f8f1ad的函数(一个函数我已经在使用请求SeTakeOwnershipPrivilege首先获得所有权)。

一旦我有了这个权限,我就可以用我缓存中的反序列化的 ACL 覆盖 ACL。

因此,要备份 ACL:

if ($aclBackup -eq $null) { 
    $aclBackup = $key.GetAccessControl().GetSecurityDescriptorBinaryForm(); 
}

并恢复它:

if (Enable-Privilege SeRestorePrivilege) {
    $acl = New-Object System.Security.AccessControl.RegistrySecurity;
    $acl.SetSecurityDescriptorBinaryForm($aclBackup, $aclIncludeAll);

    $key = $keyRoot.OpenSubKey($subKeyName, $regOpenMode, $regTakeOwnChangePerms);
    $key.SetAccessControl($acl);
    $key.Close();
}

希望这对将来的其他人有所帮助...

于 2013-02-20T18:09:22.767 回答
0

由于您正在对内存中的对象进行修改,因此您需要使用该命令Set-ACL来影响对实际文件 ACL 的更改。

使用 Get ACL 将从注册表项中读取访问列表。我不认为你需要这条线。

$key = [Microsoft.Win32.Registry]::ClassesRoot.OpenSubKey($subKeyName, $regOpenMode, $regTakeOwnChangePerms);

尝试

$ACLobject = Get-ACL -Path $RegKey
$ACLObject |Set-ACL -Path $newRegKey

在这两者之间,您可以以任何您喜欢的方式操作 $ACLobject 的属性。

于 2013-02-20T16:43:39.323 回答