Пример #1
0
        /// <summary>
        ///     Sets the period of time to wait for the associated process to exit, and blocks the current thread of execution
        ///     until the time has elapsed or the process has exited.
        /// </summary>
        /// <param name="milliseconds">
        ///     The amount of time, in milliseconds, to wait for the associated process to exit. A value of
        ///     0 specifies an immediate return, and a value of -1 specifies an infinite wait.
        /// </param>
        /// <returns>true if the associated process has exited; otherwise, false.</returns>
        public bool WaitForExit(int milliseconds)
        {
            bool exited;

            using var handle = ProcessNative.OpenProcessHandle(ProcessNative.ProcessAccessFlags.Synchronize, ProcessId);
            if (handle.IsInvalid)
            {
                exited = true;
            }
            else
            {
                using var processWaitHandle = new ProcessWaitHandle(handle);
                if (processWaitHandle.WaitOne(milliseconds, false))
                {
                    exited    = true;
                    _signaled = true;

                    if (ProcessNative.GetExitCodeProcess(handle, out var exitCode))
                    {
                        ExitCode = (int)exitCode;
                    }
                }
                else
                {
                    exited    = false;
                    _signaled = false;
                }
            }

            if (exited)
            {
                RaiseOnExited();
            }
            return(exited);
        }
Пример #2
0
 /// <summary>
 ///     Creates a new <see cref="ProcessHook"/> instance from the specified <paramref name="processId"/>.
 /// </summary>
 /// <param name="processId">The ID of the running process.</param>
 /// <exception cref="UnauthorizedAccessException">
 ///     Thrown when the AppDomain lacks the necessary elevation to obtain a
 ///     handle on the target process.
 /// </exception>
 public ProcessHook(int processId)
 {
     ProcessId = processId;
     _handle   = ProcessNative.OpenProcessHandle(ProcessNative.ProcessAccessFlags.QueryLimitedInformation | ProcessNative.ProcessAccessFlags.Synchronize, processId);
     if (_handle.IsInvalid)
     {
         throw new UnauthorizedAccessException($"Unable to access handle of process: {Marshal.GetLastWin32Error()}");
     }
 }
Пример #3
0
        /// <summary>
        ///     Retrieves the process ID of Windows Logon component for the specified session identifier.
        /// </summary>
        /// <param name="sessionId">The ID of the session winlogon.exe should be running in.</param>
        /// <returns>The system-unique identifier of the Windows Logon component. If this function fails it returns zero.</returns>
        private static int GetWinLogonProcessId(uint sessionId)
        {
            const string winLogonName = "winlogon";

            foreach (var process in ProcessNative.GetProcesses())
            {
                if (process.Name.Equals(winLogonName) && ProcessNative.ProcessIdToSessionId((uint)process.Id, out var winLogonSessionId) && winLogonSessionId == sessionId)
                {
                    return(process.Id);
                }
            }
            return(0);
        }
Пример #4
0
 /// <summary>
 ///     Creates a read-only record of the provided process info.
 /// </summary>
 /// <param name="id">The system-unique identifier of the process.</param>
 /// <param name="parentProcessId">The system-unique identifier of the process object that created the current process.</param>
 /// <param name="image">The name of the executable belonging to the process.</param>
 /// <param name="commandLine">The command-line string passed to the process.</param>
 /// <param name="workingDirectory">The current working directory of the process.</param>
 /// <param name="creationTime">The time at which the process object was created on the system.</param>
 public ProcessInfo(int id,
                    int parentProcessId,
                    string image,
                    string commandLine,
                    string workingDirectory,
                    long creationTime)
 {
     Id = id;
     ParentProcessId  = parentProcessId;
     Image            = image;
     CommandLine      = commandLine;
     WorkingDirectory = workingDirectory;
     Name             = Path.GetFileNameWithoutExtension(Image);
     CreationDate     = DateTime.FromFileTime(creationTime);
     if (ProcessNative.ProcessIdToSessionId((uint)Id, out var sessionId))
     {
         SessionId = (int)sessionId;
     }
 }
Пример #5
0
        /// <summary>
        ///     Creates a new process object with the privileges of LocalSystem in the interactive desktop session.
        /// </summary>
        /// <param name="info">
        ///     The <see cref="WardenStartInfo"/> that contains the information that is used to start the process,
        ///     including the PackageFamilyName, ApplicationId, and any command-line arguments.
        /// </param>
        /// <returns>A <see cref="WardenProcess"/> instance that is associated with the created process.</returns>
        internal static WardenProcess?AsLocalSystem(WardenStartInfo info)
        {
            var environmentBlockHandle = IntPtr.Zero;
            var startInfo          = new StartupInfo();
            var processInformation = new ProcessInformation();

            startInfo.cb = Marshal.SizeOf <StartupInfo>();
            try
            {
                if (!TryGetInteractiveUserToken(out var sessionId, out var interactiveUserToken))
                {
                    throw new Win32Exception("GetSessionUserToken failed.");
                }

                // By default CreateProcessAsUser creates a process on a non-interactive window station, meaning
                // the window station has a desktop that is invisible and the process is incapable of receiving
                // user input. To remedy this we set the lpDesktop parameter to indicate we want to enable user
                // interaction with the new process.
                startInfo.wShowWindow = (short)SW.SW_SHOW;
                startInfo.lpDesktop   = InteractiveWindowStation;

                using var registryHandle = LoadUserProfile((int)sessionId, interactiveUserToken, out _);
                if (registryHandle.IsInvalid)
                {
                    throw new Win32Exception("LoadUserProfile failed.");
                }
                // copy the users env block
                if (!CreateEnvironmentBlock(ref environmentBlockHandle, interactiveUserToken, false))
                {
                    throw new Win32Exception("CreateEnvironmentBlock failed.");
                }

                var logonProcessId = GetWinLogonProcessId(sessionId);
                if (logonProcessId == 0)
                {
                    throw new Win32Exception($"Unable to find the WinLogon process ID for session '{sessionId}'.");
                }

                using var processHandle = ProcessNative.OpenProcessHandle(ProcessNative.ProcessAccessFlags.MaximumAllowed, logonProcessId);
                if (processHandle.IsInvalid)
                {
                    throw new Win32Exception("Unable to obtain a valid handle for winlogon.exe");
                }
                if (!ProcessNative.OpenProcessToken(processHandle, TOKEN_ALL_ACCESS, out var processToken))
                {
                    throw new Win32Exception("Unable to open the process token for winlogon.exe");
                }

                // ReSharper disable once UseObjectOrCollectionInitializer
                var securityAttributes = new SecurityAttributes();
                securityAttributes.Length = Marshal.SizeOf <SecurityAttributes>();


                // copy the access token of the explorer process; the newly created token will be a primary token
                if (!DuplicateTokenEx(processToken, MAXIMUM_ALLOWED, securityAttributes, SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, TokenType.Primary, out var winLogonToken))
                {
                    throw new Win32Exception("Unable to duplicate the winlogon.exe process token");
                }

                const int creationFlags = CREATE_UNICODE_ENVIRONMENT | DETACHED_PROCESS;
                if (!CreateProcessAsUser(winLogonToken,
                                         info.FileName,
                                         info.Arguments,
                                         securityAttributes,
                                         securityAttributes,
                                         false,
                                         creationFlags,
                                         environmentBlockHandle,
                                         info.WorkingDirectory,
                                         ref startInfo,
                                         out processInformation))
                {
                    throw new Win32Exception($"CreateProcessAsUserW failed: {Marshal.GetLastWin32Error()}");
                }
                UnloadUserProfile(interactiveUserToken, registryHandle);
                return(WardenProcess.GetProcessById(processInformation.ProcessId, info.Track, info.FilteredImages));
            }
            finally
            {
                DestroyEnvironmentBlock(environmentBlockHandle);
                CloseHandle(processInformation.ThreadHandle);
                CloseHandle(processInformation.ProcessHandle);
                CloseHandle(startInfo.hStdError);
                CloseHandle(startInfo.hStdInput);
                CloseHandle(startInfo.hStdOutput);
                CloseHandle(startInfo.lpReserved2);
            }
        }