---
# System prepended metadata

title: Запуск фаззера на один раунд
tags: [run, fuzzer]

---

# Запуск фаззера на один раунд

###### tags: `fuzzer`, `run`

## Создание сессии

Файл реализации - [`fuzz_task.py`](https://github.com/google/clusterfuzz/blob/master/src/python/bot/tasks/fuzz_task.py)

Для запуска фаззера используется класс `FuzzingSession`

![](https://i.imgur.com/vEOwaHl.png)

В качестве аргументов в конструктор класса `FuzzingSession` передаются:
- `fuzzer_name` - Имя фаззера (libfuzzer, afl, ...)
- `job_name` - Название доп. тулзы/санитайзера (HWASAN, ASAN, CFI, MSAN, TSAN, UBSAN)
- `test_timeout` - Максимальное время, через которое процесс фаззера должен быть убит

## Обновление компонентов

Все бинарные компоненты и скрипты хранятся в Google Cloud Storage (GCS). Для обновления компонентов необходимо скачать оттуда архив и распаковать его в соответствующую папку

### Обновление fuzzing engine

Сначала обновляются необходимые компоненты фаззера (fuzzing engine). Обновлённая версия скачивается и распаковывается в папку его установки. За это отвечает функция [`update_fuzzer_and_data_bundles`](https://github.com/google/clusterfuzz/blob/master/src/python/bot/tasks/setup.py#L465).

### Обновление фаззеров

После обновления основых компонентов проверяется наличие обновлённых бинарников в GCS. Процессы скачивания бинарников, настройки переменных среды, выбора нового фаззера для запуска в clusterfuzz осуществляются функцией [`setup_build`](https://github.com/google/clusterfuzz/blob/master/src/python/build_management/build_manager.py#L1397). В ней вычисляется тип сборки: *Custom*, *Funcsia*, *Regular*, *RemoteRegular*. Затем вызывается соотвествующий конструктор класса. После этого вызывается метод класса `setup`, осуществляющий вышеперечисленные действия.

![](https://i.imgur.com/FvnMXk2.png)

В процессе сборки (setup build) существуют следующие этапы:
- Скачивание архива с фаззерами
- Выбор нового фаззера для запуска
- Установка переменных среды

В [`_unpack_build`](https://github.com/google/clusterfuzz/blob/master/src/python/build_management/build_manager.py#L464) осуществляются первые два этапа. Скачивается архив с фаззерами (если локально нет файлов с этой ревизией) и распаковывается в *build_dir*. Далее из *build_dir* функцией [`_set_random_fuzz_target_for_fuzzing_if_needed`](https://github.com/google/clusterfuzz/blob/master/src/python/build_management/build_manager.py#L271)  выбирается фаззер (fuzz target) для запуска (подробнее [здесь](https://hackmd.io/@reverse-clusterfuzz/HktT2JF8U)) и устанавливается переменная среды `FUZZ_TARGET`.

## Фаззинг

После обновления всех копонентов выполняется фаззинг. Для libFuzzer он реализуется функцией [`do_engine_fuzzing`](https://github.com/google/clusterfuzz/blob/master/src/python/bot/tasks/fuzz_task.py#L1575), поскольку libFuzzer регистрируется при старте в `_ENGINES`

```python=
def run():
  """Initialise builtin fuzzing engines."""
  engine.register('libFuzzer', libFuzzer_engine.LibFuzzerEngine)
  engine.register('honggfuzz', honggfuzz_engine.HonggfuzzEngine)
  engine.register('syzkaller', syzkaller_engine.SyzkallerEngine)

```

Сначала происходит скачивание *корпусов* (corpus) из GCS. Корпуса будут использоваться мутатором для генерации входных данных (fuzz input)

```python=
    # Synchronize corpus files with GCS
    sync_corpus_directory = builtin.get_corpus_directory(
        self.data_directory, self.fuzz_target.project_qualified_name())
    self.sync_corpus(sync_corpus_directory)

```

Потом происходит непосредственно процесс фаззинга со сбором крешей и статистики

```python=
    # Do the actual fuzzing.
    for fuzzing_round in range(environment.get_value('MAX_TESTCASES', 1)):
      logs.log('Fuzzing round {}.'.format(fuzzing_round))
      result, current_fuzzer_metadata, fuzzing_strategies = run_engine_fuzzer(
          engine_impl, self.fuzz_target.binary, sync_corpus_directory,
          self.testcase_directory)
      fuzzer_metadata.update(current_fuzzer_metadata)

      # Prepare stats.
      testcase_run = engine_common.get_testcase_run(result.stats, result.command)
```

В функции [`run_engine_fuzzer`](https://github.com/google/clusterfuzz/blob/master/src/python/bot/tasks/fuzz_task.py#L1287). Есть две стадии: подготовка (`engine_impl.prepare`) и фаззинг (`engine_impl.fuzz`). На стадии подготовки выбираются стратегии для эффективного фаззинга, проверется наличие словарей, количество тест-кейсов в *корпусе* ([файл стратегий](https://github.com/google/clusterfuzz/blob/master/src/python/fuzzing/strategy.py)). На стадии фаззинга запускается фаззер, который может работать не более чем `max_time` секунд. То есть либо он отработает 1 тест-кейс, либо будет остановлен по истечении времени. Всё это реализуется классом [`LibFuzzerEgine`](https://github.com/google/clusterfuzz/blob/master/src/python/bot/fuzzers/libFuzzer/engine.py#L84). Для запуска и остановки фаззера используется модуль subprocess в функции [`ProcessRunner.run_and_wait`](https://github.com/google/clusterfuzz/blob/master/src/python/system/new_process.py#L301) После завершения работы фаззера парсится его вывод, собираются необходимые характеристики. Всё это происходит тесткейс за тесткейсом. Когда все тесткейсы отработаны, раунд завершается. Настройки фаззеров - сколько тесткейсов по умолчанию, количество потоков, задержки - находятся в [`setup.py`](https://github.com/google/clusterfuzz/blob/master/src/local/butler/scripts/setup.py)