我有一个小命令,允许我从CMD查询信息,但它需要管理员权限(不是在我的应用程序级别,但在CMD级别)只有我走这条路线的原因是因为我无法获得WMI在我的生活中查询bitlocker设置,这个项目需要离开我的办公桌。
if (bitA.Text == "Bitlocker Available")
{
Process cmd2 = new Process();
cmd2.StartInfo.Verb = "runas";
cmd2.StartInfo.FileName = "cmd.exe";
cmd2.StartInfo.Arguments = "/c ping 8.8.8.8";
cmd2.StartInfo.UseShellExecute = false;
cmd2.StartInfo.RedirectStandardOutput = true;
cmd2.StartInfo.RedirectStandardError = true;
cmd2.Start();
//* Read the output (or the error)
string output2 = cmd2.StandardOutput.ReadToEnd();
bitB.Text = output2;
cmd2.WaitForExit();
}
答案 0 :(得分:2)
您可以通过将startInfo对象的Verb属性设置为' runas'来指示应该使用提升的权限启动新进程,如下所示:
startInfo.Verb = "runas";
这将导致Windows的行为就像使用"以管理员身份运行"从资源管理器启动进程一样菜单命令。将提示用户使用UAC确认他们想要这样做。
编辑:我看到你已经设置了这个动词。你在问你是否可以绕过UAC吗?这将是一种愚蠢的行为,否则病毒编写者等可以用一行代码绕过安全检查。
答案 1 :(得分:1)
正如我在评论中所说,问题在于" runas"动词要求UseShellExecute为true,但重定向要求UseShellExecute为false。这使问题变得棘手,但关键是启动一个流程作为管理员,你可以通过某种IPC进行通信,然后这个过程启动你想要重定向输出的任何进程。它甚至可以是相同的可执行文件,只是打开收到的参数。如果我正在编写库,我可能会将shim可执行文件嵌入到汇编资源中。以下是使用命名管道的简单示例:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
using System.IO.Pipes;
using System.IO;
namespace AdminRedirect
{
class Program
{
private static readonly int ProcessId = Process.GetCurrentProcess().Id;
static void Main(string[] args)
{
bool isAdmin = IsAdministrator();
Console.WriteLine("Id = {0}, IsAdmin = {1}", ProcessId, isAdmin);
if (!isAdmin)
{
Console.WriteLine("Press any key to spawn the admin process");
Console.ReadKey(intercept: true);
string pipeName = "mypipe-" + Guid.NewGuid();
Process cmd = new Process()
{
StartInfo =
{
Verb = "runas",
Arguments = pipeName,
FileName = typeof(Program).Assembly.Location,
UseShellExecute = true
}
};
using (var pipeStream = new NamedPipeServerStream(pipeName))
{
cmd.Start();
Console.WriteLine("Started {0}", cmd.Id);
pipeStream.WaitForConnection();
Console.WriteLine("Received connection from {0}", cmd.Id);
using (var reader = new StreamReader(pipeStream))
{
string line;
while((line = reader.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
}
Console.WriteLine("Hit any key to end");
Console.ReadKey(intercept: true);
}
else
{
if (args.Length > 0)
{
string pipeName = args[0];
Console.WriteLine("Opening client pipe: {0}", pipeName);
using (var pipeStream = new NamedPipeClientStream(pipeName))
{
pipeStream.Connect();
using (var writer = new StreamWriter(pipeStream))
{
StartChildProcess(writer);
}
}
}
else
{
Console.WriteLine("We are admin and not piping, so just run");
StartChildProcess(Console.Out);
Console.WriteLine("Hit any key to end");
Console.ReadKey(intercept: true);
}
}
}
private static bool IsAdministrator()
{
WindowsIdentity identity = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(identity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
private static void StartChildProcess(TextWriter output)
{
var cmd = new Process()
{
StartInfo =
{
FileName = "cmd.exe",
Arguments = "/c ping 8.8.8.8",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true
}
};
cmd.Start();
string procOutput = cmd.StandardOutput.ReadToEnd();
output.Write("Id: {0}, Output:{1}", cmd.Id, procOutput);
}
}
}
答案 2 :(得分:0)
要使用runas
,您必须UseShellExecute
为真,但要使用任何重定向方法,您必须UseShellExecute
为假。你不能同时拥有两者。
如果您需要重定向输出并同时提升,则必须执行以下步骤:
runas
和UseShellExecute = true
启动另一个您控制 1 的流程,以生成提升的流程。 ping.exe
启动UseShellExecute = false
并重定向输出。 1:它可能是你的同一个EXE,但传递一些特殊的命令行参数将它置于这种新模式