Ejemplo n.º 1
0
    def process(self, context, output):
        try:
            filename = output['filename']
            self.gzip_file = os.path.join(
                get_path_in_data_folder("logs"),
                f"{context.session.guid}/screenshot_{filename}.gz"
            )
            self.decompressed_file = os.path.join(
                get_path_in_data_folder("logs"),
                f"{context.session.guid}/screenshot_{filename}.jpg"
            )

            file_chunk = output['data']
            with open(self.gzip_file, 'ab+') as reassembled_gzip_data:
                reassembled_gzip_data.write(b64decode(file_chunk))

            if output['current_chunk_n'] == (output['chunk_n'] + 1):
                try:
                    with open(self.decompressed_file, 'wb') as reassembled_file:
                        with gzip.open(self.gzip_file) as compressed_screenie:
                            reassembled_file.write(compressed_screenie.read())
                except Exception as e:
                    logging.error(f"Error decompressing re-assembled screenshot: {e}")
                return f"Saved screenshot to {self.decompressed_file}!"
            else:
                return f"Processed chunk {output['current_chunk_n']}/{output['chunk_n'] + 1}"
        except TypeError:
            return output
Ejemplo n.º 2
0
    def __init__(self, guid, psk):
        self._guid = str(guid)
        self._alias = str(guid)
        self._info = None
        self.address = None
        self.checkin_time = None
        self.crypto = ECDHE(psk=psk)
        self.jobs = Jobs(self)

        self.logger = logging.getLogger(f"session:{str(self._guid)}")
        self.logger.propagate = False
        self.logger.setLevel(logging.DEBUG)

        try:
            os.mkdir(
                os.path.join(get_path_in_data_folder("logs"), f"{self._guid}"))
        except FileExistsError:
            pass

        formatter = logging.Formatter('%(asctime)s - %(message)s')
        fh = logging.FileHandler(os.path.join(
            get_path_in_data_folder("logs"), f"{self._guid}/{self._guid}.log"),
                                 encoding='UTF-8')
        fh.setLevel(logging.DEBUG)
        fh.setFormatter(formatter)
        self.logger.addHandler(fh)
Ejemplo n.º 3
0
def start(args):
    if not os.path.exists(get_data_folder()):
        logging.info("First time use detected, creating data folder (~/.st)")
        os.makedirs(get_path_in_data_folder('logs'))
    if not os.path.exists(get_path_in_data_folder('logs')):
        os.mkdir(get_path_in_data_folder('logs'))

    loop = asyncio.get_event_loop()
    teamserver_digest = hmac.new(args['<password>'].encode(), msg=b'silenttrinity', digestmod=sha512).hexdigest()

    stop = asyncio.Future()
    for sig in (signal.SIGINT, signal.SIGTERM):
        loop.add_signal_handler(sig, stop.set_result, None)

    if args['--insecure']:
        logging.warning('SECURITY WARNING: --insecure flag passed, communication between client and server will be in cleartext!')

    if args['--debug']:
        logger = logging.getLogger()
        logger_handler = logging.StreamHandler()  # Handler for the logger
        logger.addHandler(logger_handler)
        logger_handler.setFormatter(logging.Formatter(
            '[%(levelname)s] %(process)d %(threadName)s - %(filename)s: %(funcName)s - %(message)s'))
        logging.getLogger().setLevel(logging.DEBUG)

    loop.run_until_complete(server(stop, args, teamserver_digest))
    def run(self):

        """
        While we could use the standard decorators to register these routes, 
        using add_url_rule() allows us to create diffrent endpoint names
        programmatically and pass the classes self object to the routes
        """

        config = Config()
        config.accesslog = os.path.join(get_path_in_data_folder("logs"), "access.log")
        config.bind = f"{self['BindIP']}:{self['Port']}"
        config.insecure_bind = True
        config.include_server_header = False
        config.use_reloader = False
        config.debug = False

        http_blueprint = Blueprint(__name__, 'http')
        http_blueprint.before_request(self.check_if_naughty)
        #http_blueprint.after_request(self.make_normal)

        http_blueprint.add_url_rule('/<uuid:GUID>', 'key_exchange', self.key_exchange, methods=['POST'])
        http_blueprint.add_url_rule('/<uuid:GUID>', 'stage', self.stage, methods=['GET'])
        http_blueprint.add_url_rule('/<uuid:GUID>/jobs', 'jobs', self.jobs, methods=['GET'])
        http_blueprint.add_url_rule('/<uuid:GUID>/jobs/<job_id>', 'job_result', self.job_result, methods=['POST'])

        # Add a catch all route
        http_blueprint.add_url_rule('/', 'unknown_path', self.unknown_path, defaults={'path': ''})
        http_blueprint.add_url_rule('/<path:path>', 'unknown_path', self.unknown_path, methods=['GET', 'POST'])

        #logging.getLogger('quart.app').setLevel(logging.DEBUG if state.args['--debug'] else logging.ERROR)
        #logging.getLogger('quart.serving').setLevel(logging.DEBUG if state.args['--debug'] else logging.ERROR)

        self.app = Quart(__name__)
        self.app.register_blueprint(http_blueprint)
        asyncio.run(serve(self.app, config))
Ejemplo n.º 5
0
 def create_db_and_schema(db_path=get_path_in_data_folder("st.db")):
     with sqlite3.connect(db_path) as db:
         db.execute('''CREATE TABLE "sessions" (
                         "id" integer PRIMARY KEY,
                         "guid" text,
                         "psk" text,
                         UNIQUE(guid,psk)
                     )''')
Ejemplo n.º 6
0
async def server(stop, args, teamserver_digest):
    if not os.path.exists(get_path_in_data_folder("st.db")):
        logging.info('Creating database')
        await AsyncSTDatabase.create_db_and_schema()

    ts = TeamServer()

    ssl_context = None
    if not args['--insecure']:
        ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
        try:
            ssl_context.load_cert_chain(
                get_path_in_data_folder("chain.pem")
            )
        except FileNotFoundError:
            create_self_signed_cert()
            ssl_context.load_cert_chain(
                get_path_in_data_folder("chain.pem")
            )

        server_cert_fingerprint = get_cert_fingerprint(get_path_in_data_folder("cert.pem"))
        logging.warning(
            (f"{colored('Teamserver certificate fingerprint:', 'yellow')} "
             f"{colored(server_cert_fingerprint.hex(), 'red')}")
        )

    STWebSocketServerProtocol.teamserver_digest = teamserver_digest
    async with websockets.serve(
        ts.connection_handler,
        host=args['<host>'],
        port=int(args['--port']),
        create_protocol=STWebSocketServerProtocol,
        ssl=ssl_context,
        ping_interval=None,
        ping_timeout=None
    ):

        logging.info(colored(f"Teamserver started on {args['<host>']}:{args['--port']}", "yellow"))

        await stop
Ejemplo n.º 7
0
def start(args):
    if not os.path.exists(get_data_folder()):
        logging.info("First time use detected, creating data folder (~/.st)")
        os.makedirs(get_path_in_data_folder('logs'))
    if not os.path.exists(get_path_in_data_folder('logs')):
        os.mkdir(get_path_in_data_folder('logs'))

    loop = asyncio.get_event_loop()
    teamserver_digest = hmac.new(args['<password>'].encode(),
                                 msg=b'silenttrinity',
                                 digestmod=sha512).hexdigest()

    stop = asyncio.Future()
    for sig in (signal.SIGINT, signal.SIGTERM):
        loop.add_signal_handler(sig, stop.set_result, None)

    if args['--insecure']:
        logging.warning(
            'SECURITY WARNING: --insecure flag passed, communication between client and server will be in cleartext!'
        )

    loop.run_until_complete(server(stop, args, teamserver_digest))
Ejemplo n.º 8
0
    def process(self, context, output):
        if self._new_dmp_file == True:
            self._new_dmp_file = False
            self.fname = ntpath.basename(self.options['Src']['Value'])
            self.gzip_file = os.path.join(
                get_path_in_data_folder("logs"),
                f"{context.session.guid}/downloader_{datetime.now().strftime('%Y_%m_%d_%H%M%S')}.gz"
            )
            self.decompressed_file = os.path.join(
                get_path_in_data_folder("logs"),
                f"{context.session.guid}/downloader_{datetime.now().strftime('%Y_%m_%d_%H%M%S')}_{self.fname}"
            )

        try:
            file_chunk = output['data']
            with open(self.gzip_file, 'ab+') as reassembled_gzip_file:
                reassembled_gzip_file.write(b64decode(file_chunk))

            if output['current_chunk_n'] == (output['chunk_n'] + 1):
                try:
                    with open(self.decompressed_file,
                              'wb') as reassembled_file:
                        with gzip.open(self.gzip_file) as compressed_file:
                            reassembled_file.write(compressed_file.read())
                    os.remove(self.gzip_file)
                except Exception as e:
                    logging.error(
                        f"Error decompressing re-assembled file: {e}")

                self._new_dmp_file = True
                return

            else:
                return f"Processed chunk {output['current_chunk_n']}/{output['chunk_n'] + 1}"
        except TypeError:
            return output
Ejemplo n.º 9
0
def test_listeners(listener_loader):
    os.makedirs(get_path_in_data_folder('logs'), exist_ok=True)

    s = requests.Session()
    retries = Retry(total=3, backoff_factor=0.5)
    s.verify = False
    s.mount('http://', HTTPAdapter(max_retries=retries))
    s.mount('https://', HTTPAdapter(max_retries=retries))

    for l in listener_loader.loaded:
        print(f"Testing listener '{l.name}'")
        assert isinstance(l, Listener) == True

        if l.name in ['http', 'https']:
            l['BindIP'] = '127.0.0.1'
            l['Port'] = str(random.randint(3000, 6000))
            if l.name == 'https':
                l['Cert'] = CERT_PATH
                l['key'] = KEY_PATH
            l.start()
            r = s.get(f"{l.name}://127.0.0.1:{l['Port']}/")
            assert r.status_code == 404
            l.stop()
            assert l.running == False
Ejemplo n.º 10
0
 def __init__(self, db_path=get_path_in_data_folder("st.db")):
     self.db_path = db_path
Ejemplo n.º 11
0
    def run(self):
        if (self['Key'] == '~/.st/key.pem') and (self['Cert']
                                                 == '~/.st/cert.pem'):
            if not os.path.exists(
                    get_path_in_data_folder("key.pem")) or not os.path.exists(
                        get_path_in_data_folder(
                            "cert.pem")) or self['RegenCert']:
                create_self_signed_cert()

        config = Config()
        config.ciphers = 'ALL'
        config.accesslog = os.path.join(get_path_in_data_folder("logs"),
                                        "access.log")
        config.bind = f"{self['BindIP']}:{self['Port']}"
        config.certfile = os.path.expanduser(self['Cert'])
        config.keyfile = os.path.expanduser(self['Key'])
        config.include_server_header = False  # This doesn't seem to do anything?
        config.use_reloader = False
        config.debug = False
        """
        While we could use the standard decorators to register these routes, 
        using add_url_rule() allows us to create diffrent endpoint names
        programmatically and pass the classes self object to the routes
        """

        http_blueprint = Blueprint(__name__, 'https')
        http_blueprint.before_request(self.check_if_naughty)
        #http_blueprint.after_request(self.make_normal)

        http_blueprint.add_url_rule('/<uuid:GUID>',
                                    'key_exchange',
                                    self.key_exchange,
                                    methods=['POST'])
        http_blueprint.add_url_rule('/<uuid:GUID>',
                                    'stage',
                                    self.stage,
                                    methods=['GET'])
        http_blueprint.add_url_rule('/<uuid:GUID>/jobs',
                                    'jobs',
                                    self.jobs,
                                    methods=['GET'])
        http_blueprint.add_url_rule('/<uuid:GUID>/jobs/<job_id>',
                                    'job_result',
                                    self.job_result,
                                    methods=['POST'])

        # Add a catch all route
        http_blueprint.add_url_rule('/',
                                    'unknown_path',
                                    self.unknown_path,
                                    defaults={'path': ''})
        http_blueprint.add_url_rule('/<path:path>',
                                    'unknown_path',
                                    self.unknown_path,
                                    methods=['GET', 'POST'])

        #logging.getLogger('quart.app').setLevel(logging.DEBUG if state.args['--debug'] else logging.ERROR)
        #logging.getLogger('quart.serving').setLevel(logging.DEBUG if state.args['--debug'] else logging.ERROR)

        self.app = Quart(__name__)
        self.app.register_blueprint(http_blueprint)
        asyncio.run(serve(self.app, config))