c# - createprocessasuser 后 .NET 应用程序崩溃

标签 c# crash marshalling createprocess createprocessasuser

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

最后,我复制当前用户 session 的用户 token (explorer.exe)

应用程序似乎以用户模式启动,但在到达我的代码的第一行之前就直接崩溃​​了;)

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

似乎 .Net 程序集的加载不起作用,但我不知道为什么(或者唯一的一个是因为我复制了一个非 .NET token ,但读取所有应用程序作为非 .NET 版本和 Windows 启动在 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);
        }

最佳答案

在转储中我看不到太多,只看到未处理的异常过滤器正在调用 WER 服务并等待用户输入。没有其他线程正在运行

FAULTING_IP: 
+0
00000000 ??              ???

EXCEPTION_RECORD:  ffffffff -- (.exr 0xffffffffffffffff)
ExceptionAddress: 00000000
   ExceptionCode: 80000003 (Break instruction exception)
  ExceptionFlags: 00000000
NumberParameters: 0

CONTEXT:  00000000 -- (.cxr 0x0;r)
eax=00000000 ebx=00000000 ecx=00000001 edx=00000000 esi=00000003 edi=00000003
eip=771dd72c esp=00a7e3bc ebp=00a7e53c iopl=0         nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
ntdll!NtWaitForMultipleObjects+0xc:
771dd72c c21400          ret     14h

FAULTING_THREAD:  000019e4

DEFAULT_BUCKET_ID:  WRONG_SYMBOLS

PROCESS_NAME:  ReleaseManager.exe

ADDITIONAL_DEBUG_TEXT:  
You can run '.symfix; .reload' to try to fix the symbol path and load symbols.

MODULE_NAME: ntdll

FAULTING_MODULE: 771a0000 ntdll

DEBUG_FLR_IMAGE_TIMESTAMP:  5308893d

ERROR_CODE: (NTSTATUS) 0x80000003 - {AUSNAHME}  Haltepunkt  Im Quellprogramm wurde ein Haltepunkt erreicht.

EXCEPTION_CODE: (HRESULT) 0x80000003 (2147483651) - Mindestens ein Argument ist ung ltig.

APP:  releasemanager.exe

ANALYSIS_VERSION: 6.3.9600.16384 (debuggers(dbg).130821-1623) x86fre

PRIMARY_PROBLEM_CLASS:  WRONG_SYMBOLS

BUGCHECK_STR:  APPLICATION_FAULT_WRONG_SYMBOLS

LAST_CONTROL_TRANSFER:  from 75699188 to 771dd72c

STACK_TEXT:  
WARNING: Stack unwind information not available. Following frames may be wrong.
00a7e53c 75699188 00000000 00a7e580 00000000 ntdll!NtWaitForMultipleObjects+0xc
00a7e558 756eb399 00000003 00a7e580 00000000 kernel32!WaitForMultipleObjects+0x19
00a7e994 756eae92 00000000 00000001 00000000 kernel32!WerpLaunchAeDebug+0x1956
00a7e9ac 75b996fd 00a7ea68 00000001 d8e06f96 kernel32!WerpLaunchAeDebug+0x144f
00a7ea38 7724366d 00a7ea68 771df7b4 fffffffe KERNELBASE!UnhandledExceptionFilter+0x1d2
00a7f968 771ea8a1 ffffffff 771df69b 00000000 ntdll!LdrSetAppCompatDllRedirectionCallback+0x1411e
00a7f978 00000000 7460bb40 ff21e000 00000000 ntdll!RtlInitializeExceptionChain+0x5a


STACK_COMMAND:  ~0s; .ecxr ; kb

FOLLOWUP_IP: 
ntdll!NtWaitForMultipleObjects+c
771dd72c c21400          ret     14h

SYMBOL_STACK_INDEX:  0

SYMBOL_NAME:  ntdll!NtWaitForMultipleObjects+c

FOLLOWUP_NAME:  MachineOwner

IMAGE_NAME:  ntdll.dll

BUCKET_ID:  WRONG_SYMBOLS

FAILURE_BUCKET_ID:  WRONG_SYMBOLS_80000003_ntdll.dll!NtWaitForMultipleObjects

ANALYSIS_SOURCE:  UM

FAILURE_ID_HASH_STRING:  um:wrong_symbols_80000003_ntdll.dll!ntwaitformultipleobjects

FAILURE_ID_HASH:  {b36f8a59-3ae7-2592-4531-80a59fca9974}

Followup: MachineOwner
---------

关于c# - createprocessasuser 后 .NET 应用程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31419257/

相关文章:

java - 保留 在 xml 编码期间

C# - 如何编码 LPWSTR 数组?

c# - 表单例份验证 没有 ASP.net 只是 C# 和 MYSQL

c# - 防止 ObsoleteAttribute 警告冒泡调用堆栈

c# - Parallel.ForEach 期间使用的线程数

android - 在Helpshift Android中崩溃

windows-phone-7 - Windows Phone 7 崩溃

c# - 折叠面板 JavaScript 问题

ipad - 调整ipad大小时动力学js崩溃

c++ - 编码(marshal)处理结构(包含数组)作为返回值