createprocessasuser后.NET应用程序崩溃

时间:2015-07-14 23:48:07

标签: c# crash marshalling createprocess createprocessasuser

我有一个在系统帐户中运行的服务,它应该以用户模式启动应用程序。在c ++中没问题,但在.NET中我有很多。

最后,我复制了当前用户会话(explorer.exe)的用户令牌

应用程序似乎从用户模式开始,但在到达我的代码的第一行之前直接崩溃;)

当我直接或通过我的服务调用流程时,我检查了流程资源管理器的差异。

似乎.Net程序集的加载不起作用,但我不知道为什么(或者唯一的一个是因为我复制了一个非.NET令牌,但是读取所有应用程序启动为非.NET版本和窗口在lload期间检测到它必须加载程序集

我的代码:

var adjustToken = IntPtr.Zero;

        int lastError;
        if (
                        !NativeMethods.OpenProcessToken(
                                                        NativeMethods.GetCurrentProcess(),
                                                        ProcessTools.TokenAdjustPrivileges | ProcessTools.TokenQuery,
                                                        ref adjustToken))
        {
            lastError = Marshal.GetLastWin32Error();
            throw new Exception($"OpenProcessToken() failed, error = {lastError}.");
        }

        try
        {
            Luid luidSeDebugNameValue;
            if (!NativeMethods.LookupPrivilegeValue(null, ProcessTools.SeDebugName, out luidSeDebugNameValue))
            {
                lastError = Marshal.GetLastWin32Error();
                throw new Exception(
                                $"LookupPrivilegeValue() failed, error = {lastError}. SeDebugPrivilege is not available");
            }

            var tokenPrivileges = new TokenPrivileges
            {
                PrivilegeCount = 1,
                Luid = luidSeDebugNameValue,
                Attributes = ProcessTools.SePrivilegeEnabled
            };
            if (
                            !NativeMethods.AdjustTokenPrivileges(
                                                                 adjustToken,
                                                                 false,
                                                                 ref tokenPrivileges,
                                                                 0,
                                                                 IntPtr.Zero,
                                                                 IntPtr.Zero))
            {
                lastError = Marshal.GetLastWin32Error();
                throw new Exception($"AdjustTokenPrivileges() failed, error = {lastError}.");
            }
            else
            {
                var userTokenDup = IntPtr.Zero;
                var token = IntPtr.Zero;

                var processes = Process.GetProcessesByName("explorer");
                var process = ProcessTools.OpenProcess(
                                                       processes.FirstOrDefault(),
                                                       ProcessAccessFlags.All,
                                                       out lastError);

                if (process == IntPtr.Zero)
                {
                    throw new Exception($"Can't open process. Last error = {lastError}.");
                }

                try
                {
                    if (!NativeMethods.OpenProcessToken(process, ProcessTools.TokenDuplicate, ref token))
                    {
                        lastError = Marshal.GetLastWin32Error();
                        throw new Exception($"Can't open process token. Last error = {lastError}.");
                    }

                    var sa = new SecurityAttributes();
                    sa.Length = Marshal.SizeOf(sa);

                    try
                    {
                        if (
                                        !NativeMethods.DuplicateTokenEx(
                                                                        token,
                                                                        ProcessTools.TokenAllAccess,
                                                                        ref sa,
                                                                        (int)
                                                                        SecurityImpersonationLevel
                                                                                        .SecurityImpersonation,
                                                                        (int) TokenType.TokenPrimary,
                                                                        ref userTokenDup))
                        {
                            lastError = Marshal.GetLastWin32Error();
                            throw new Exception($"Can't duplicate process token. Last error = {lastError}.");
                        }

                        var si = new Startupinfo();
                        si.Cbyte = Marshal.SizeOf(si);
                        si.Desktop = @"winsta0\default";

                        var inputHandle =
                            NativeMethods.GetStdHandle(NativeMethods.ConsoleStandardHandle.StandardInputHandle);
                        var outputHandle =
                            NativeMethods.GetStdHandle(NativeMethods.ConsoleStandardHandle.StandardInputHandle);
                        var errHandle =
                            NativeMethods.GetStdHandle(NativeMethods.ConsoleStandardHandle.StandardInputHandle);
                        if (errHandle != IntPtr.Zero)
                        {
                            si.StandardError = errHandle;
                        }

                        if (outputHandle != IntPtr.Zero)
                        {
                            si.StandardOutput = outputHandle;
                        }

                        if (inputHandle != IntPtr.Zero)
                        {
                            si.StandardInput = inputHandle;
                        }

                        const int CreationFlags = ProcessTools.NormalPriorityClass | ProcessTools.CreateNewConsole;
                        var file = new FileInfo(applicationName);
                        var dir = file.Directory?.FullName;

                        ProcessInformation procInfo;
                        var result = NativeMethods.CreateProcessAsUser(
                                                                       userTokenDup,
                                                                       file.FullName,
                                                                       arguments,
                                                                       ref sa,
                                                                       ref sa,
                                                                       false,
                                                                       CreationFlags,
                                                                       IntPtr.Zero,
                                                                       dir,
                                                                       ref si,
                                                                       out procInfo);
                        lastError = Marshal.GetLastWin32Error();

                        NativeMethods.CloseHandle(userTokenDup);

                        if (!result)
                        {
                            throw new Exception(
                                            $"Could not create process in user interactive mode. Last error = {lastError}.");
                        }

                        if (milliseconds == 0)
                        {
                            return;
                        }

                        var res = NativeMethods.WaitForSingleObject(procInfo.Process, milliseconds);

                        if (res == ProcessTools.WaitTimeOut)
                        {
                            throw new Exception(
                                            $"Process not started within = {milliseconds} seconds.");
                        }


                    }
                    finally
                    {
                        NativeMethods.CloseHandle(token);
                    }
                }
                finally
                {
                    NativeMethods.CloseHandle(process);
                }
            }
        }
        finally
        {
            NativeMethods.CloseHandle(adjustToken);
        }

0 个答案:

没有答案