如何以编程方式将注册表项的所有权授予管理员

本文关键字:所有权 管理员 注册表 编程 方式 | 更新日期: 2023-09-27 17:57:29

当我将一些机器升级到Windows 10时,遇到了一个奇怪的问题,因为RuntimeBroker上的不正确权限导致了问题。我在网上找到了一个建议更改权限的解决方案(首先是在注册表中,然后是在DCOM配置中),我正在尝试编写一个小型.NET应用程序来自动化这个过程。

目前,相关注册表项的所有者是NT SERVICE'TrustedInstaller,我正在尝试将其更改为COMPUTER'Administrators。我有一个简单的WPF应用程序,requestedExecutionLevel设置为"requireAdministrator",但我仍然遇到问题。这里有一段代码来说明这个问题:

using System.Security.AccessControl;
using System.Security.Principal;
using Microsoft.Win32;
namespace PermissionFixer
{
    public class Fixer
    {
        public void Fix()
        {
            var subKey = Registry.ClassesRoot.OpenSubKey(@"AppID'{9CA88EE3-ACB7-47c8-AFC4-AB702511C276}", true);
            if (subKey != null)
            {
                var admins = new NTAccount("Administrators");
                var ac = subKey.GetAccessControl();
                ac.SetOwner(admins);
                ac.AddAccessRule(new RegistryAccessRule(admins, RegistryRights.FullControl, AccessControlType.Allow));
                subKey.SetAccessControl(ac);
            }
        }
    }
}

问题是,它甚至没有通过对OpenSubKey()的调用,然后点击一个SecurityException,上面写着"不允许请求的注册表访问"。我认为这是因为管理员还没有访问权限(记住它属于TrustedInstaller),但这有点像鸡和蛋的问题。奇怪的是,当我手动使用regedit时,我被允许将所有者更改为Administrators,而且我很确定我的regedit实例是以Administrators身份运行的。

如何在.NET中实现此功能?

如何以编程方式将注册表项的所有权授予管理员

我发现了这一点,幸运的是,使用.NET类可以实现这一点。以下是如何调用OpenSubKey:

var subKey = Registry.ClassesRoot.OpenSubKey(@"AppID'{9CA88EE3-ACB7-47c8-AFC4-AB702511C276}", RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.TakeOwnership);

然后你必须拒绝呼叫AddAccessRule()。。。在拥有所有权之前,你不能修改它;你必须串行地执行这两个操作。因此,首先获取所有权,然后重新打开具有不同访问权限的密钥以添加访问规则。

EDIT:我今天发现必须先通过挂接p/Invoke调用来操作运行应用程序的令牌。我发现在另一个Stack Overflow问题中引用了一个名为TokenManipulator的类。在您的项目中包括该类,然后在调用OpenSubKey之前向您的令牌授予备份、还原和TakeOwnership权限。所以你的方法最终会看起来像这样:

try
{
    TokenManipulator.AddPrivilege("SeRestorePrivilege");
    TokenManipulator.AddPrivilege("SeBackupPrivilege");
    TokenManipulator.AddPrivilege("SeTakeOwnershipPrivilege");
    var subKey = Registry.ClassesRoot.OpenSubKey(@"AppID'{9CA88EE3-ACB7-47c8-AFC4-AB702511C276}", RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.TakeOwnership);
    // code to change owner...
}
finally
{
    TokenManipulator.RemovePrivilege("SeRestorePrivilege");
    TokenManipulator.RemovePrivilege("SeBackupPrivilege");
    TokenManipulator.RemovePrivilege("SeTakeOwnershipPrivilege");
}