更改注册表项的ACL,编辑值,然后将其更改回来

时间:2013-02-20 16:36:39

标签: .net powershell

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

  1. 尝试打开要编辑的密钥

    1. 如果此操作失败,请尝试打开权限密钥

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

    3. 备份ACL
    4. 使用$acl = $key.GetAccessControl();
    5. 获取ACL的工作副本
    6. 使用$acl.AddAccessRule($rule); $acl.SetAccessControl($acl);
    7. 应用权限
    8. 打开要编辑的密钥
  2. 使用$key.SetValue(...)

  3. 更改我需要更改的值
  4. 还原对之前所做权限的任何更改。

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

    $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恢复到脚本启动时的状态?

2 个答案:

答案 0 :(得分:1)

我明白了。看来你不能以这种方式重用ObjectSecurity个对象,所以我不得不使用GetSecurityDescriptorBinaryForm()方法序列化备份ACL,并使用SetSecurityDescriptorBinaryForm(...)方法再次反序列化它。

但是,一旦我这样做了,我又收到了另一个错误 - 安全标识符不允许是该对象的所有者

我必须通过请求SeRestorePrivilege系统权限来解决这个问题,我使用http://social.technet.microsoft.com/Forums/en/winserverpowershell/thread/e718a560-2908-4b91-ad42-d392e7f8f1ad中的Enable-Privelege函数(我已用于请求SeTakeOwnershipPrivilege的函数)首先需要拥有所有权)。

获得此权限后,我可以使用我在缓存中的反序列化覆盖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();
}

希望将来帮助其他人......

答案 1 :(得分: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的属性。