Ejemplo n.º 1
0
    def _create(self, config, force=False):
        project_dir = config['project_dir']

        # Check if the project directory already exists
        _check_project_dir(project_dir, force)

        # Create the project directory
        os.mkdir(project_dir)

        if config['use_seeds'] and not os.path.isdir(config['seeds_dir']):
            os.mkdir(config['seeds_dir'])

        # Create symlinks to the target files (if they exist)
        if config['target_files']:
            self._symlink_project_files(project_dir, *config['target_files'])

        # Create a symlink to the guest tools directory
        self._symlink_guest_tools(project_dir, config['image'])

        # Create a symlink to guestfs (if it exists)
        if config['guestfs_path']:
            self._symlink_guestfs(project_dir, config['guestfs_path'])

        # Render the templates
        self._create_launch_script(project_dir, config)
        self._create_lua_config(project_dir, config)
        self._create_bootstrap(project_dir, config)

        # Save the project configuration as JSON
        _save_json_description(project_dir, config)

        # Generate recipes for PoV generation
        if config['use_recipes']:
            os.makedirs(config['recipes_dir'])
            call_command(RecipeCommand(), [], project=os.path.basename(project_dir))

        # Display relevant messages to the user
        display_marker_warning = config['target_path'] and \
                                 config['warn_input_file'] and \
                                 not (config['use_symb_input_file'] or config['sym_args'])

        if display_marker_warning:
            logger.warning('You did not specify the input file marker @@. '
                           'This marker is automatically substituted by a '
                           'file with symbolic content. You will have to '
                           'manually edit the bootstrap file in order to run '
                           'the program on multiple paths.\n\n'
                           'Example: %s @@\n\n'
                           'You can also make arguments symbolic using the '
                           '``S2E_SYM_ARGS`` environment variable in the '
                           'bootstrap file', config['target_path'])

        if config['use_seeds'] and not config['use_symb_input_file'] and config['warn_seeds']:
            logger.warning('Seed files have been enabled, however you did not '
                           'specify an input file marker (i.e. \'@@\') to be '
                           'substituted with a seed file. This means that '
                           'seed files will be fetched but never used. Is '
                           'this intentional?')
Ejemplo n.º 2
0
    def _create(self, config, force=False):
        project_dir = config['project_dir']
        target = config['target']

        # Check if the project directory already exists
        _check_project_dir(project_dir, force)

        # Create the project directory
        os.makedirs(project_dir)

        if config['use_seeds'] and not os.path.isdir(config['seeds_dir']):
            os.mkdir(config['seeds_dir'])

        # Create symlinks to the target files (if they exist)
        if target.files:
            self._symlink_project_files(project_dir, *target.files)

        target.args.generate_symbolic_files(project_dir, config['use_seeds'])

        # Create symlinks to symbolic files
        if target.args.symbolic_files:
            self._symlink_project_files(project_dir,
                                        *target.args.symbolic_files)

        # Create a symlink to the guest tools directory
        self._symlink_guest_tools(project_dir, config['image'])

        # Create a symlink to guestfs (if it exists)
        if config['guestfs_paths']:
            self._symlink_guestfs(project_dir, config['guestfs_paths'])

        # Render the templates
        self._create_launch_script(project_dir, config)
        self._create_lua_config(project_dir, config)
        self._create_bootstrap(project_dir, config)

        # Even though the AbstractProject will save the project description, we
        # need it to be able to generate recipes below
        self._save_json_description(project_dir, config)

        # Generate recipes for PoV generation
        if config['use_recipes']:
            os.makedirs(config['recipes_dir'])
            call_command(RecipeCommand(), [], project=project_dir)

        # Display relevant messages to the user
        display_marker_warning = config['target'].path and \
                                 config['warn_input_file'] and \
                                 not config['single_path'] and \
                                 not (config['target'].args.symbolic_files or config['sym_args'])

        if display_marker_warning:
            logger.warning(
                'You did not specify any symbolic input. '
                'Symbolic execution requires symbolic inputs. You will have to '
                'manually edit the bootstrap file in order to run '
                'the program on multiple paths.\n\n'
                'Example: %s @@\n\n'
                'You can also make arguments symbolic using the '
                '``S2E_SYM_ARGS`` environment variable in the '
                'bootstrap file', config['target'].path)

        seed_files_count = len(config['target'].args.blank_seed_files)
        if config['use_seeds'] and config['warn_seeds']:
            if not seed_files_count:
                logger.warning(
                    'Seed files have been enabled, however you did not '
                    'specify an input file marker (i.e. \'@@\') to be '
                    'substituted with a seed file. This means that '
                    'seed files will be fetched but never used. Is '
                    'this intentional?')
            if seed_files_count > 1:
                raise CommandError(
                    'You specified multiple symbolic inputs with @@. You may only have one '
                    'when seeds are enabled.')

        return project_dir
Ejemplo n.º 3
0
    def handle(self, *args, **options):
        self._validate_and_create_project(options)

        # Prepare the configuration for file templates
        config = {
            'creation_time':
            str(datetime.datetime.now()),
            'project_dir':
            self._project_dir,
            'project_type':
            self._configurator.PROJECT_TYPE,
            'image':
            self._img_json,
            'target':
            os.path.basename(self._target_path) if self._target_path else None,
            'target_path':
            self._target_path,
            'target_arch':
            options['target_arch'],
            'target_args':
            options['target_args'],

            # These contain all the files that must be downloaded into the guest
            'target_files': [],

            # List of module names that go into ModuleExecutionDetector
            'modules':
            options['modules'],

            # List of binaries that go into ProcessExecutionDetector
            # These are normally executable files
            'processes':
            options['processes'],
            'sym_args':
            options['sym_args'],

            # See _create_bootstrap for an explanation of the @@ marker
            'use_symb_input_file':
            '@@' in options['target_args'],

            # The use of seeds is specified on the command line
            'use_seeds':
            options['use_seeds'],
            'seeds_dir':
            os.path.join(self._project_dir, 'seeds'),

            # The use of recipes is set by the configurator
            'use_recipes':
            False,
            'recipes_dir':
            os.path.join(self._project_dir, 'recipes'),

            # The use of guestfs is dependent on the specific image
            'has_guestfs':
            True,
            'guestfs_dir':
            os.path.join(self._project_dir, 'guestfs'),

            # These options are determined by the configurator's analysis
            'dynamically_linked':
            False,
            'modelled_functions':
            False,

            # Configurators can silence warnings in case they have specific
            # hard-coded options
            'warn_seeds':
            True,
            'warn_input_file':
            True,

            # Searcher options
            'use_cupa':
            True,
            'use_test_case_generator':
            True,
            'use_fault_injection':
            False,

            # This will add analysis overhead, so disable unless requested by the user.
            # Also enabled by default for Decree targets.
            'enable_pov_generation':
            options['enable_pov_generation']
        }

        for tf in options['target_files']:
            if not os.path.exists(tf):
                raise CommandError('%s does not exist' % tf)

            config['target_files'].append(os.path.basename(tf))

        # The configurator may modify the config dictionary here
        self._configurator.validate_configuration(config)

        display_marker_warning = self._target_path and \
                                 config['warn_input_file'] and \
                                 not (config['use_symb_input_file'] or config['sym_args'])

        if display_marker_warning:
            logger.warning(
                'You did not specify the input file marker @@. This marker is automatically substituted by '
                'a file with symbolic content. You will have to manually edit the bootstrap file in order '
                'to run the program on multiple paths.\n\n'
                'Example: %s @@\n\n'
                'You can also make arguments symbolic using the ``S2E_SYM_ARGS`` environment variable in '
                'the bootstrap file', self._target_path)

        if config['use_seeds'] and not config[
                'use_symb_input_file'] and config['warn_seeds']:
            logger.warning('Seed files have been enabled, however you did not '
                           'specify an input file marker (i.e. \'@@\') to be '
                           'substituted with a seed file. This means that '
                           'seed files will be fetched but never used. Is '
                           'this intentional?')

        if config['use_seeds'] and not os.path.isdir(config['seeds_dir']):
            os.mkdir(config['seeds_dir'])

        if config['enable_pov_generation']:
            config['use_recipes'] = True

        if self._target_path:
            # Do some basic analysis on the target
            self._configurator.analyze(config)

            # Create a symlink to the target program
            self._symlink_target_files(options['target_files'])

        # Create a symlink to the guest tools directory
        self._symlink_guest_tools()

        # Create a symlink to guestfs (if it exists)
        if not self._symlink_guestfs():
            config['has_guestfs'] = False

        # Render the templates
        logger.info('Creating launch script')
        self._create_launch_script(config)

        logger.info('Creating S2E configuration')
        self._create_lua_config(config)

        logger.info('Creating S2E bootstrap script')
        self._create_bootstrap(config)

        # Record some basic information on the project
        self._save_json_description(config)

        if config['use_recipes']:
            os.makedirs(config['recipes_dir'])
            project_name = os.path.basename(self._project_dir)
            cmd = RecipeCommand()
            cmd.handle_common_args(env=options['env'], project=project_name)
            cmd.handle()

        # Return the instructions to the user
        logger.success(_create_instructions(config))