如何为子进程降低权限?

17 浏览
0 Comments

如何为子进程降低权限?

我知道如何从一个进程中使用管理员权限启动另一个进程:\n

proc.StartInfo.UseShellExecute = true;
proc.StartInfo.Verb = "runas";

\n其中,proc是一个System.Diagnostics.Process。但是如何做相反的操作呢?\n如果您所在的进程已经具有提升的权限,如何以非管理员权限启动新进程呢?更准确地说,我们需要以与Windows资源管理器相同的权限级别启动新进程,因此,如果UAC被禁用,则不会有任何变化,但是如果UAC被启用,而我们的进程正在以提升的权限运行,我们需要以非提升的方式执行某个操作,因为我们正在创建一个虚拟驱动器,如果使用提升的权限创建,而Windows资源管理器正在以非提升的方式运行,那么它将不会显示出来。\n请随意更改标题为更好的描述,我想不出一个好的描述。

0
0 Comments

孩子进程降低权限的问题在Raymond Chen的博客中得到了解决。他在博客中提到了如何从提升的进程中启动一个非提升的进程,以及反之。通过在GitHub上搜索C#版本的代码,我在Microsoft的Node.js工具的Visual Studio存储库中找到了以下实现:SystemUtilities.cs(ExecuteProcessUnElevated函数)。

为了防止文件消失,以下是文件的内容:

//版权所有(c)Microsoft。版权所有。根据Apache License,Version 2.0许可。有关许可信息,请参阅项目根目录中的License.txt文件。
using System;
using System.Runtime.InteropServices;
namespace Microsoft.NodejsTools.SharedProject
{
    /// 
    /// 用于访问窗口IShell*接口以使用它们来启动一个非提升的进程的实用程序
    /// 
    internal class SystemUtility
    {
        /// 
        /// 我们是提升的,应该启动非提升的进程。我们不能直接创建进程,否则它将变得提升。因此,为了解决这个问题,我们让资源管理器执行进程创建(资源管理器通常以非提升方式运行)。
        /// 
        internal static void ExecuteProcessUnElevated(string process, string args, string currentDirectory = "")
        {
            var shellWindows = (IShellWindows)new CShellWindows();
            //获取桌面窗口
            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);
            //获取资源管理器浏览器
            var serviceGuid = SID_STopLevelBrowser;
            var interfaceGuid = typeof(IShellBrowser).GUID;
            var shellBrowser = (IShellBrowser)serviceProvider.QueryService(ref serviceGuid, ref interfaceGuid);
            //获取资源管理器调度
            var dispatch = typeof(IDispatch).GUID;
            var folderView = (IShellFolderViewDual)shellBrowser.QueryActiveShellView().GetItemObject(SVGIO_BACKGROUND, ref dispatch);
            var shellDispatch = (IShellDispatch2)folderView.Application;
            //使用非提升的调度启动进程
            shellDispatch.ShellExecute(process, args, currentDirectory, string.Empty, SW_SHOWNORMAL);
        }
        /// 
        /// 互操作定义
        /// 
        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);
        }
    }
}

Raymond还发表了一篇后续文章,使用CreateProcess而不是ShellExecute来启动非提升的进程。

0
0 Comments

这个问题的出现是因为需要降低子进程的权限,而解决方法是使用来自Code Project文章的示例代码。该示例代码似乎在RunDll32.exe中进行注入,我对C++/Win32的了解有限,所以没有深入研究实际实现,只是使用了它。经确认,它在Vista和Win7的x86和x64上都能正常工作(至少对我们来说如此,x86和x64需要不同的dll,在安装时进行检查并使用正确的dll)。

代码示例请参考以下链接:High elevation can be bad for your application: How to start a non-elevated process at the end of the installation

0
0 Comments

如何将子进程的权限降低?

问题的原因是想要将子进程的权限降低。解决方法是使用explorer.exe进程来运行子进程,以非提升模式运行。代码示例是使用NSIS安装程序的代码,具体代码如下:

Exec '"$WINDIR\explorer.exe" "$TEMP\MyUnElevatedProcess.exe"'

该方法是将子进程放入临时文件夹,然后使用explorer.exe进程来运行该子进程,以非提升模式运行。然而,该方法无法捕获子进程的标准输出和标准错误输出。该方法也有一个问题,就是子进程会在Windir文件夹下运行,而不是临时文件夹。为了解决这个问题,可以将文件路径设置为相对于Windir文件夹的路径。

如果想在Modern UI安装程序的完成页面上使用复选框,可以使用以下两行代码:

!define MUI_FINISHPAGE_RUN "$WINDIR\explorer.exe"
!define MUI_FINISHPAGE_RUN_PARAMETERS "$TEMP\MyUnElevatedProcess.exe"

需要注意的是,Shell通常使用explorer.exe来运行应用程序,但可以在注册表中更改Shell应用程序,因此最好不要将Shell应用程序硬编码到您用于启动应用程序的代码中。

总结起来,通过使用explorer.exe进程来运行子进程,可以实现将子进程的权限降低。然而,这种方法可能不适用于所有情况,并且可能在未来的Windows更新/版本中不再起作用。

0