Ejemplo n.º 1
0
        public Task <int> Start()
        {
            try
            {
                var t1 = new StreamReader(_connection.ControlStream).ConsumeOutput(HandleControlStream);

                WaitHandle.WaitAny(new WaitHandle[] { tokenSwitchSuccessEvent.WaitHandle, _process.GetProcessWaitHandle(), _connection.DisconnectedWaitHandle });

                if (!tokenSwitchSuccessEvent.IsSet)
                {
                    Logger.Instance.Log(
                        _connection?.IsAlive ?? true
                            ? $"Failed to substitute token."
                            : $"Failed to substitute token. Connection from server lost."
                        , LogLevel.Error);

                    TerminateProcess();

                    return(Task.FromResult(Constants.GSUDO_ERROR_EXITCODE));
                }

                Logger.Instance.Log("Process token successfully substituted.", LogLevel.Debug);
                _ = _connection.FlushAndCloseAll();

                return(GetResult());
            }
            finally
            {
                ConsoleApi.SetConsoleCtrlHandler(ConsoleHelper.IgnoreConsoleCancelKeyPress, false);
            }
        }
Ejemplo n.º 2
0
        private static SafeProcessHandle CreateProcessWithToken(IntPtr newToken, string appToRun, string args, string startupFolder, bool hidden)
        {
            var STARTF_USESHOWWINDOW = 0x00000001;
            var STARTF_USESTDHANDLES = 0x00000100;

            var startupInfo = new STARTUPINFO()
            {
                cb          = (int)Marshal.SizeOf(typeof(STARTUPINFO)),
                dwFlags     = STARTF_USESHOWWINDOW,
                wShowWindow = (short)(hidden ? 0 : 1),
            };

            if (Console.IsErrorRedirected | Console.IsInputRedirected | Console.IsOutputRedirected)
            {
                startupInfo.dwFlags   |= STARTF_USESTDHANDLES;
                startupInfo.hStdOutput = ConsoleApi.GetStdHandle(ConsoleApi.STD_OUTPUT_HANDLE);
                startupInfo.hStdInput  = ConsoleApi.GetStdHandle(ConsoleApi.STD_INPUT_HANDLE);
                startupInfo.hStdError  = ConsoleApi.GetStdHandle(ConsoleApi.STD_ERROR_HANDLE);
            }

            PROCESS_INFORMATION processInformation;

            if (!CreateProcessWithTokenW(newToken, 0, null, $"{appToRun} {args}", (UInt32)0, IntPtr.Zero, startupFolder, ref startupInfo, out processInformation))
            {
                throw new Win32Exception();
            }
            return(new SafeProcessHandle(processInformation.hProcess, true));
        }
Ejemplo n.º 3
0
        public TokenSwitchRenderer(Connection connection, ElevationRequest elevationRequest)
        {
            if (Settings.SecurityEnforceUacIsolation && !elevationRequest.NewWindow)
            {
                throw new Exception("TokenSwitch mode not supported when SecurityEnforceUacIsolation is set.");
            }

            _connection       = connection;
            _elevationRequest = elevationRequest;
            Environment.SetEnvironmentVariable("prompt", Environment.ExpandEnvironmentVariables(elevationRequest.Prompt));

            ProcessApi.CreateProcessFlags dwCreationFlags = ProcessApi.CreateProcessFlags.CREATE_SUSPENDED;

            if (elevationRequest.NewWindow)
            {
                dwCreationFlags |= ProcessApi.CreateProcessFlags.CREATE_NEW_CONSOLE;
            }

            string exeName, args;

            if (elevationRequest.IntegrityLevel == IntegrityLevel.MediumPlus &&
                ArgumentsHelper.UnQuote(elevationRequest.FileName.ToUpperInvariant()) != Environment.GetEnvironmentVariable("COMSPEC").ToUpperInvariant())
            {
                // Now, we have an issue with this method: The process launched with the new token throws Access Denied if it tries to read its own token.
                // Kind of dirty workaround is to wrap the call with a "CMD.exe /c ".. this intermediate process will then
                // launching the command with a fresh new (desired) token and we know cmd wont try to read it's substitute token (throwing Access Denied).

                exeName = Environment.GetEnvironmentVariable("COMSPEC");
                args    = $"/s /c \"{elevationRequest.FileName} {elevationRequest.Arguments}\"";
            }
            else
            {
                // Hack not needed if we are already calling CMD
                exeName = elevationRequest.FileName;
                args    = elevationRequest.Arguments;
            }

            _process = ProcessFactory.CreateProcessAsUserWithFlags(exeName, args, dwCreationFlags, out _processInformation);

            elevationRequest.TargetProcessId = _processInformation.dwProcessId;
            if (!elevationRequest.NewWindow)
            {
                ConsoleApi.SetConsoleCtrlHandler(ConsoleHelper.IgnoreConsoleCancelKeyPress, true);
            }
        }
Ejemplo n.º 4
0
        private static uint[] GetConsoleAttachedPids(uint[] processIds)
        {
            var num = ConsoleApi.GetConsoleProcessList(processIds, 1);

            if (num == 0)
            {
                throw new System.ComponentModel.Win32Exception();
            }

            processIds = new UInt32[num];

            num = ConsoleApi.GetConsoleProcessList(processIds, (uint)processIds.Length);
            if (num == 0)
            {
                throw new System.ComponentModel.Win32Exception();
            }
            return(processIds);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Shows or hides the Console window.
        /// </summary>
        /// <param name="show">true to show; false to hide</param>
        public static void ShowWindow(bool show = true)
        {
            const int SW_HIDE = 0;
            const int SW_SHOW = 5;
            var       handle  = ConsoleApi.GetConsoleWindow();

            if (handle == IntPtr.Zero && show)
            {
                ConsoleApi.AllocConsole();
                handle = ConsoleApi.GetConsoleWindow();
            }

            if (handle == IntPtr.Zero)
            {
                throw new InvalidOperationException("No console window available!");
            }

            ConsoleApi.ShowWindow(handle, show ? SW_SHOW : SW_HIDE);
        }
Ejemplo n.º 6
0
        public bool TryBreak()
        {
            bool tmpResult = false;

            try
            {
                tmpResult = ConsoleApi.GenerateConsoleCtrlEvent(0, (uint)this.process.Handle.ToInt32());

                if (!tmpResult)
                {
                    int tmpError = Marshal.GetLastWin32Error();
                }
            }
            catch (Exception ex)
            {
                SimpleFileLogger.Instance.LogError("Unable to break the process", ex);
            }

            return(tmpResult);
        }
Ejemplo n.º 7
0
        public Task <int> GetResult()
        {
            try
            {
                _ = ProcessApi.ResumeThread(_processInformation.hThread);

                if (_elevationRequest.Wait)
                {
                    _process.GetProcessWaitHandle().WaitOne();
                    if (ProcessApi.GetExitCodeProcess(_process, out int exitCode))
                    {
                        return(Task.FromResult(exitCode));
                    }
                }

                return(Task.FromResult(0));
            }
            finally
            {
                ConsoleApi.SetConsoleCtrlHandler(ConsoleHelper.IgnoreConsoleCancelKeyPress, false);
            }
        }
Ejemplo n.º 8
0
        internal static SafeProcessHandle CreateProcessAsUserWithFlags(string lpApplicationName, string args, ProcessApi.CreateProcessFlags dwCreationFlags, out PROCESS_INFORMATION pInfo)
        {
            var sInfoEx = new ProcessApi.STARTUPINFOEX();

            sInfoEx.StartupInfo.cb = Marshal.SizeOf(sInfoEx);
            IntPtr lpValue = IntPtr.Zero;

            var pSec = new ProcessApi.SECURITY_ATTRIBUTES();
            var tSec = new ProcessApi.SECURITY_ATTRIBUTES();

            pSec.nLength = Marshal.SizeOf(pSec);
            tSec.nLength = Marshal.SizeOf(tSec);

            var command = $"{lpApplicationName} {args}";

            Logger.Instance.Log($"{nameof(CreateProcessAsUser)}: {lpApplicationName} {args}", LogLevel.Debug);
            if (!ProcessApi.CreateProcess(null, command, ref pSec, ref tSec, false, dwCreationFlags, IntPtr.Zero, null, ref sInfoEx, out pInfo))
            {
                throw new Win32Exception((int)ConsoleApi.GetLastError());
            }

            return(new SafeProcessHandle(pInfo.hProcess, true));
        }
Ejemplo n.º 9
0
 internal static TokenProvider CreateUnelevated(IntegrityLevel level)
 {
     if (ProcessHelper.IsAdministrator())
     {
         // Have you impersonated system first?
         if (!WindowsIdentity.GetCurrent().IsSystem)
         {
             try
             {
                 return(TokenProvider
                        .CreateFromSystemAccount()
                        .EnablePrivilege(Privilege.SeAssignPrimaryTokenPrivilege, true)
                        .Impersonate(() =>
                 {
                     return CreateFromCurrentProcessToken().GetLinkedToken().Duplicate()
                     .SetIntegrity(level);
                 }));
             }
             catch (Exception e)
             {
                 Logger.Instance.Log("Unable to get unelevated token, will try SaferApi Token. " + e.ToString(),
                                     LogLevel.Warning);
                 return(TokenProvider.CreateFromSaferApi(SaferLevels.NormalUser));
             }
         }
         else
         {
             IntPtr hwnd = ConsoleApi.GetShellWindow();
             _ = ConsoleApi.GetWindowThreadProcessId(hwnd, out uint pid);
             return(TokenProvider.CreateFromProcessToken((int)pid));
         }
     }
     else
     {
         return(TokenProvider.CreateFromCurrentProcessToken());
     }
 }
Ejemplo n.º 10
0
        void OnMessageReceived(byte[] RawMessage)
        {
            try
            {
                string   Message = Encoding.Unicode.GetString(RawMessage);
                XElement xMsg    = XElement.Parse(Message, LoadOptions.PreserveWhitespace);

                if (xMsg.Name.LocalName == "Connect-Terminal")
                {
                    try
                    {
                        string Domain   = xMsg.Attribute("Domain").Value;
                        string UserName = xMsg.Attribute("UserName").Value;
                        string Password = xMsg.Attribute("Password").Value;

                        lock (ProcessLock)
                        {
                            // Remove any processes which have exited so that instead of reattaching we launch a new one...
                            List <string> ToRemove = new List <string>();
                            foreach (var kvp in Processes)
                            {
                                var TheProcess = kvp.Value;
                                if (TheProcess.CommandPrompt == null || !TheProcess.CommandPrompt.IsStillRunning)
                                {
                                    ToRemove.Add(kvp.Key);
                                }
                            }
                            foreach (string Key in ToRemove)
                            {
                                Processes.Remove(Key);
                            }

                            // Next check if we have this process already open, referenced by full username...
                            string FullUserName;
                            if (Domain.Length > 0)
                            {
                                FullUserName = Domain + "\\" + UserName;
                            }
                            else
                            {
                                FullUserName = UserName;
                            }
                            if (Processes.ContainsKey(FullUserName))
                            {
                                CredentialValidation.ValidateUser(Domain, UserName, Password);
                                ConnectedProcess = Processes[FullUserName];

                                if (!ConsoleApi.AttachConsole((uint)ConnectedProcess.CommandPrompt.ProcessId))
                                {
                                    throw new Win32Exception(Marshal.GetLastWin32Error());
                                }

                                if (Conin != null)
                                {
                                    Conin.Dispose(); Conin = null;
                                }
                                Conin = new ConsoleInput();

                                if (CT != null)
                                {
                                    CT.Dispose(); CT = null;
                                }
                                CT = new ConsoleTracker();

                                string XmlMsg = "<Terminal-Connected Reconnected=\"true\" full-user-name=\"" + FullUserName + "\" />";
                                byte[] RawMsg = Encoding.Unicode.GetBytes(XmlMsg);
                                SendMessage(NetworkStream, RawMsg);
                            }
                            else
                            {
                                ConnectedProcess = new SlaveProcess();
                                try
                                {
#if DEBUG && ShowCmdWindow
                                    ConnectedProcess.Start(Domain, UserName, Password, IsLocalProvider);
#else
                                    ConnectedProcess.Start(Domain, UserName, Password, false);
#endif

                                    Processes.Add(FullUserName, ConnectedProcess);

                                    Thread.Sleep(2500);         // TODO: WaitForInputIdle() would be preferred and more robust.

                                    //ConnectedProcess.CommandPrompt.WaitForInputIdle(15000);

                                    if (!ConnectedProcess.CommandPrompt.IsStillRunning)
                                    {
                                        throw new Exception("Newly launched terminal appears to have exited immediately or never actually launched.");
                                    }

                                    if (!ConsoleApi.AttachConsole((uint)ConnectedProcess.CommandPrompt.ProcessId))
                                    {
                                        this.Log.WriteLine("AttachConsole() failed.", Severity.Debug);
                                        throw new Win32Exception(Marshal.GetLastWin32Error());
                                    }

                                    this.Log.WriteLine("Console attached.", Severity.Debug);

                                    if (Conin != null)
                                    {
                                        Conin.Dispose(); Conin = null;
                                    }
                                    Conin = new ConsoleInput();

                                    if (CT != null)
                                    {
                                        CT.Dispose(); CT = null;
                                    }
                                    CT = new ConsoleTracker();

                                    this.Log.WriteLine("Console established without errors.", Severity.Debug);
                                }
                                finally
                                {
                                    if (ConnectedProcess.CommandPrompt.DebugLog.Length > 0)
                                    {
                                        this.Log.WriteLine(ConnectedProcess.CommandPrompt.DebugLog.ToString(), Severity.Debug);
                                        string XmlMsg = "<Debug>" + ConnectedProcess.CommandPrompt.DebugLog.ToString() + "</Debug>";
                                        byte[] RawMsg = Encoding.Unicode.GetBytes(XmlMsg);
                                        SendMessage(NetworkStream, RawMsg);
                                        ConnectedProcess.CommandPrompt.DebugLog.Clear();
                                    }
                                }

                                {
                                    string XmlMsg = "<Terminal-Connected Reconnected=\"false\" full-user-name=\"" + FullUserName + "\" />";
                                    byte[] RawMsg = Encoding.Unicode.GetBytes(XmlMsg);
                                    SendMessage(NetworkStream, RawMsg);
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        string EncodedText = System.Convert.ToBase64String(Encoding.Unicode.GetBytes(ex.ToString() + "\n"));
                        string XmlMsg      = "<Error>" + EncodedText + "</Error>";
                        byte[] RawMsg      = Encoding.Unicode.GetBytes(XmlMsg);
                        SendMessage(NetworkStream, RawMsg);
                    }
                }

                if (xMsg.Name.LocalName == "Console-Input")
                {
                    // TODO: This xml format isn't very efficient.  Could at least string it all into one array of INPUT_RECORDs.
                    List <ConsoleApi.KEY_EVENT_RECORD> Keys = new List <ConsoleApi.KEY_EVENT_RECORD>();
                    foreach (var Key in xMsg.Elements())
                    {
                        if (Key.Name != "Key")
                        {
                            throw new FormatException("Expected <Key> objects in <Console-Input>");
                        }
                        ConsoleApi.KEY_EVENT_RECORD KER = new ConsoleApi.KEY_EVENT_RECORD();
                        KER.bKeyDown          = Boolean.Parse(Key.Attribute("down").Value);
                        KER.dwControlKeyState = (ConsoleApi.ControlKeyState)UInt32.Parse(Key.Attribute("ctrl").Value);
                        KER.UnicodeChar       = (char)UInt32.Parse(Key.Attribute("char").Value);
                        KER.wRepeatCount      = UInt16.Parse(Key.Attribute("repeat").Value);
                        KER.wVirtualKeyCode   = UInt16.Parse(Key.Attribute("key").Value);
                        KER.wVirtualScanCode  = UInt16.Parse(Key.Attribute("scan").Value);
                        Keys.Add(KER);
                    }

                    //byte[] Raw = System.Convert.FromBase64String(xMsg.Value);
                    //string Msg = Encoding.Unicode.GetString(Raw);
                    lock (ProcessLock)
                    {
                        if (ConnectedProcess != null)
                        {
                            StringBuilder Text = new StringBuilder();
                            foreach (var Key in Keys)
                            {
                                Text.Append(Key.UnicodeChar);
                            }
                            //Debug.WriteLine("Writing to console as input: '" + Text + "'");

                            ConsoleApi.INPUT_RECORD[] irs = new ConsoleApi.INPUT_RECORD[1];
                            ConsoleApi.INPUT_RECORD   ir  = new ConsoleApi.INPUT_RECORD();
                            ir.EventType = (ushort)ConsoleApi.EventTypes.KEY_EVENT;

                            foreach (var Key in Keys)
                            {
                                ir.KeyEvent = Key;
                                irs[0]      = ir;
                                Conin.Write(irs);
                            }

                            //Thread.Sleep(50);
                            //CT.DebugWholeConsole();
                        }
                    }
                }

                if (xMsg.Name.LocalName == "Reload-Console")
                {
                    lock (ProcessLock) CT.PendingReload = true;
                }
            }
            catch (Exception ex)
            {
                Debug.Write("Exception detected in SlaveCore.OnMessageReceived(): " + ex.ToString());
                throw ex;
            }
        }
Ejemplo n.º 11
0
        protected void ClientThreadEntry()
        {
            try
            {
                TcpListener listenerV4 = new TcpListener(IPAddress.Any, PortNumber);
                TcpListener listenerV6 = new TcpListener(IPAddress.IPv6Any, PortNumber);
                listenerV4.Start(10);
                listenerV6.Start(10);

                // Start listening for connections.

                Log.WriteLine("Listening for TCP connections on port " + PortNumber + "...\n", Severity.Debug);
                while (!Stopping)
                {
                    TcpClient ClientRequest;
                    try
                    {
                        if (listenerV4.Pending())
                        {
                            ClientRequest = listenerV4.AcceptTcpClient();
                        }
                        else if (listenerV6.Pending())
                        {
                            ClientRequest = listenerV6.AcceptTcpClient();
                        }
                        else
                        {
                            Thread.Sleep(250); continue;
                        }

                        Log.WriteLine("TCP Client accepted.\n", Severity.Debug);

                        NetworkStream = new SslStream(ClientRequest.GetStream(), false);
                        NetworkStream.AuthenticateAsServer(GetRemoteDesktopCertificate(), false, SslProtocols.Tls12, true);
                        if (!NetworkStream.IsAuthenticated)
                        {
                            NetworkStream = null;
                            Log.WriteLine("Unable to authenticate incoming connection from " + ((IPEndPoint)ClientRequest.Client.RemoteEndPoint).Address.ToString() + ".", Severity.Warning);
                            ClientRequest.Close();
                            continue;
                        }
                        if (!NetworkStream.IsEncrypted)
                        {
                            NetworkStream = null;
                            Log.WriteLine("Unable to encrypt incoming connection from " + ((IPEndPoint)ClientRequest.Client.RemoteEndPoint).Address.ToString() + ".", Severity.Warning);
                            ClientRequest.Close();
                            continue;
                        }
                        // Display the properties and settings for the authenticated stream.
                        Log.WriteLine("Authentication successful [host].\n", Severity.Debug);
#if DEBUG
                        DisplaySecurityLevel(Log, NetworkStream, Severity.Debug);
                        DisplaySecurityServices(Log, NetworkStream, Severity.Debug);
                        DisplayCertificateInformation(Log, NetworkStream, Severity.Debug);
                        DisplayStreamProperties(Log, NetworkStream, Severity.Debug);
#endif

                        // Transmit our version info as a hello.
                        System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
                        FileVersionInfo            fvi      = FileVersionInfo.GetVersionInfo(assembly.Location);
                        string version = fvi.FileVersion;
                        string XmlMsg  = "<Portal-Version Core-Library=\"" + fvi.FileVersion + "\" />";
                        byte[] RawMsg  = Encoding.Unicode.GetBytes(XmlMsg);
                        if (NetworkStream != null)
                        {
                            SendMessage(NetworkStream, RawMsg);
                        }
                    }
                    catch (Win32Exception ex)
                    {
                        Log.WriteLine("Exception accepting new connection: " + ex.ToString(), Severity.Debug);
                        if ((uint)ex.ErrorCode == 0x80004005)
                        {
                            // The credentials supplied to the pacakage were not recognized.
                            // This error comes up rom NetworkStream.AuthenticateAsServer() or GetRemoteDesktopCertificate() for localhost slave when there is no administrative access.
                            Log.WriteLine("This exception usually indicates that administrative access was required but not present.", Severity.Debug);
                        }
                        continue;
                    }
                    catch (Exception ex)
                    {
                        // Note: "The credentials supplied to the package were not recognized" is probably a sign that the code doesn't have Administrator access and can't access the subsystem or certificate it needs.
                        Log.WriteLine("Exception accepting new connection: " + ex.ToString(), Severity.Debug);
                        continue;
                    }

                    try
                    {
                        ServiceConnection(NetworkStream, ClientRequest, ClientRequest.GetStream());
                    }
                    catch (Exception ex)
                    {
                        Log.WriteLine("Exception servicing connection: " + ex.ToString(), Severity.Debug);
                    }

                    lock (ProcessLock)
                    {
                        // Setting ConnectedProcess to null before accepting a new connection is essential to security.  It prevents access to the console without a new authentication and Connect-Terminal.
                        ConnectedProcess = null;

                        // If we aren't attached to a console, FreeConsole() would return ERROR_INVALID_PARAMETER.
                        ConsoleApi.FreeConsole();

                        Log.WriteLine("Closing connection in SlaveCore (if it isn't already).", Severity.Debug);
                        if (ClientRequest != null)
                        {
                            ClientRequest.Dispose(); ClientRequest = null;
                        }

                        if (Conin != null)
                        {
                            Conin.Dispose(); Conin = null;
                        }
                        if (CT != null)
                        {
                            CT.Dispose(); CT = null;
                        }
                    }
                }

                lock (ProcessLock)
                {
                    ConnectedProcess = null;
                    foreach (var kvp in Processes)
                    {
                        kvp.Value.Dispose();
                    }
                    Processes.Clear();
                }
            }
            catch (Exception e)
            {
                Log.WriteLine("Error: " + e.ToString(), Severity.Error);
            }
        }
Ejemplo n.º 12
0
 public void Init()
 {
     instance = new ConsoleApi();
 }
Ejemplo n.º 13
0
 static Console()
 {
     Handler = ConsoleCtrlHandler;
     ConsoleApi.SetConsoleCtrlHandler(Handler, true);
     SystemEvents.SessionEnding += SystemEvents_SessionEnding;
 }
 public GetIntersightConsoleConsoleConfig()
 {
     ApiInstance = new ConsoleApi(Config);
     MethodName  = "GetConsoleConsoleConfigListWithHttpInfo";
 }