C#WPF - 即使使用管理员权限,也不允许注册表访问?

时间:2017-02-17 12:44:19

标签: c# wpf windows registry administrator

我最近一直在研究一个非常好的注册表编辑器。

但是,Regedit中指出的某些注册表项不会显示在我的程序中,因为它们在打开时会引发权限不足的错误,因此会被错误处理捕获并跳过:

注册表编辑器:

Registry 1

我的节目:

Registry 2

正如您所看到的,即使我使用管理员权限运行程序,也会丢失SECURITY密钥,并且SAM密钥不可扩展。

这显然可以通过制作假钥匙并将它们放在那里来修复,并且只为它们显示一个空的默认值,但这不是一个具体的解决方案,只是一种让用户看起来好像问题的方法解决了。​​

我想知道是否有办法以具体的方式解决问题,换句话说,是否可以获得对这些密钥的注册表访问权限?

它们显示的所有内容都是空的默认值,包括可扩展的SAM键 - 它只有一个名为“SAM”的子键,并且还有一个空的默认值。

然而,对于用户来说,如果程序与Regedit完全一样,那就更好了,因为这意味着它是一个功能齐全的软件。

感谢您的帮助。

编辑(包含代码):

public static void TreeViewItemExpanded(TreeViewItem sender)
        {
            if (sender.Items[0] is string)
            {
                sender.Items.Clear();

                RegistryKey expandedKey = (RegistryKey)sender.Tag;

                foreach (string key in expandedKey.GetSubKeyNames().OrderBy(x => x)) try { sender.Items.Add(CreateTreeViewItem(expandedKey.OpenSubKey(key))); } catch { }
            }
        }

        private static TreeViewItem CreateTreeViewItem(RegistryKey key)
        {
            TreeViewItem treeViewItem = new TreeViewItem() { Header = new RegistryEditor_RegistryStructure_TreeView() { Name = Path.GetFileName(key.ToString()) }, Tag = key };

            try { if (key.SubKeyCount > 0) treeViewItem.Items.Add("Loading..."); } catch { }

            return treeViewItem;
        }

2 个答案:

答案 0 :(得分:1)

您没有向例程提供示例代码,但我怀疑您使用的是默认的注册表安全描述符。

您可以在调用RegCreateKeyEx或RegSetKeySecurity函数时为注册表项指定安全描述符。

当您调用RegOpenKeyEx函数时,系统会根据密钥的安全描述符检查所请求的访问权限。如果用户没有对注册表项的正确访问权限,则打开操作将失败。如果管理员需要访问密钥,则解决方案是启用SE_TAKE_OWNERSHIP_NAME权限并使用WRITE_OWNER访问权限打开注册表项。

此信息来自:MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724878(v=vs.85).aspx

在C#中你应该使用Registery Permission Class https://msdn.microsoft.com/en-us/library/system.security.permissions.registrypermission(v=vs.110).aspx

可以在此处找到如何处理注册表权限的一个很好的示例: https://msdn.microsoft.com/en-us/library/microsoft.win32.registrykey.setaccesscontrol(v=vs.110).aspx

答案 1 :(得分:0)

您需要启用SE_RESTORE_PRIVILEGESE_BACKUP_PRIVILEGE并使用RegOpenKeyExZwOpenKeyExREG_OPTION_BACKUP_RESTORE标记(但这只能从Windows开始工作7及更高版本的Windows

  

如果设置了此标志,则该函数将忽略samDesired参数和   尝试使用备份或还原所需的访问权限打开密钥   钥匙。如果调用线程具有SE_BACKUP_NAME权限   启用后,将使用ACCESS_SYSTEM_SECURITY打开密钥   KEY_READ访问权限。如果调用线程有SE_RESTORE_NAME   启用权限,从Windows Vista开始,密钥已打开   使用ACCESS_SYSTEM_SECURITY,DELETE和KEY_WRITE访问权限。   如果启用了这两个权限,则该密钥具有组合访问权限   两种特权。

例如

#define LAA(se) {{se},SE_PRIVILEGE_ENABLED|SE_PRIVILEGE_ENABLED_BY_DEFAULT}
#define BEGIN_PRIVILEGES(tp, n) static const struct {ULONG PrivilegeCount;LUID_AND_ATTRIBUTES Privileges[n];} tp = {n,{
#define END_PRIVILEGES }};

ULONG AdjustBackupRestore()
{
    HANDLE hToken;
    if (OpenProcessToken(NtCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
    {
        BEGIN_PRIVILEGES(tp, 2)
            LAA(SE_RESTORE_PRIVILEGE),
            LAA(SE_BACKUP_PRIVILEGE),
        END_PRIVILEGES

        AdjustTokenPrivileges(hToken, FALSE, (::PTOKEN_PRIVILEGES)&tp, 0, 0, 0);
        ULONG err = GetLastError();
        CloseHandle(hToken);

        return err;
    }

    return GetLastError();
}
if (!AdjustBackupRestore())//called once on startup
{
    HKEY hKey;
    if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SECURITY\\SAM", REG_OPTION_BACKUP_RESTORE|REG_OPTION_OPEN_LINK, 0, &hKey))
    {
        RegCloseKey(hKey);
    }
}

然而,为了获得注册表编辑器/查看器的全部功能,我将使用本机API

enter image description here