Esempio n. 1
0
        public Task <int> Execute()
        {
            Native.ConsoleApi.FreeConsole();
            if (!Native.ConsoleApi.AttachConsole(-1))
            {
                Native.ConsoleApi.AllocConsole();
                Logger.Instance.Log($"Failed to attach console.\r\n{new Win32Exception().ToString()}", LogLevel.Error);
            }

            var app  = CommandToRun.First();
            var args = string.Join(" ", CommandToRun.Skip(1).ToArray());

            if (InputArguments.IntegrityLevel.HasValue &&
                (int)InputArguments.IntegrityLevel != ProcessHelper.GetCurrentIntegrityLevel() &&
                Environment.GetEnvironmentVariable("gsudoAttachRun") != "1")
            {
                Environment.SetEnvironmentVariable("gsudoAttachRun", "1"); // prevents infinite loop on machines with UAC disabled.

                var process = ProcessFactory.StartAttachedWithIntegrity(
                    InputArguments.GetIntegrityLevel(), app, args, Directory.GetCurrentDirectory(), false, true);

                process.GetProcessWaitHandle().WaitOne();

                if (ProcessApi.GetExitCodeProcess(process, out var exitCode))
                {
                    return(Task.FromResult(exitCode));
                }
            }
            else
            {
                Helpers.ProcessFactory.StartAttached(app, args).WaitForExit();
            }

            return(Task.FromResult(0));
        }
Esempio n. 2
0
        private static int RunWithoutService(string exeName, string args, ElevationRequest elevationRequest)
        {
            Logger.Instance.Log("Already running as the specified user/permission-level. Running in-process...", LogLevel.Debug);
            var sameIntegrity = (int)InputArguments.GetIntegrityLevel() == ProcessHelper.GetCurrentIntegrityLevel();

            // No need to escalate. Run in-process

            if (!string.IsNullOrEmpty(elevationRequest.Prompt))
            {
                Environment.SetEnvironmentVariable("PROMPT", Environment.ExpandEnvironmentVariables(elevationRequest.Prompt));
            }

            if (sameIntegrity)
            {
                if (elevationRequest.NewWindow)
                {
                    using (var process = ProcessFactory.StartDetached(exeName, args, Environment.CurrentDirectory, false))
                    {
                        if (elevationRequest.Wait)
                        {
                            process.WaitForExit();
                            var exitCode = process.ExitCode;
                            Logger.Instance.Log($"Process exited with code {exitCode}", exitCode == 0 ? LogLevel.Debug : LogLevel.Info);
                            return(exitCode);
                        }
                        return(0);
                    }
                }
                else
                {
                    using (Process process = ProcessFactory.StartAttached(exeName, args))
                    {
                        process.WaitForExit();
                        var exitCode = process.ExitCode;
                        Logger.Instance.Log($"Process exited with code {exitCode}", exitCode == 0 ? LogLevel.Debug : LogLevel.Info);
                        return(exitCode);
                    }
                }
            }
            else // lower integrity
            {
                var p = ProcessFactory.StartAttachedWithIntegrity(InputArguments.GetIntegrityLevel(), exeName, args, elevationRequest.StartFolder, InputArguments.NewWindow, !InputArguments.NewWindow);
                if (p == null || p.IsInvalid)
                {
                    return(Constants.GSUDO_ERROR_EXITCODE);
                }

                if (elevationRequest.Wait)
                {
                    ProcessHelper.GetProcessWaitHandle(p.DangerousGetHandle()).WaitOne();
                    ProcessApi.GetExitCodeProcess(p, out var exitCode);
                    Logger.Instance.Log($"Process exited with code {exitCode}", exitCode == 0 ? LogLevel.Debug : LogLevel.Info);
                    return(exitCode);
                }

                return(0);
            }
        }
Esempio n. 3
0
 private static void SetRequestPrompt(ElevationRequest elevationRequest)
 {
     if ((int)InputArguments.GetIntegrityLevel() < (int)IntegrityLevel.High)
         elevationRequest.Prompt = Environment.GetEnvironmentVariable("PROMPT", EnvironmentVariableTarget.User) ?? Environment.GetEnvironmentVariable("PROMPT", EnvironmentVariableTarget.Machine) ?? "$P$G";
     else if (elevationRequest.Mode != ElevationRequest.ConsoleMode.Piped || InputArguments.NewWindow)
         elevationRequest.Prompt = Settings.Prompt;
     else
         elevationRequest.Prompt = Settings.PipedPrompt;
 }
Esempio n. 4
0
        private static bool IsRunningAsDesiredUser()
        {
            if (InputArguments.RunAsSystem && !WindowsIdentity.GetCurrent().IsSystem)
                return false;

            if ((int)InputArguments.GetIntegrityLevel() != ProcessHelper.GetCurrentIntegrityLevel())
                return false;

            return true;
        }
Esempio n. 5
0
        public Task <int> Execute()
        {
            var elevationRequest = new ElevationRequest()
            {
                IntegrityLevel  = InputArguments.GetIntegrityLevel(),
                TargetProcessId = ProcessId,
            };

            TokenSwitcher.ReplaceProcessToken(elevationRequest);
            return(Task.FromResult(0));
        }
Esempio n. 6
0
        private static bool IsElevationRequired()
        {
            if (InputArguments.RunAsSystem && !WindowsIdentity.GetCurrent().IsSystem)
                return true;

            var integrityLevel = InputArguments.GetIntegrityLevel();

            if (integrityLevel == IntegrityLevel.MediumRestricted)
                return true;

            return (int)integrityLevel > ProcessHelper.GetCurrentIntegrityLevel();
        }
Esempio n. 7
0
        public static string GetPipeName(string connectingUser, int connectingPid)
        {
            if (connectingPid < 0)
            {
                connectingPid = 0;
            }
            string integrity = InputArguments.GetIntegrityLevel().ToString();
            var    data      = $"{connectingUser}_{connectingPid}";

#if !DEBUG
            data = GetHash(data);
#endif
            return($"{GetPipePrefix()}_{data}");
        }
Esempio n. 8
0
 // Enforce SecurityEnforceUacIsolation
 private void AdjustUacIsolationRequest(ElevationRequest elevationRequest, bool isShellElevation)
 {
     if ((int)(InputArguments.GetIntegrityLevel()) >= ProcessHelper.GetCurrentIntegrityLevel())
     {
         if (!elevationRequest.NewWindow)
         {
             if (isShellElevation)
             {
                 // force auto shell elevation in new window
                 elevationRequest.NewWindow = true;
                 // do not wait by default on this scenario, only if user has requested it.
                 elevationRequest.Wait = InputArguments.Wait;
                 Logger.Instance.Log("Elevating shell in a new console window because of SecurityEnforceUacIsolation", LogLevel.Info);
             }
             else
             {
                 // force raw mode (that disables user input with SecurityEnforceUacIsolation)
                 elevationRequest.Mode = ElevationRequest.ConsoleMode.Piped;
                 Logger.Instance.Log("User Input disabled because of SecurityEnforceUacIsolation. Press Ctrl-C three times to abort. Or use -n argument to elevate in new window.", LogLevel.Warning);
             }
         }
     }
 }
Esempio n. 9
0
        public async Task <int> Execute()
        {
            int? exitCode;
            bool isRunningAsDesiredUser = IsRunningAsDesiredUser();
            bool isElevationRequired    = IsElevationRequired();

            bool isShellElevation = string.IsNullOrEmpty(CommandToRun.FirstOrDefault()); // are we auto elevating the current shell?

            if (isElevationRequired & ProcessHelper.GetCurrentIntegrityLevel() < (int)IntegrityLevel.Medium)
            {
                throw new ApplicationException("Sorry, gsudo doesn't allow to elevate from low integrity level."); // This message is not a security feature, but a nicer error message. It would have failed anyway since the named pipe's ACL restricts it.
            }
            CommandToRun = ArgumentsHelper.AugmentCommand(CommandToRun.ToArray());
            bool isWindowsApp = ProcessFactory.IsWindowsApp(CommandToRun.FirstOrDefault());

            var elevationMode = GetElevationMode(isWindowsApp);

            if (!isRunningAsDesiredUser)
            {
                CommandToRun = AddCopyEnvironment(CommandToRun, elevationMode);
            }

            var exeName = CommandToRun.FirstOrDefault();

            var elevationRequest = new ElevationRequest()
            {
                FileName         = exeName,
                Arguments        = GetArguments(),
                StartFolder      = Environment.CurrentDirectory,
                NewWindow        = InputArguments.NewWindow,
                Wait             = (!isWindowsApp && !InputArguments.NewWindow) || InputArguments.Wait,
                Mode             = elevationMode,
                ConsoleProcessId = Process.GetCurrentProcess().Id,
                IntegrityLevel   = InputArguments.GetIntegrityLevel(),
            };

            if (isElevationRequired && Settings.SecurityEnforceUacIsolation)
            {
                AdjustUacIsolationRequest(elevationRequest, isShellElevation);
            }

            SetRequestPrompt(elevationRequest);

            Logger.Instance.Log($"Command to run: {elevationRequest.FileName} {elevationRequest.Arguments}", LogLevel.Debug);

            if (elevationRequest.Mode == ElevationRequest.ConsoleMode.VT)
            {
                elevationRequest.ConsoleWidth  = Console.WindowWidth;
                elevationRequest.ConsoleHeight = Console.WindowHeight;

                if (TerminalHelper.IsConEmu())
                {
                    elevationRequest.ConsoleWidth--; // weird ConEmu/Cmder fix
                }
            }

            if (isRunningAsDesiredUser && isShellElevation && !InputArguments.NewWindow)
            {
                Logger.Instance.Log("Already running as the specified user/permission-level (and no command specified). Exiting...", LogLevel.Error);
                return(Constants.GSUDO_ERROR_EXITCODE);
            }

            if (isRunningAsDesiredUser || !isElevationRequired) // already elevated or running as correct user. No service needed.
            {
                return(RunWithoutService(exeName, GetArguments(), elevationRequest));
            }

            if (Settings.CacheMode.Value.In(CacheMode.Disabled) ||
                Math.Abs(Settings.CacheDuration.Value.TotalSeconds) < 1 ||
                (InputArguments.KillCache && !IsServiceAvailable()))
            {
                exitCode = await RunUsingSingleUseElevation(elevationRequest).ConfigureAwait(false);
            }
            else if (Settings.CacheMode.Value.In(CacheMode.Auto) ||
                     elevationRequest.Mode != ElevationRequest.ConsoleMode.TokenSwitch)
            {
                exitCode = await RunUsingElevatedService(elevationRequest).ConfigureAwait(false);
            }
            else if (Settings.CacheMode.Value == CacheMode.Explicit && IsServiceAvailable())
            {
                exitCode = await RunUsingElevatedService(elevationRequest).ConfigureAwait(false);
            }
            else
            {
                exitCode = await RunUsingSingleUseElevation(elevationRequest).ConfigureAwait(false);
            }

            if (exitCode.HasValue && exitCode.Value != Constants.GSUDO_ERROR_EXITCODE)
            {
                Logger.Instance.Log($"Process exited with code {exitCode}", exitCode == 0 ? LogLevel.Debug : LogLevel.Info);
            }

            return(exitCode ?? 0);
        }