使用不同的用户凭据通过提升启动另一个进程

时间:2012-03-26 13:12:25

标签: .net security uac

我正在尝试使用非提升的进程启动提升的进程,但我还需要为具有管理凭据的用户提供用户名和密码。我已尝试使用"runas"方法进行提升以及使用清单,但两者都会产生不同的错误。

例如,如果我这样做(不使用需要提升的清单):

ProcessStartInfo info = new ProcessStartInfo(path);

info.UseShellExecute = false;
info.UserName = username;
info.Password = securePwd;
info.Domain = "MyDomain";
info.Verb = "runas";

var proc = Process.Start(info);

该过程在不显示UAC确认对话框的情况下启动,并在尝试执行需要管理员权限的命令时失败(我只是尝试将测试文件写入Program Files目录)。

如果我向目标应用程序添加一个表明它需要提升的清单,那么我会得到一个Win32Exception表明该操作需要提升。

问题似乎是将UseShellExecute设置为false(因为在不是这种情况下两种方法都可以正常工作),但我必须将其设置为false才能在不同的用户帐户。

如何从非提升流程启动提升流程并手动提供用户名和密码?

BOUNTY EDIT:虽然不能要求用户输入管理员凭据,但完全可以接受UAC nag对话框。我不打算在这里绕过UAC。

5 个答案:

答案 0 :(得分:12)

我很惊讶没有办法做到这一点,直到我找到了Chris Jackson的博客文章:

  

Why Can’t I Elevate My Application to Run As Administrator While Using CreateProcessWithLogonW?

     

你需要一个引导程序。一些过程可以让您转换到备用用户,后者可以负责运行requireAdministrator应用程序。所以,你可以设计这样的东西:

     

enter image description here

     

为什么我们不创建ShellExecuteWithLogonW API?我永远不会说永远,我们可能会在某个时候。但是今天,这个API的用例一直是用例,其中有一个优越的替代设计。

     

最常见的请求是编写本土软件部署软件的人,他们希望将凭据编码到应用程序中并提升自己的流程。这里真正的问题不在于缺少API,而是您在应用中编码了管理员凭据,供全世界阅读。

因此解决方案需要 ShellExecute,它是唯一知道如何触发同意对话框的人。

它提出了一个很好的观点:你对一个人的密码做了什么?

Bonus Chatter

Server Core上没有UAC,因为没有窗口显示同意提示。

答案 1 :(得分:3)

From MSDN

  

您无法提升已在运行的流程。因此,你应该   重构您的应用程序,将其分为admin&非管理操作 -   以正常权限运行默认应用程序并启动   每个行政行动的另一个升级过程。

假设你request administrator rights from the outset on the processes that require them,让我们一起工作吧。根据您提供的背景信息:

  

问题似乎是将UseShellExecute设置为false(两者都是如此)   当不是这种情况时,方法工作正常),但我必须设置它   为了在不同的用户下启动进程,为false   帐户。

正如您所提到的,完全如the documentation for UseShellExecute中所述:

  

如果UserName属性不是Nothing,则UseShellExecute必须为false   或者是一个空字符串,或者抛出InvalidOperationException   当调用Process.Start(ProcessStartInfo)方法时。

我们现在知道你直接执行程序而不是使用shell。这是有价值的信息。

通过文档回溯,the docs for ProcessStartInfo带有以下安全说明:

  

此类包含适用于类级别的链接需求   所有成员。直接调用者抛出SecurityException   没有完全信任的许可。有关安全性的详细信息   要求见Link Demands

因此,您没有正确的链接需求。在尝试解决您的权限问题时,您无意中创建了另一个权限问题。

结果是您需要使用正确的Security Demand来装饰您的调用方法,该FullTrust应为{{1}}。您可以在代码中执行此操作declarativelyimperatively

Additional reading

答案 2 :(得分:1)

如果您正在创作Windows Installer(MSI)应用程序并使用MSP进行更新,那么Windows Installer内置了对您的方案的支持: - 查看User Account Control (UAC) Patching

它基本上是这样的:

  • 当您创作原始MSI时,您生成证书,并将其公钥(或类似内容)放入MSI中。
  • 目标计算机的管理员在计算机上安装MSI。
  • 您创作了更新(MSP),并使用证书对其进行签名。
  • 目标计算机上的任何用户现在都可以安装更新 - Windows Installer将根据原始MSI中的公钥验证证书,并同意安装(如果是)。我不认为你会得到一个UAC提示,但我不确定。

答案 3 :(得分:0)

根据MSDN文档:

  

当UseShellExecute为false时,您只能使用启动可执行文件   过程对象。

我注意到您的声明var proc = Process.Start(info);未使用Process作为班级类型。

还要确保参数path是可执行文件的完全限定路径。例如,"c:\\directory\\contains\\process_to_be_started\\executable.exe"

根据MSDN文档,这很重要:

  

如果UserName和Password为,则必须设置WorkingDirectory属性   提供。如果未设置该属性,则默认工作目录为   %SYSTEMROOT%\ SYSTEM32。

我会尝试下面的代码来使用提升的权限(使用管理员权限)运行目标进程。

ProcessStartInfo info = new ProcessStartInfo(path);

info.UseShellExecute = false;
info.UserName = username;
info.Password = securePwd;
info.Domain = "MyDomain";
info.Verb = "runas";
info.WorkingDirectory = "c:\\directory\\contains\\process_to_be_started"

'var proc = Process.Start(info);

Process proc = Process.Start(info);

答案 4 :(得分:0)

ProcessStartInfo.Verb="runas"仅针对Windows Vista及更高版本,因此您应该询问系统级别,而不是针对XP进行提升。

我认为如果您选择ProcessStartInfo.Verb="runas",则不应指定用户名和密码。

如果是UAC,那么无论如何它都应该成功,它应该不是问题。