C# 您如何降低子进程的权限
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1173630/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you de-elevate privileges for a child process
提问by Davy8
I know how to launch a process with Admin privileges from a process using:
我知道如何使用以下方法从进程中启动具有管理员权限的进程:
proc.StartInfo.UseShellExecute = true;
proc.StartInfo.Verb = "runas";
where proc is a System.Diagnostics.Process. But how does one do the opposite?
其中 proc 是 System.Diagnostics.Process。但是如何做相反的事情呢?
If the process you're in is already elevated, how do you launch the new process without admin privileges? More accurately, we need to launch the new process with the same permission level as Windows Explorer, so no change if UAC is disabled, but if UAC is enabled, but our process is running elevated, we need to perform a certain operation un-elevated because we're creating a virtual drive and if it's created with elevated permissions and Windows explorer is running unelevated it won't show up.
如果你所在的进程已经被提升,你如何在没有管理员权限的情况下启动新进程?更准确地说,我们需要以与Windows资源管理器相同的权限级别启动新进程,因此如果禁用UAC则没有变化,但是如果启用了UAC,但我们的进程正在提升运行,我们需要执行未提升的某些操作因为我们正在创建一个虚拟驱动器,如果它是使用提升的权限创建的,并且 Windows 资源管理器在未提升的情况下运行,它将不会显示。
Feel free to change the title to something better, I couldn't come up with a good description.
随意将标题更改为更好的内容,我无法想出一个好的描述。
采纳答案by Davy8
We ended up using the sample from this Code Project article: High elevation can be bad for your application: How to start a non-elevated process at the end of the installation
我们最终使用了此代码项目文章中的示例:高海拔可能对您的应用程序不利:如何在安装结束时启动非海拔进程
It seems to work so far, I gather it injects into RunDll32.exe, my C++/Win32 is fairly weak so I didn't look too much into the actual implementation, just it's use. Confirmed that it works in Vista and Win7 both x86 and x64 (at least for us, x86 and x64 require different dll's which is checked for at install time and the proper one is used).
到目前为止它似乎可以工作,我认为它注入了 RunDll32.exe,我的 C++/Win32 相当薄弱,所以我没有过多研究实际实现,只是它的使用。确认它适用于 x86 和 x64 的 Vista 和 Win7(至少对我们来说,x86 和 x64 需要不同的 dll,在安装时检查并使用正确的 dll)。
回答by Darin Dimitrov
You can use ProcessStartInfo.UserNameand ProcessStartInfo.Passwordto specify the account you want your process to run under.
您可以使用ProcessStartInfo.UserName和ProcessStartInfo.Password来指定您希望进程在其下运行的帐户。
class Program
{
static void Main(string[] args)
{
var psi = new ProcessStartInfo(@"c:\windows\system32\whoami.exe");
var password = new SecureString();
password.AppendChar('s');
password.AppendChar('e');
password.AppendChar('c');
password.AppendChar('r');
password.AppendChar('e');
password.AppendChar('t');
psi.Password = password;
psi.UserName = "username";
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
var p = new Process();
p.StartInfo = psi;
p.Start();
p.WaitForExit();
Console.WriteLine(p.StandardOutput.ReadToEnd());
}
}
回答by mr.baby123
The solution for you is to use EXPLORER.exe process.
您的解决方案是使用 EXPLORER.exe 进程。
The idea is to run the process in UN-ELEVATED mode, using windows's file explorer process explorer.exe
(info).
Lets say the process that we want to launch is on $TEMP\MyUnElevatedProcess.exe
.
这个想法是使用 Windows 的文件资源管理器进程explorer.exe
( info)在 UN-ELEVATED 模式下运行该进程。假设我们要启动的进程是 on $TEMP\MyUnElevatedProcess.exe
。
So, for NSIS code, I will just write: (but can be run in ANY language)
所以,对于 NSIS 代码,我只会写:(但可以用任何语言运行)
Exec '"$WINDIR\explorer.exe" "$TEMP\MyUnElevatedProcess.exe"'
Example code (using NSIS installer)
示例代码(使用 NSIS 安装程序)
Exec '"$WINDIR\explorer.exe" "$TEMP\MyUnElevatedProcess.exe"'
***code taken from http://mdb-blog.blogspot.com/2013/01/nsis-lunch-program-as-user-from-uac.html
*** 代码取自http://mdb-blog.blogspot.com/2013/01/nsis-lunch-program-as-user-from-uac.html
回答by NtFreX
If you want to start an unelevated process from an elevated one you could copy the access token of the shell process and use it to start a new process.
如果您想从提升的进程启动一个未提升的进程,您可以复制 shell 进程的访问令牌并使用它来启动一个新进程。
public static class UnelevatedProcessStarter
{
public static void Start(string cmdArgs)
{
// 1. Get the shell
var shell = NativeMethods.GetShellWindow();
if (shell == IntPtr.Zero)
{
throw new Exception("Could not find shell window");
}
// 2. Copy the access token of the process
NativeMethods.GetWindowThreadProcessId(shell, out uint shellProcessId);
var hShellProcess = NativeMethods.OpenProcess(0x00000400 /* QueryInformation */, false, (int)shellProcessId);
if (!NativeMethods.OpenProcessToken(hShellProcess, 2 /* TOKEN_DUPLICATE */, out IntPtr hShellToken))
{
throw new Win32Exception();
}
// 3. Dublicate the acess token
uint tokenAccess = 8 /*TOKEN_QUERY*/ | 1 /*TOKEN_ASSIGN_PRIMARY*/ | 2 /*TOKEN_DUPLICATE*/ | 0x80 /*TOKEN_ADJUST_DEFAULT*/ | 0x100 /*TOKEN_ADJUST_SESSIONID*/;
var securityAttributes = new SecurityAttributes();
NativeMethods.DuplicateTokenEx(
hShellToken,
tokenAccess,
ref securityAttributes,
2 /* SecurityImpersonation */,
1 /* TokenPrimary */,
out IntPtr hToken);
// 4. Create a new process with the copied token
var si = new Startupinfo();
si.cb = Marshal.SizeOf(si);
if (!NativeMethods.CreateProcessWithTokenW(
hToken,
0x00000002 /* LogonNetcredentialsOnly */,
null,
cmdArgs,
0x00000010 /* CreateNewConsole */,
IntPtr.Zero,
null,
ref si,
out ProcessInformation _))
{
throw new Win32Exception();
}
}
public class NativeMethods
{
[DllImport("user32.dll")]
public static extern IntPtr GetShellWindow();
[DllImport("user32.dll", SetLastError = true)]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenProcess(int processAccess, bool bInheritHandle, int processId);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool OpenProcessToken(IntPtr processHandle, UInt32 desiredAccess, out IntPtr tokenHandle);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool DuplicateTokenEx(IntPtr hExistingToken, uint dwDesiredAccess,
ref SecurityAttributes lpTokenAttributes,
int impersonationLevel,
int tokenType,
out IntPtr phNewToken);
[DllImport("advapi32", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool CreateProcessWithTokenW(
IntPtr hToken, int dwLogonFlags,
string lpApplicationName, string lpCommandLine,
int dwCreationFlags, IntPtr lpEnvironment,
string lpCurrentDirectory, [In] ref Startupinfo lpStartupInfo, out ProcessInformation lpProcessInformation);
}
[StructLayout(LayoutKind.Sequential)]
public struct ProcessInformation
{
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}
[StructLayout(LayoutKind.Sequential)]
public struct SecurityAttributes
{
public int nLength;
public IntPtr lpSecurityDescriptor;
public int bInheritHandle;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct Startupinfo
{
public Int32 cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwYSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public Int32 dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
}
回答by Paul
Raymond Chen addressed this in his blog:
Raymond Chen 在他的博客中谈到了这一点:
How can I launch an unelevated process from my elevated process and vice versa?
Searching in GitHubfor a C# version of this code, I found the following implementation in Microsoft's Node.js tools for Visual Studiorepository: SystemUtilities.cs(the ExecuteProcessUnElevated
function).
在GitHub 中搜索此代码的 C# 版本,我在 Microsoft 的用于 Visual Studio存储库的Node.js 工具中找到了以下实现:SystemUtilities.cs(ExecuteProcessUnElevated
函数)。
Just in case the file disappears, here's the file's contents:
以防万一文件消失,这里是文件的内容:
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Runtime.InteropServices;
namespace Microsoft.NodejsTools.SharedProject
{
/// <summary>
/// Utility for accessing window IShell* interfaces in order to use them to launch a process unelevated
/// </summary>
internal class SystemUtility
{
/// <summary>
/// We are elevated and should launch the process unelevated. We can't create the
/// process directly without it becoming elevated. So to workaround this, we have
/// explorer do the process creation (explorer is typically running unelevated).
/// </summary>
internal static void ExecuteProcessUnElevated(string process, string args, string currentDirectory = "")
{
var shellWindows = (IShellWindows)new CShellWindows();
// Get the desktop window
object loc = CSIDL_Desktop;
object unused = new object();
int hwnd;
var serviceProvider = (IServiceProvider)shellWindows.FindWindowSW(ref loc, ref unused, SWC_DESKTOP, out hwnd, SWFO_NEEDDISPATCH);
// Get the shell browser
var serviceGuid = SID_STopLevelBrowser;
var interfaceGuid = typeof(IShellBrowser).GUID;
var shellBrowser = (IShellBrowser)serviceProvider.QueryService(ref serviceGuid, ref interfaceGuid);
// Get the shell dispatch
var dispatch = typeof(IDispatch).GUID;
var folderView = (IShellFolderViewDual)shellBrowser.QueryActiveShellView().GetItemObject(SVGIO_BACKGROUND, ref dispatch);
var shellDispatch = (IShellDispatch2)folderView.Application;
// Use the dispatch (which is unelevated) to launch the process for us
shellDispatch.ShellExecute(process, args, currentDirectory, string.Empty, SW_SHOWNORMAL);
}
/// <summary>
/// Interop definitions
/// </summary>
private const int CSIDL_Desktop = 0;
private const int SWC_DESKTOP = 8;
private const int SWFO_NEEDDISPATCH = 1;
private const int SW_SHOWNORMAL = 1;
private const int SVGIO_BACKGROUND = 0;
private readonly static Guid SID_STopLevelBrowser = new Guid("4C96BE40-915C-11CF-99D3-00AA004AE837");
[ComImport]
[Guid("9BA05972-F6A8-11CF-A442-00A0C90A8F39")]
[ClassInterfaceAttribute(ClassInterfaceType.None)]
private class CShellWindows
{
}
[ComImport]
[Guid("85CB6900-4D95-11CF-960C-0080C7F4EE85")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
private interface IShellWindows
{
[return: MarshalAs(UnmanagedType.IDispatch)]
object FindWindowSW([MarshalAs(UnmanagedType.Struct)] ref object pvarloc, [MarshalAs(UnmanagedType.Struct)] ref object pvarlocRoot, int swClass, out int pHWND, int swfwOptions);
}
[ComImport]
[Guid("6d5140c1-7436-11ce-8034-00aa006009fa")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IServiceProvider
{
[return: MarshalAs(UnmanagedType.Interface)]
object QueryService(ref Guid guidService, ref Guid riid);
}
[ComImport]
[Guid("000214E2-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IShellBrowser
{
void VTableGap01(); // GetWindow
void VTableGap02(); // ContextSensitiveHelp
void VTableGap03(); // InsertMenusSB
void VTableGap04(); // SetMenuSB
void VTableGap05(); // RemoveMenusSB
void VTableGap06(); // SetStatusTextSB
void VTableGap07(); // EnableModelessSB
void VTableGap08(); // TranslateAcceleratorSB
void VTableGap09(); // BrowseObject
void VTableGap10(); // GetViewStateStream
void VTableGap11(); // GetControlWindow
void VTableGap12(); // SendControlMsg
IShellView QueryActiveShellView();
}
[ComImport]
[Guid("000214E3-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IShellView
{
void VTableGap01(); // GetWindow
void VTableGap02(); // ContextSensitiveHelp
void VTableGap03(); // TranslateAcceleratorA
void VTableGap04(); // EnableModeless
void VTableGap05(); // UIActivate
void VTableGap06(); // Refresh
void VTableGap07(); // CreateViewWindow
void VTableGap08(); // DestroyViewWindow
void VTableGap09(); // GetCurrentInfo
void VTableGap10(); // AddPropertySheetPages
void VTableGap11(); // SaveViewState
void VTableGap12(); // SelectItem
[return: MarshalAs(UnmanagedType.Interface)]
object GetItemObject(UInt32 aspectOfView, ref Guid riid);
}
[ComImport]
[Guid("00020400-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
private interface IDispatch
{
}
[ComImport]
[Guid("E7A1AF80-4D96-11CF-960C-0080C7F4EE85")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
private interface IShellFolderViewDual
{
object Application { [return: MarshalAs(UnmanagedType.IDispatch)] get; }
}
[ComImport]
[Guid("A4C6892C-3BA9-11D2-9DEA-00C04FB16162")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IShellDispatch2
{
void ShellExecute([MarshalAs(UnmanagedType.BStr)] string File, [MarshalAs(UnmanagedType.Struct)] object vArgs, [MarshalAs(UnmanagedType.Struct)] object vDir, [MarshalAs(UnmanagedType.Struct)] object vOperation, [MarshalAs(UnmanagedType.Struct)] object vShow);
}
}
}