Exemple #1
0
    def pre_start(self):
        logger.log('INFO', f'Starting user application: {self.name}')

        nukes = self.extract_all_nodes()

        for vm in nukes:
            path = f'{self.startup_dir}/{vm.hostname}-protonuke'

            if vm.topology.hardware.os_type.upper() == 'WINDOWS':
                kwargs = {
                    'src':
                    path,
                    'dst':
                    '/ProgramData/Microsoft/Windows/Start Menu/Programs/Startup/protonuke-scheduler.cmd',
                }

                templates = utils.abs_path(__file__, 'templates/')

                with open(path, 'w') as f:
                    utils.mako_serve_template('protonuke_scheduler.mako',
                                              templates,
                                              f,
                                              protonuke_args=vm.metadata.args)
            else:
                kwargs = {
                    'src': path,
                    'dst': '/etc/default/protonuke',
                }

                with open(path, 'w') as f:
                    f.write('PROTONUKE_ARGS = {}'.format(vm.metadata.args))

            self.add_inject(hostname=vm.hostname, inject=kwargs)

        logger.log('INFO', f'Started user application: {self.name}')
Exemple #2
0
    def stop(self):
        logger.log('INFO', f'Stopping user component: {self.name}')

        hostname = self.metadata.get('hostname', 'detector')
        wait = self.metadata.get('waitDuration', 30)

        mm = self.mm_init()

        self.print(
            f'waiting {wait} seconds before stopping Snort in {hostname}')

        time.sleep(wait)

        self.print(
            f'stopping Snort in {hostname} (be patient... it may take a while)'
        )

        mm.cc_filter(f'name={hostname}')
        mm.cc_exec(f'pkill -INT snort')

        logfiles = ['alert', 'snort.log', 'snort.stats']

        for log in logfiles:
            self.print(f'copying /var/log/snort/{log} from {hostname}')
            utils.mm_recv(mm, hostname, f'/var/log/snort/{log}',
                          f'{self.base_dir}/{log}')

            if log == 'snort.stats' and os.path.exists(
                    f'{self.base_dir}/{log}'):
                self.print(f'converting snort.stats to JSON')

                lines = []

                with open(f'{self.base_dir}/{log}') as f:
                    lines = f.readlines()

                # get rid of comment in file
                lines.pop(0)

                # remove comment field from header line
                header = lines.pop(0)
                header = header.replace('#', '')

                lines.insert(0, header)

                data = csv.DictReader(lines)

                with open(f'{self.base_dir}/snort-stats.jsonl', 'w') as f:
                    for row in data:
                        out = {
                            'timestamp':
                            int(row['time']),
                            'total_alerts_per_second':
                            int(row['total_alerts_per_second']),
                        }

                        json.dump(row, f)
                        f.write('\n')

        logger.log('INFO', f'Stopped user component: {self.name}')
Exemple #3
0
    def start(self):
        logger.log('INFO', f'Starting user component: {self.name}')

        freq = self.metadata.get('pollPeriod', 1)
        vms = self.__vm_list()

        mm = self.mm_init()

        for vm in vms:
            mm.cc_filter(f'name={vm}')
            mm.cc_background(f"bash -c 'vmstat -n -t {freq} >> /vmstat.out'")

        logger.log('INFO', f'Started user component: {self.name}')
Exemple #4
0
    def cleanup(self):
        logger.log('INFO', f'Cleaning up user component: {self.name}')

        scripts = self.metadata.get('scripts', {})
        targets = self.metadata.get('targets', None)

        mm = self.mm_init()

        for target in targets:
            target_host = target.get('hostname', 'traffic-server')
            target_script = scripts['trafficServer']

            background = target.get('backgroundClient', None)

            if background:
                hostname = background.get('hostname', 'background-gen')
                script = scripts['backgroundGen']

                self.print(
                    f'deleting /{os.path.basename(target_script)} on {target_host}'
                )

                mm.cc_filter(f'name={target_host}')
                mm.cc_exec(f'rm /{os.path.basename(target_script)}')

                self.print(
                    f'deleting /{os.path.basename(script)} on {hostname}')

                mm.cc_filter(f'name={hostname}')
                mm.cc_exec(f'rm /{os.path.basename(script)}')
            else:
                self.print(
                    'no background client configured for target {target_host}')

            malware = target.get('malwareClient', None)

            if malware:
                hostname = malware.get('hostname', 'malware-gen')
                script = scripts['malwareGen']

                self.print(
                    f'deleting /{os.path.basename(script)} on {hostname}')

                mm.cc_filter(f'name={hostname}')
                mm.cc_exec(f'rm /{os.path.basename(script)}')
            else:
                self.print(
                    'no malware client configured for target {target_host}')

        logger.log('INFO', f'Cleaned up user component: {self.name}')
Exemple #5
0
    def cleanup(self):
        logger.log('INFO', f'Cleaning up user component: {self.name}')

        hostname = self.metadata.get('hostname', 'detector')
        logfiles = ['snort.log', 'snort.err', 'snort.stats']

        mm = self.mm_init()

        for log in logfiles:
            self.print(f'deleting /var/log/snort/{log} from {hostname}')

            mm.cc_filter(f'name={hostname}')
            mm.cc_exec(f'rm /var/log/snort/{log}')

        logger.log('INFO', f'Cleaned up user component: {self.name}')
Exemple #6
0
    def configure(self):
        logger.log('INFO', f'Configuring user component: {self.name}')

        scripts = self.metadata.get('scripts', {})
        targets = self.metadata.get('targets', None)

        mm = self.mm_init()

        for target in targets:
            hostname = target.get('hostname', 'traffic-server')
            script = scripts['trafficServer']

            self.print(f'copying {os.path.basename(script)} to {hostname}')

            # Copies script to root directory of VM. For example, if script is
            # /phenix/topologies/trafficgen-test/scripts/traffic-server.py, then
            # it will be copied to /traffic-server.py in the VM.
            utils.mm_send(mm, hostname, script, os.path.basename(script))

            background = target.get('backgroundClient', None)

            if background:
                hostname = background.get('hostname', 'background-gen')
                script = scripts['backgroundGen']

                self.print(f'copying {os.path.basename(script)} to {hostname}')

                utils.mm_send(mm, hostname, script, os.path.basename(script))
            else:
                self.print(
                    'no background client configured for target {hostname}')

            malware = target.get('malwareClient', None)

            if malware:
                hostname = malware.get('hostname', 'malware-gen')
                script = scripts['malwareGen']

                self.print(f'copying {os.path.basename(script)} to {hostname}')

                utils.mm_send(mm, hostname, script, os.path.basename(script))
            else:
                self.print(
                    'no malware client configured for target {hostname}')

        logger.log('INFO', f'Configured user component: {self.name}')
Exemple #7
0
    def stop(self):
        logger.log('INFO', f'Stopping user component: {self.name}')

        vms = self.__vm_list()

        mm = self.mm_init()

        for vm in vms:
            mm.cc_filter(f'name={vm}')
            mm.cc_exec('pkill vmstat')
            utils.mm_recv(mm, vm, '/vmstat.out', f'{self.base_dir}/{vm}.out')
            mm.cc_exec('rm /vmstat.out')

        stats = []

        for vm in vms:
            with open(f'{self.base_dir}/{vm}.out', 'r') as f:
                lines = f.readlines()

                for i, line in enumerate(lines):
                    if i in (0, 1):
                        continue

                    items = []

                    for item in line.split():
                        try:
                            items.append(int(item))
                        except ValueError:
                            items.append(item)

                    items[-2] = f'{items[-2]} {items[-1]}'
                    del items[-1]

                    stat = dict(zip(lines[1].split(), items))
                    stat['vm_name'] = vm

                    stats.append(stat)

        with open(f'{self.base_dir}/vm_stats.jsonl', 'a+') as f:
            for datum in stats:
                json_record = json.dumps(datum)
                f.write(json_record + '\n')

        logger.log('INFO', f'Stopped user component: {self.name}')
Exemple #8
0
    def stop(self):
        logger.log('INFO', f'Stopping user component: {self.name}')

        vms = self.metadata.get('vms', None)

        mm = self.mm_init()

        convert = self.metadata.get('convertToJSON', False)

        if convert:
            self.print(f'PCAP --> JSON conversion enabled... please be patient')
        else:
            self.print(f'PCAP --> JSON conversion disabled')

        for vm in vms:
            hostname = vm.get('hostname', None)

            if not hostname:
                self.eprint('no hostname provided for VM config')
                sys.exit(1)

            pcap_out = f'{self.base_dir}/{hostname}.pcap'
            json_out = f'{self.base_dir}/{hostname}.pcap.jsonl'

            utils.mm_exec_wait(mm, hostname, 'pkill tcpdump')

            self.print(f'copying PCAP file from node {hostname}...')

            utils.mm_recv(mm, hostname, '/dump.pcap', pcap_out)
            mm.cc_exec('rm /dump.pcap')

            self.print(f'done copying PCAP file from node {hostname}')

            if convert:
                self.print(f'starting PCAP --> JSON conversion for node {hostname}...')

                subprocess.run(
                    f"bash -c 'tshark -r {pcap_out} -T ek > {json_out} 2>/dev/null'",
                    shell=True,
                )

                self.print(f'PCAP --> JSON conversion for node {hostname} complete')

        logger.log('INFO', f'Stopped user component: {self.name}')
Exemple #9
0
    def pre_start(self):
        logger.log('INFO', f'Starting user application: {self.name}')

        nukes = self.extract_all_nodes()

        for vm in nukes:
            path = f'{self.startup_dir}/{vm.hostname}-protonuke'

            kwargs = {
                'src' : path,
                'dst' : '/etc/default/protonuke',
            }

            self.add_inject(hostname=vm.hostname, inject=kwargs)

            with open(path, 'w') as f:
                f.write('PROTONUKE_ARGS = {}'.format(vm.metadata.args))

        logger.log('INFO', f'Started user application: {self.name}')
Exemple #10
0
    def stop(self):
        logger.log('INFO', f'Stopping user component: {self.name}')

        vms = self.metadata.get('vms', None)

        mm = self.mm_init()

        for vm in vms:
            hostname = vm.get('hostname', None)

            if not hostname:
                continue

            self.print(f'stopping ettercap in VM {hostname}')

            mm.cc_filter(f'name={hostname}')
            mm.cc_exec('pkill ettercap')

        logger.log('INFO', f'Stopped user component: {self.name}')
Exemple #11
0
    def configure(self):
        logger.log('INFO', f'Configuring user component: {self.name}')

        hostname = self.metadata.get('hostname', 'detector')
        scripts = self.metadata.get('scripts', {})
        configs = self.metadata.get('configs', [])

        mm = self.mm_init()

        config_snort = scripts.get('configSnort', None)

        if config_snort:
            script = config_snort['script']
            executor = config_snort['executor']

            self.print(f'copying {os.path.basename(script)} to {hostname}')

            # Copies script to root directory of VM. For example, if script is
            # /phenix/topologies/snort-test/scripts/configure-snort.sh, then it
            # will be copied to /configure-snort.sh in the VM.
            utils.mm_send(mm, hostname, script, os.path.basename(script))

            self.print(f'running {os.path.basename(script)} on {hostname}')

            mm.cc_filter(f'name={hostname}')
            mm.cc_exec(f'{executor} /{os.path.basename(script)}')

        for config in configs:
            src = config['src']
            dst = config['dst']

            self.print(f'copying {os.path.basename(src)} to {hostname}')

            utils.mm_send(mm, hostname, src, dst)

        iface = self.metadata.get('sniffInterface', 'eth0')

        self.print(f'ensuring {iface} is up in {hostname}')

        mm.cc_filter(f'name={hostname}')
        mm.cc_exec(f'ip link set {iface} up')

        logger.log('INFO', f'Configured user component: {self.name}')
Exemple #12
0
    def start(self):
        logger.log('INFO', f'Starting user component: {self.name}')

        hostname = self.metadata.get('hostname', 'detector')
        iface = self.metadata.get('sniffInterface', 'eth0')

        mm = self.mm_init()

        self.print(f'clearing existing Snort logs in {hostname}')

        mm.cc_filter(f'name={hostname}')
        mm.cc_exec('rm -rf /var/log/snort')
        mm.cc_exec('mkdir -p /var/log/snort')

        self.print(f'starting Snort in {hostname}')

        mm.cc_filter(f'name={hostname}')
        mm.cc_background(f'snort -i {iface} -c /etc/snort/snort.conf')

        logger.log('INFO', f'Started user component: {self.name}')
Exemple #13
0
    def start(self):
        logger.log('INFO', f'Starting user component: {self.name}')

        vms = self.metadata.get('vms', None)

        mm = self.mm_init()

        for vm in vms:
            hostname = vm.get('hostname', None)
            iface = vm.get('iface', None)
            method = vm.get('method', 'arp')
            targets = vm.get('targets', None)

            if not hostname:
                continue

            if not iface:
                self.printf(f'missing interface name for VM {hostname}')
                continue

            if not targets:
                self.printf(f'missing targets for VM {hostname}')
                continue

            self.print(f'ensuring interface {iface} is up in VM {hostname}')

            cmd = f'ip link set {iface} up'

            mm.cc_filter(f'name={hostname}')
            mm.cc_exec(cmd)

            self.print(
                f'starting ettercap using {method} against {targets} in VM {hostname}'
            )

            cmd = f'ettercap -Tq -i {iface} -M {method} {targets}'

            mm.cc_background(cmd)

        logger.log('INFO', f'Started user component: {self.name}')
    def pre_start(self):
        logger.log('INFO', f'Starting user application: {self.name}')

        templates = utils.abs_path(__file__, 'templates/')

        guards = self.extract_all_nodes()

        for vm in guards:
            path = f"{self.startup_dir}/{vm.hostname}-wireguard.conf"

            kwargs = {
                'src': path,
                'dst': '/etc/wireguard/wg0.conf',
            }

            self.add_inject(hostname=vm.hostname, inject=kwargs)

            with open(path, 'w') as f:
                utils.mako_serve_template('wireguard_config.mako',
                                          templates,
                                          f,
                                          wireguard=vm.metadata)

            if vm.metadata.get('boot', False):
                path = f"{self.startup_dir}/{vm.hostname}-wireguard-enable.sh"

                kwargs = {
                    'src': path,
                    'dst': '/etc/phenix/startup/wireguard-enable.sh',
                }

                self.add_inject(hostname=vm.hostname, inject=kwargs)

                with open(path, 'w') as f:
                    utils.mako_serve_template('wireguard_enable.mako',
                                              templates,
                                              f,
                                              name='wg0')

        logger.log('INFO', f'Started user application: {self.name}')
Exemple #15
0
    def start(self):
        logger.log('INFO', f'Starting user component: {self.name}')

        vms = self.metadata.get('vms', None)

        mm = self.mm_init()

        for vm in vms:
            hostname = vm.get('hostname', None)
            iface    = vm.get('iface',    None)
            options  = vm.get('options',  '')
            filter   = vm.get('filter',   '')

            if not hostname:
                self.eprint('no hostname provided for VM config')
                sys.exit(1)

            if not iface:
                self.eprint('no interface name provided for VM config')
                sys.exit(1)

            res = utils.mm_exec_wait(mm, hostname, 'which tcpdump')
            if not res:
                self.eprint(f'tcpdump is not installed in VM {hostname}')
                sys.exit(1)

            self.print(f'starting tcpdump on interface {iface} in VM {hostname}')

            if filter:
                self.print(f'using filter {filter} for tcpdump in VM {hostname}')

            mm.cc_filter(f'name={hostname}')
            mm.cc_exec(f'ip link set {iface} up')
            mm.cc_background(f'tcpdump {options} -i {iface} -U -w /dump.pcap {filter}')

        logger.log('INFO', f'Started user component: {self.name}')
    def start(self):
        logger.log('INFO', f'Starting user component: {self.name}')

        self.monitor = True

        thread = threading.Thread(target=self.__run_monitor)
        thread.start()

        logger.log('INFO', f'Started user component: {self.name}')

        # wait for calling process to send SIGTERM
        signal.pause()
        self.monitor = False

        logger.log('INFO', f'Stopping user component: {self.name}')

        thread.join()
        self.__flush_buffer()

        logger.log('INFO', f'Stopped user component: {self.name}')
Exemple #17
0
    def start(self):
        logger.log('INFO', f'Starting user component: {self.name}')

        scripts = self.metadata.get('scripts', {})
        targets = self.metadata.get('targets', None)

        mm = self.mm_init()

        for target in targets:
            target_host = target.get('hostname', 'traffic-server')
            target_iface = target.get('interface', 'IF0')
            target_script = scripts['trafficServer']
            target_ip = self.extract_node_ip(target_host, target_iface)
            duration = target.get('duration', 5)

            background = target.get('backgroundClient', None)

            if background:
                hostname = background.get('hostname', 'background-gen')
                rate = background.get('rate', 10000)
                prob = background.get('probability', .01)
                script = scripts['backgroundGen']

                self.print(
                    f'running {os.path.basename(target_script)} on {target_host}'
                )

                mm.cc_filter(f'name={target_host}')
                mm.cc_background(f'python3 /{os.path.basename(target_script)}')

                self.print(f'running {os.path.basename(script)} on {hostname}')

                mm.cc_filter(f'name={hostname}')
                mm.cc_background(
                    f'python3 /{os.path.basename(script)} --ip {target_ip} '
                    f'--rate {rate} --duration {duration} --probability {prob}'
                )
            else:
                self.print(
                    'no background client configured for target {target_host}')

            malware = target.get('malwareClient', None)

            if malware:
                hostname = malware.get('hostname', 'malware-gen')
                rate = background.get('rate', 20)
                prob = background.get('probability', 1.25)
                script = scripts['malwareGen']

                self.print(f'running {os.path.basename(script)} on {hostname}')

                mm.cc_filter(f'name={hostname}')
                mm.cc_background(
                    f'python3 /{os.path.basename(script)} --ip {target_ip} '
                    f'--rate {rate} --duration {duration} --probability {prob}'
                )
            else:
                self.print(
                    'no malware client configured for target {target_host}')

            self.print(
                f'pausing for {int(duration) + 5}s while traffic is generated for {target_host}'
            )

            time.sleep(int(duration) + 5)

        logger.log('INFO', f'Started user component: {self.name}')
Exemple #18
0
    def start(self):
        logger.log('INFO', f'Starting user component: {self.name}')

        goart      = self.metadata.get('framework', None)
        technique  = self.metadata.get('technique', None)
        test_name  = self.metadata.get('testName',  None)
        test_index = self.metadata.get('testIndex', None)

        mm = self.mm_init()

        if not goart or not os.path.exists(goart):
            self.eprint('goart executable not found')
            sys.exit(1)

        if not technique:
            self.eprint('no technique configured')
            sys.exit(1)

        if test_name is None and test_index is None:
            self.eprint('no technique test configured')
            sys.exit(1)

        vms = self.metadata.get('vms', None)

        for vm in vms:
            self.print(f'copying {goart} to {vm.hostname}')

            utils.mm_send(mm, vm.hostname, goart, f'/tmp/{os.path.basename(goart)}')

            mm.cc_filter(f'name={vm.hostname}')
            mm.cc_exec(f'chmod +x /tmp/{os.path.basename(goart)}')

            args = ['-q', '-f', 'json', '-t', self.metadata.technique]

            out_file = f'/tmp/{str(uuid.uuid4())}.json'

            args.extend(['-o', out_file])

            if test_index is not None:
                args.extend(['-i', str(test_index)])
            elif test_name is not None:
                args.extend(['-n', test_name])
            else: # should never get here...
                self.eprint('no technique test configured')
                sys.exit(1)

            inputs = vm.get('inputs', {})
            for name, value in inputs.items():
                args.extend(['--input', f'{name}={value}'])

            env = self.metadata.get('env', {})
            for name, value in env.items():
                args.extend(['--env', f'{name}={value}'])

            env = vm.get('env', {})
            for name, value in env.items():
                args.extend(['--env', f'{name}={value}'])

            cmd = f"/tmp/{os.path.basename(goart)} {' '.join(args)}"

            self.print(f'executing {cmd} in {vm.hostname}')

            utils.mm_exec_wait(mm, vm.hostname, cmd)

            self.print(f'getting results file {out_file} from {vm.hostname}')

            results_file = os.path.join(self.base_dir, f'{vm.hostname}.json')

            try:
                utils.mm_recv(mm, vm.hostname, out_file, results_file)
            except Exception as ex:
                self.eprint(f'failed to get results file: {ex}')
                sys.exit(1)

            validator = self.metadata.get('validator', None)

            if validator:
                self.print(f'validating results from {vm.hostname}')

                tempfile = f'/tmp/{str(uuid.uuid4())}.sh'

                with open(tempfile, 'w') as tf:
                    tf.write(validator)

                results = Box.from_json(filename=results_file)

                proc = subprocess.run(
                    ['sh', tempfile, vm.hostname],
                    input=results.Executor.ExecutedCommand.results.encode(),
                    capture_output=True,
                )

                if proc.returncode != 0:
                    stderr = proc.stderr.decode()
                    if stderr:
                        self.eprint(f'results validation failed: {stderr}')
                    else:
                        self.eprint('results validation failed')

                    if self.metadata.get('abortOnError', False): os.exit(1)
                else:
                    self.print('results are valid')

                os.remove(tempfile)

        logger.log('INFO', f'Started user component: {self.name}')