Exemplo n.º 1
0
    def __init__(self, input_directory, target_path, fuzzing_strategies):
        """Inits AflFuzzInputDirectory.

    Args:
      input_directory: Directory passed to afl-fuzz containing corpus.
      target_path: Path to the fuzzer executable. Used to find seed corpus.
      fuzzing_strategies: fuzzing strategies to use.
    """

        self.input_directory = input_directory
        self.strategies = fuzzing_strategies

        # We only need to use this when a temporary input directory is made.
        # (ie: when there is an oversized testcase in the input).
        self.original_input_directory = None

        engine_common.unpack_seed_corpus_if_needed(
            target_path,
            self.input_directory,
            max_bytes=constants.MAX_FILE_BYTES)

        # Ensure there is a usable testcase in the input directory. This is needed
        # because locally (and possibly for new fuzzers on CF) the dummy file is not
        # always in the input directory, which prevents AFL from running.
        if not list_full_file_paths(self.input_directory):
            write_dummy_file(self.input_directory)

        # Make a new corpus without oversized inputs if needed.
        self.create_new_if_needed()

        # Decide if we should skip AFL's deterministic steps.
        self.skip_deterministic = True
        self._decide_skip_deterministic()
Exemplo n.º 2
0
    def run(self, initial_corpus_path, minimized_corpus_path, bad_units_path):
        """Run corpus pruning. Output result to directory."""
        if not shell.get_directory_file_count(initial_corpus_path):
            # Empty corpus, nothing to do.
            return

        # Set memory tool options and fuzzer arguments.
        engine_common.unpack_seed_corpus_if_needed(self.runner.target_path,
                                                   initial_corpus_path,
                                                   force_unpack=True)

        environment.reset_current_memory_tool_options(redzone_size=MIN_REDZONE,
                                                      leaks=True)
        self.runner.process_sanitizer_options()
        additional_args = self.runner.get_libfuzzer_flags()

        # Execute fuzzer with arguments for corpus pruning.
        logs.log("Running merge...")
        try:
            result = self.runner.minimize_corpus(
                additional_args,
                [initial_corpus_path],
                minimized_corpus_path,
                bad_units_path,
                CORPUS_PRUNING_TIMEOUT,
            )
        except engine.TimeoutError as e:
            raise CorpusPruningException(
                "Corpus pruning timed out while minimizing corpus\n" +
                e.message)
        except engine.Error as e:
            raise CorpusPruningException(
                "Corpus pruning failed to minimize corpus\n" + e.message)

        symbolized_output = stack_symbolizer.symbolize_stacktrace(result.logs)

        # Sanity check that there are files in minimized corpus after merging.
        if not shell.get_directory_file_count(minimized_corpus_path):
            raise CorpusPruningException(
                "Corpus pruning failed to minimize corpus\n" +
                symbolized_output)

        logs.log("Corpus merge finished successfully.",
                 output=symbolized_output)
Exemplo n.º 3
0
def get_corpus_directories(main_corpus_directory,
                           new_testcases_directory,
                           fuzzer_path,
                           fuzzing_strategies,
                           strategy_pool,
                           minijail_chroot=None,
                           allow_corpus_subset=True):
    """Return a list of corpus directories to be passed to the fuzzer binary for
  fuzzing."""
    corpus_directories = []

    corpus_directories.append(new_testcases_directory)

    # Check for seed corpus and add it into corpus directory.
    engine_common.unpack_seed_corpus_if_needed(fuzzer_path,
                                               main_corpus_directory)

    # Pick a few testcases from our corpus to use as the initial corpus.
    subset_size = engine_common.random_choice(
        engine_common.CORPUS_SUBSET_NUM_TESTCASES)

    if (allow_corpus_subset
            and strategy_pool.do_strategy(strategy.CORPUS_SUBSET_STRATEGY)
            and shell.get_directory_file_count(main_corpus_directory) >
            subset_size):
        # Copy |subset_size| testcases into 'subset' directory.
        corpus_subset_directory = create_corpus_directory('subset')
        copy_from_corpus(corpus_subset_directory, main_corpus_directory,
                         subset_size)
        corpus_directories.append(corpus_subset_directory)
        fuzzing_strategies.append(strategy.CORPUS_SUBSET_STRATEGY.name + '_' +
                                  str(subset_size))
        if minijail_chroot:
            bind_corpus_dirs(minijail_chroot, [main_corpus_directory])
    else:
        # Regular fuzzing with the full main corpus directory.
        corpus_directories.append(main_corpus_directory)

    if minijail_chroot:
        bind_corpus_dirs(minijail_chroot, corpus_directories)

    return corpus_directories
Exemplo n.º 4
0
    def run(self, initial_corpus_path, minimized_corpus_path, bad_units_path):
        """Run corpus pruning. Output result to directory."""
        if not shell.get_directory_file_count(initial_corpus_path):
            # Empty corpus, nothing to do.
            return

        # Set memory tool options and fuzzer arguments.
        engine_common.unpack_seed_corpus_if_needed(self.runner.fuzzer_path,
                                                   initial_corpus_path,
                                                   force_unpack=True)

        environment.reset_current_memory_tool_options(redzone_size=MIN_REDZONE,
                                                      leaks=True)
        self.runner.process_sanitizer_options()
        additional_args = self.runner.get_libfuzzer_flags()

        # Execute fuzzer with arguments for corpus pruning.
        logs.log('Running merge...')
        result = self.runner.merge(
            [minimized_corpus_path, initial_corpus_path],
            CORPUS_PRUNING_TIMEOUT,
            artifact_prefix=bad_units_path,
            tmp_dir=self.context.merge_tmp_dir,
            additional_args=additional_args)

        # Sanity check that we didn't time out.
        symbolized_output = stack_symbolizer.symbolize_stacktrace(
            result.output)
        if result.timed_out:
            raise CorpusPruningException(
                'Corpus pruning timed out while merging corpus: %s.' %
                symbolized_output)
        # Sanity check that we didn't error out and there are files in minimized
        # corpus after merging.
        if (result.return_code
                or not shell.get_directory_file_count(minimized_corpus_path)):
            raise CorpusPruningException(
                'Corpus pruning failed to merge corpus: %s.' %
                symbolized_output)
        logs.log('Corpus merge finished successfully.',
                 output=symbolized_output)
Exemplo n.º 5
0
    def prepare(self, corpus_dir, target_path, _):
        """Prepare for a fuzzing session, by generating options. Returns a
    FuzzOptions object.

    Args:
      corpus_dir: The main corpus directory.
      target_path: Path to the target.
      build_dir: Path to the build directory.

    Returns:
      A FuzzOptions object.
    """
        arguments = fuzzer.get_arguments(target_path)
        strategy_pool = strategy_selection.generate_weighted_strategy_pool(
            strategy_list=strategy.LIBFUZZER_STRATEGY_LIST,
            use_generator=True,
            engine_name=self.name)
        strategy_info = launcher.pick_strategies(strategy_pool, target_path,
                                                 corpus_dir, arguments)

        arguments.extend(strategy_info.arguments)

        # Check for seed corpus and add it into corpus directory.
        engine_common.unpack_seed_corpus_if_needed(target_path, corpus_dir)

        # Pick a few testcases from our corpus to use as the initial corpus.
        subset_size = engine_common.random_choice(
            engine_common.CORPUS_SUBSET_NUM_TESTCASES)

        if (not strategy_info.use_dataflow_tracing
                and strategy_pool.do_strategy(strategy.CORPUS_SUBSET_STRATEGY)
                and shell.get_directory_file_count(corpus_dir) > subset_size):
            # Copy |subset_size| testcases into 'subset' directory.
            corpus_subset_dir = self._create_temp_corpus_dir('subset')
            launcher.copy_from_corpus(corpus_subset_dir, corpus_dir,
                                      subset_size)
            strategy_info.fuzzing_strategies.append(
                strategy.CORPUS_SUBSET_STRATEGY.name + '_' + str(subset_size))
            strategy_info.additional_corpus_dirs.append(corpus_subset_dir)
        else:
            strategy_info.additional_corpus_dirs.append(corpus_dir)

        # Check dict argument to make sure that it's valid.
        dict_argument = fuzzer_utils.extract_argument(arguments,
                                                      constants.DICT_FLAG,
                                                      remove=False)
        if dict_argument and not os.path.exists(dict_argument):
            logs.log_error('Invalid dict %s for %s.' %
                           (dict_argument, target_path))
            fuzzer_utils.extract_argument(arguments, constants.DICT_FLAG)

        # If there's no dict argument, check for %target_binary_name%.dict file.
        if (not fuzzer_utils.extract_argument(
                arguments, constants.DICT_FLAG, remove=False)):
            default_dict_path = dictionary_manager.get_default_dictionary_path(
                target_path)
            if os.path.exists(default_dict_path):
                arguments.append(constants.DICT_FLAG + default_dict_path)

        return LibFuzzerOptions(corpus_dir, arguments,
                                strategy_info.fuzzing_strategies,
                                strategy_info.additional_corpus_dirs,
                                strategy_info.extra_env,
                                strategy_info.use_dataflow_tracing,
                                strategy_info.is_mutations_run)
Exemplo n.º 6
0
 def _unpack_seed_corpus_if_needed(self, *args, **kwargs):
   return engine_common.unpack_seed_corpus_if_needed(
       self.FUZZ_TARGET_PATH, self.CORPUS_DIRECTORY, *args, **kwargs)