0

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

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

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

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

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

1 回答 1

0

在转储中我看不到太多,只是未处理的异常过滤器正在调用 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
---------
于 2015-07-15T01:25:04.193 回答