C# 将权限启动新进程(CreateProcessWithTokenW)

网上有很多CreateProcessAsUser的方法。但是这个受限于执行者的权限,如果执行者是RunAsAdministrator,则会出现ERROR 1314(权限不足)的问题。所以采用了CreateProcessWithTokenW方法

public class RunProcessAsCommonUser
    {
        #region 自己根据网上改的简单粗暴版
        [StructLayout(LayoutKind.Sequential)]
        internal struct PROCESS_INFORMATION
        {
            public IntPtr hProcess;
            public IntPtr hThread;
            public uint dwProcessId;
            public uint dwThreadId;
        }



        [StructLayout(LayoutKind.Sequential)]
        internal struct SECURITY_ATTRIBUTES
        {
            public uint nLength;
            public IntPtr lpSecurityDescriptor;
            public bool bInheritHandle;
        }


        [StructLayout(LayoutKind.Sequential)]
        public struct STARTUPINFO
        {
            public uint cb;
            public string lpReserved;
            public string lpDesktop;
            public string lpTitle;
            public uint dwX;
            public uint dwY;
            public uint dwXSize;
            public uint dwYSize;
            public uint dwXCountChars;
            public uint dwYCountChars;
            public uint dwFillAttribute;
            public uint dwFlags;
            public short wShowWindow;
            public short cbReserved2;
            public IntPtr lpReserved2;
            public IntPtr hStdInput;
            public IntPtr hStdOutput;
            public IntPtr hStdError;

        }

        internal enum SECURITY_IMPERSONATION_LEVEL
        {
            SecurityAnonymous,
            SecurityIdentification,
            SecurityImpersonation,
            SecurityDelegation
        }

        internal enum TOKEN_TYPE
        {
            TokenPrimary = 1,
            TokenImpersonation
        }


        [DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx", SetLastError = true)]
        private static extern bool DuplicateTokenEx(
            IntPtr hExistingToken,
            uint dwDesiredAccess,
            ref SECURITY_ATTRIBUTES lpThreadAttributes,
            Int32 ImpersonationLevel,
            Int32 dwTokenType,
            ref IntPtr phNewToken);


        [DllImport("advapi32.dll", SetLastError = true)]
        private static extern bool OpenProcessToken(
            IntPtr ProcessHandle,
            UInt32 DesiredAccess,
            ref IntPtr TokenHandle);



        /// <summary>
        /// 具体参考https://docs.microsoft.com/zh-cn/windows/desktop/api/winbase/nf-winbase-createprocesswithtokenw
        /// </summary>
        /// <param name="hToken">用户的主令牌的句柄</param>
        /// <param name="dwLogonFlags">登录选项</param>
        /// <param name="lpApplicationName">模块名称</param>
        /// <param name="lpCommandLine">要执行的命令行,注意这里和上面的参数的区别</param>
        /// <param name="dwCreationFlags">控制进程创建方式的标志,一般情况下CREATE_UNICODE_ENVIRONMENT 0x00000400就行</param>
        /// <param name="lpEnvironment">如果此参数为NULL,则新进程使用从lpUsername指定的用户的配置文件创建的环境</param>
        /// <param name="lpCurrentDirectory">如果此参数为NULL,则新进程将具有与调用进程相同的当前驱动器和目录</param>
        /// <param name="lpStartupInfo"></param>
        /// <param name="lpProcessInformation"></param>
        /// <returns></returns>
        [DllImport("advapi32.dll", EntryPoint = "CreateProcessWithTokenW", SetLastError = true,
                                 CharSet = CharSet.Unicode,
                                 CallingConvention = CallingConvention.StdCall)]
        private extern static bool CreateProcessWithTokenW(
         IntPtr hToken,
         uint dwLogonFlags,
         String lpApplicationName,
         String lpCommandLine,
         uint dwCreationFlags,
         IntPtr lpEnvironment,
         String lpCurrentDirectory,
         ref STARTUPINFO lpStartupInfo,
         out PROCESS_INFORMATION lpProcessInformation);
        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool CloseHandle(
            IntPtr hObject);

        private const uint TOKEN_DUPLICATE = 0x0002;
        private const int GENERIC_ALL_ACCESS = 0x10000000;

        public const uint LOGON_WITH_PROFILE = 00000001;
        public const uint NORMAL_PRIORITY_CLASS = 0x00000020;
        private const uint CREATE_UNICODE_ENVIRONMENT = 0x00000400;

        /// <summary>
        /// 进程的路径
        /// </summary>
        /// <param name="processpath"></param>
        public static void CreateProcess(string processpath)
        {
            IntPtr token = IntPtr.Zero;
            Process[] ps = Process.GetProcessesByName("explorer");
            int processId = -1;//=processId 
            if (ps.Length > 0)
            {
                processId = ps[0].Id;
            }
            bool result = false;
            Process p = Process.GetProcessById(processId);
            OpenProcessToken(p.Handle, TOKEN_DUPLICATE, ref token);
            CloseHandle(p.Handle);
            IntPtr primaryToken = IntPtr.Zero;
            SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
            sa.nLength = (uint)Marshal.SizeOf(sa);
            result = DuplicateTokenEx(
                    token,
                    GENERIC_ALL_ACCESS,//使用允许所有权限,否则会报error:5的错误
                    ref sa,
                    (int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
                    (int)TOKEN_TYPE.TokenPrimary,
                    ref primaryToken);
            if (result == false)
            {
                int error = Marshal.GetLastWin32Error();
                string message = String.Format("DuplicateTokenEx Error: {0}", error);
                Debug.WriteLine(message);

            }
            CloseHandle(token);

            PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
            STARTUPINFO si = new STARTUPINFO();
            result = CreateProcessWithTokenW(
               primaryToken,
               LOGON_WITH_PROFILE,
               null,
               processpath,
               NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT,
               IntPtr.Zero,
               null,
               ref si,
               out pi);
            if (result == false)
            {
                int error = Marshal.GetLastWin32Error();
                string message = String.Format("CreateProcessAsUser Error: {0}", error);
                Debug.WriteLine(message);

            }
        }
        #endregion

    }

参考文档

CreateProcessWithTokenW介绍

https://docs.microsoft.com/zh-cn/windows/desktop/api/winbase/nf-winbase-createprocesswithtokenw

DuplicateTokenEx介绍(注意权限那里)

https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-duplicatetokenex

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值