WMI: 远程编辑注册表

4
我正在尝试使用以下代码(写得很糟糕,但仅是概念验证)来编辑域上计算机的注册表。我有一个域帐户,并已验证域管理员组存在于我正在尝试影响的计算机的本地管理员组中。我已连接到这些其他计算机以执行其他管理类型任务,因此我确定我在这些主机上拥有管理权限。
所有StdRegProv的“获取”方法都正常工作(http://msdn.microsoft.com/en-us/library/aa393664%28VS.85%29.aspx),但“设置”或“创建”方法以及检查访问权限都返回“5”,这是根据winerror.h的“Error_Access_Denied”。所以问题就在这里:为什么我在尝试修改注册表时会被拒绝访问?如果有人能帮助我解决这个问题,我将非常感激!
我差点忘了,在我的本地计算机上以管理员模式启动Visual Studio并对本地计算机运行代码时,它可以无缝运行。如果我不在本地计算机上以管理员模式启动,则代码会失败,因此我怀疑这可能是UAC问题?更新:使用regedit连接到远程计算机,我可以更改注册表键,这使我相信这不是UAC问题,但在我的机器上以提升的模式运行时,它使用本地WMI连接执行,所以也许它是UAC问题。另外,winXP机器返回相同的错误码(5,ERROR_ACCESS_DENIED),这使我相信这不是UAC问题...这很糟糕。解决方案:ManagementClass对象正在使用错误的重载;它必须使用ManagementScope进行参数化,否则,您只是在本地执行函数。
ManagementClass mc = new ManagementClass(scope, new ManagementPath("StdRegProv"), null);

是的,我很失败 :/ 9000行代码,而这一行让我卡了最久的时间。

using System;
using System.Management;


public class EditRemoteRegistry
{
    public static void Main(string[] args)
    {
        ConnectionOptions options = new ConnectionOptions();
        options.EnablePrivileges = true;
        options.Impersonation = ImpersonationLevel.Impersonate;
        options.Password = "password goes here";
        //options.Authority = "my company's domain";
        //options.Username = "Admin username";

        ManagementScope scope = new ManagementScope("\\\\arbitraryhost\\root\\default", options);
        scope.Connect();

        ManagementClass mc = new ManagementClass("StdRegProv");

        ManagementBaseObject inParams = mc.GetMethodParameters("CreateKey");
        inParams["hDefKey"] = (UInt32)2147483650;
        inParams["sSubKeyName"] = "Software\\Test";
        ManagementBaseObject outParams = mc.InvokeMethod("CreateKey", inParams, null);
        //Should return a 0, but returns a 5, "Error_Access_Denied"
        Console.WriteLine("CreateKey Method returned " + outParams["returnValue"]);

        //This chunk works fine
        ManagementBaseObject inParams5 = mc.GetMethodParameters("GetDWORDValue");
        inParams5["hDefKey"] = 2147483650;
        inParams5["sSubKeyName"] = "Software\\Test";
        inParams5["sValueName"] = "testDWORDvalue";
        ManagementBaseObject outParams5 = mc.InvokeMethod("GetDWORDValue", inParams5, null);
        Console.WriteLine("GetDWORDValue returned " + (UInt32)outParams5["returnValue"] + " ");
        Console.WriteLine((UInt32)outParams5["uValue"]);


        ManagementBaseObject inParams6 = mc.GetMethodParameters("SetStringValue");
        inParams6["hDefKey"] = 2147483650;
        inParams6["sSubKeyName"] = "Software\\Test";
        inParams6["sValueName"] = "TestStringValue";
        inParams6["sValue"] = "Hello World!";
        ManagementBaseObject outParams6 = mc.InvokeMethod("SetStringValue", inParams6, null);
        //Should return a 0, but returns a 5, "Error_Access_Denied"
        Console.WriteLine("SetStringValue returned " + outParams6["returnValue"]);

        Console.ReadKey();
    }
}
2个回答

2
您也可以关闭远程UAC过滤。
禁用远程UAC通过更改控制远程UAC的注册表项并不推荐,但在工作组中可能是必要的。注册表项为HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\system\LocalAccountTokenFilterPolicy。当此项的值为零(0)时,启用了远程UAC访问令牌过滤。当该值为1时,远程UAC被禁用。

http://msdn.microsoft.com/en-us/library/aa826699(VS.85).aspx


好的提示,但不幸的是,根据政策,需要在整个域上启用UAC。此外,在更改注册表值后,机器是否需要重新启动? - Quanta
你尝试将用户添加到本地管理员组了吗?根据我发布的链接:“如果您的计算机是域的一部分,请使用在远程计算机的本地管理员组中的域帐户连接到目标计算机。然后,UAC访问令牌过滤不会影响本地管理员组中的域帐户。”我不知道在你的情况下是否可行。 - Adam Driscoll
不幸的是,是的,我已经尝试过了(请参见我的帖子的第一段)。我认为msdn在说“然后UAC访问令牌过滤将不会影响本地管理员组中的域帐户”时是错误的,因为它肯定会影响,除非我漏掉了什么...我希望我漏掉了什么。肯定有人在远程使用WMI编辑注册表吧? - Quanta
2
明白了...注意我的ManagementClass没有使用连接对象进行参数化。我过去两天一直像一个失败的N00b-tard dumba**一样在本地执行这些函数。为了解决问题,我制作了一个.reg文件,将其推送到远程机器上运行,并在win32_process上获得了错误代码8。我觉得这很奇怪,所以我决定运行记事本并注意到它在我的面前执行而不是在远程机器上执行。正确的代码应该是:ManagementClass mc = new ManagementClass(conn, new ManagementPath("StdRegProv"), null); - Quanta

0

似乎在启用UAC的计算机上运行WMI设置器存在问题。

引用

根据我们从现场收到的报告,似乎需要禁用UAC才能使远程WMI查询正常工作。当UAC运行时,管理员帐户实际上有两个安全令牌,一个普通用户令牌和一个管理员令牌(只有在通过UAC提示时才激活)。不幸的是,通过网络传入的远程请求会为管理员获取普通用户令牌,由于没有办法远程处理UAC提示,因此无法将令牌提升为真正的管理员安全令牌。

source: http://www.poweradmin.com/help/enableWMI.aspx

尝试编辑远程计算机的注册表键:

HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\system\LocalAccountTokenFilterPolicy。

0 - 构建过滤令牌(启用远程UAC) 1 - 构建提升令牌(禁用远程UAC)


那就是问题所在,我无法远程编辑密钥,因为UAC已经开启了。不幸的是,我将在成千上万台机器上运行此代码,并且它们都必须运行UAC :/ - Quanta

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接