Пример #1
0
 private static bool ProcessOwnedByUser(int pid, string userName, bool ignoreCase = false)
 {
     if (userName == null)
     {
         return(false);
     }
     try
     {
         using (AutoDisposeHandle processHandle = OpenProcess(pid))
             using (AutoDisposeHandle processToken = OpenProcessToken(processHandle))
                 using (WindowsIdentity identity = new WindowsIdentity(processToken))
                 {
                     string owner            = identity.Name;
                     int    userNameIdxSlash = userName.IndexOf('\\');
                     if (userNameIdxSlash == -1)             // Specified user name did not contain a domain name, so we should remove it from the [owner] string.
                     {
                         owner = owner.Substring(owner.IndexOf('\\') + 1);
                     }
                     return(string.Compare(owner, userName, ignoreCase) == 0);
                 }
     }
     catch
     {
         return(false);
     }
 }
Пример #2
0
        private static int CreateProcessAsUser(string executablePath, string commandLine, string workingDirectory, IntPtr userToken)
        {
            using (AutoDisposeHandle environmentVariables = CreateEnvironmentBlock(userToken))
            {
                if (environmentVariables == null)
                {
                    return(-1);
                }

                NativeMethods.STARTUPINFO startupInformation = new NativeMethods.STARTUPINFO();
                startupInformation.length     = Marshal.SizeOf(typeof(NativeMethods.STARTUPINFO));
                startupInformation.desktop    = "Winsta0\\Default";
                startupInformation.showWindow = (short)NativeMethods.WindowShowStyle.ShowNoActivate;
                NativeMethods.PROCESS_INFORMATION processInformation = new NativeMethods.PROCESS_INFORMATION();
                try
                {
                    bool result = NativeMethods.CreateProcessAsUser
                                  (
                        userToken,
                        executablePath,
                        commandLine,
                        IntPtr.Zero,
                        IntPtr.Zero,
                        false,
                        (uint)(NativeMethods.CreateProcessFlags.DETACHED_PROCESS | NativeMethods.CreateProcessFlags.CREATE_UNICODE_ENVIRONMENT),
                        environmentVariables,
                        workingDirectory,
                        ref startupInformation,
                        ref processInformation
                                  );
                    if (!result)
                    {
                        Win32Helper.ThrowLastWin32Error("Unable to start process \"" + executablePath + "\"");
                    }
                    return(processInformation.processID);
                }
                finally
                {
                    if (processInformation.processHandle != IntPtr.Zero)
                    {
                        try
                        {
                            NativeMethods.CloseHandle(processInformation.processHandle);
                        }
                        catch { }
                    }
                    if (processInformation.threadHandle != IntPtr.Zero)
                    {
                        try
                        {
                            NativeMethods.CloseHandle(processInformation.threadHandle);
                        }
                        catch { }
                    }
                }
            }
        }
Пример #3
0
        private static AutoDisposeHandle CreateEnvironmentBlock(IntPtr userToken)
        {
            IntPtr handle;

            if (NativeMethods.CreateEnvironmentBlock(out handle, userToken, false))
            {
                return(AutoDisposeHandle.Create(handle, h => NativeMethods.DestroyEnvironmentBlock(h)));
            }
            return(null);
        }
Пример #4
0
        private static AutoDisposeHandle DuplicateTokenEx(IntPtr originalToken)
        {
            IntPtr handle;

            if (NativeMethods.DuplicateTokenEx(originalToken, (uint)TokenAccessLevels.MaximumAllowed, IntPtr.Zero, NativeMethods.SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, NativeMethods.TOKEN_TYPE.TokenPrimary, out handle))
            {
                return(AutoDisposeHandle.Create(handle, h => NativeMethods.CloseHandle(h)));
            }
            return(null);
        }
Пример #5
0
        private static AutoDisposeHandle OpenProcessToken(IntPtr processHandle)
        {
            IntPtr handle;

            if (NativeMethods.OpenProcessToken(processHandle, (uint)TokenAccessLevels.MaximumAllowed, out handle))
            {
                return(AutoDisposeHandle.Create(handle, h => NativeMethods.CloseHandle(h)));
            }
            return(null);
        }
Пример #6
0
 private static bool UserIsMatch(int pid, WellKnownSidType type)
 {
     try
     {
         using (AutoDisposeHandle processHandle = OpenProcess(pid))
             using (AutoDisposeHandle processToken = OpenProcessToken(processHandle))
                 using (WindowsIdentity identity = new WindowsIdentity(processToken))
                     return(identity.User.IsWellKnown(type));
     }
     catch
     {
         return(false);
     }
 }
Пример #7
0
 /// <summary>
 /// Returns the name of the user which owns the specified process, including domain name. e.g. "NT AUTHORITY\SYSTEM"
 /// </summary>
 /// <param name="pid">The ID of the process.</param>
 /// <returns></returns>
 public static string GetUserWhichOwnsProcess(int pid)
 {
     try
     {
         using (AutoDisposeHandle processHandle = OpenProcess(pid))
             using (AutoDisposeHandle processToken = OpenProcessToken(processHandle))
                 using (WindowsIdentity identity = new WindowsIdentity(processToken))
                     return(identity.Name);
     }
     catch
     {
         return(null);
     }
 }
Пример #8
0
        /// <summary>
        /// Attempts to start the specified interactive process in the current console session (a.k.a. local desktop visible on the computer's monitor) by impersonating the security context of another process that is running in that session.  This method can be called from a background service to start an interactive process.  Returns the process ID of the executed program, or -1 if there was a problem. May also throw an exception.
        /// </summary>
        /// <param name="executablePath">This can be null if the first token in the [commandLine] argument is the executable path.</param>
        /// <param name="commandLine">Sometimes, for unknown reasons, the first argument in this command line can be dropped.  This may be avoided by passing null for [executablePath] and including the executable path as the first token of [commandLine].</param>
        /// <param name="workingDirectory"></param>
        /// <param name="execArgs">Optional arguments to control process selection.</param>
        /// <returns>The process ID of the executed program, or -1 if there was a problem. May also throw an exception.</returns>
        /// <returns></returns>
        public static int ExecuteInteractive(string executablePath, string commandLine, string workingDirectory, ProcessExecuteArgs execArgs = null)
        {
            if (execArgs == null)
            {
                execArgs = ProcessExecuteArgs.Default();
            }
            if (execArgs.requiredSessionID == -1)
            {
                execArgs.requiredSessionID = GetConsoleSessionId();
            }
            if (execArgs.requiredSessionID == -1)
            {
                return(-1);                // No session currently attached to the console.
            }
            // In order to be able to open a process when no user is logged in, we will use an
            // existing process from the active console session as a sort of template.

            int templateProcessId = -1;

            if (templateProcessId == -1 && (execArgs.flags & ProcessExecuteFlags.ImpersonateExplorer) > 0)
            {
                // First, we will try explorer.exe
                // GetProcessesByName uses case-sensitive matching.
                templateProcessId = Process.GetProcessesByName("explorer").FirstOrDefault(p => IsSuitableProcess(p, execArgs))?.Id ?? -1;
                if (templateProcessId != -1)
                {
                    Logger.Info("Will impersonate explorer.exe for session " + execArgs.requiredSessionID);
                }
            }

            if (templateProcessId == -1 && (execArgs.flags & ProcessExecuteFlags.ImpersonateWinlogon) > 0)
            {
                // Next, we will try winlogon.exe, though it is said a process impersonating winlogon is killed by the system after about 10 minutes.
                templateProcessId = Process.GetProcessesByName("winlogon").FirstOrDefault(p => IsSuitableProcess(p, execArgs))?.Id ?? -1;
                if (templateProcessId != -1)
                {
                    Logger.Info("Will impersonate winlogon.exe for session " + execArgs.requiredSessionID);
                }
            }

            if (templateProcessId == -1 && (execArgs.flags & ProcessExecuteFlags.ImpersonateAnyProcess) > 0)
            {
                // If the above scans failed, try any process that meets the other criteria.
                templateProcessId = Process.GetProcesses().FirstOrDefault(p => IsSuitableProcess(p, execArgs))?.Id ?? -1;
                if (templateProcessId != -1)
                {
                    Logger.Info("Will impersonate an arbitrary local system process for session " + execArgs.requiredSessionID);                     // Don't log the process name, as that could potentially reveal private information if a log is shared.
                }
            }

            if (templateProcessId == -1)
            {
                return(-1);                // No process could be found to use as a template.
            }
            // Open Process
            using (AutoDisposeHandle cloneableProcHandle = OpenProcess(templateProcessId))
            {
                // Get token from process
                using (AutoDisposeHandle originalToken = OpenProcessToken(cloneableProcHandle))
                {
                    if (originalToken == null)
                    {
                        return(-1);
                    }

                    // Clone the token
                    using (AutoDisposeHandle duplicatedToken = DuplicateTokenEx(originalToken))
                    {
                        if (duplicatedToken == null)
                        {
                            return(-1);
                        }

                        // Try to start process
                        return(CreateProcessAsUser(executablePath, commandLine, workingDirectory, duplicatedToken));
                    }
                }
            }
        }
Пример #9
0
 private static AutoDisposeHandle OpenProcess(int templateProcessId)
 {
     return(AutoDisposeHandle.Create(NativeMethods.OpenProcess(NativeMethods.ProcessAccessFlags.All, false, templateProcessId), h => NativeMethods.CloseHandle(h)));
 }