From 0fd8e286b989d605b58f04af46e9be9c6a3060ae Mon Sep 17 00:00:00 2001 From: Daniil Kutz Date: Wed, 24 Jan 2024 19:18:48 +0300 Subject: [PATCH] Refactor docs --- docs/config/index.md | 483 ++++++ docs/index.md | 3332 +-------------------------------------- docs/install/index.md | 102 ++ docs/sydr-fuzz/index.md | 1040 ++++++++++++ docs/sydr/index.md | 1387 ++++++++++++++++ 5 files changed, 3020 insertions(+), 3324 deletions(-) create mode 100644 docs/config/index.md create mode 100644 docs/install/index.md create mode 100644 docs/sydr-fuzz/index.md create mode 100644 docs/sydr/index.md diff --git a/docs/config/index.md b/docs/config/index.md new file mode 100644 index 0000000..4d0b3f9 --- /dev/null +++ b/docs/config/index.md @@ -0,0 +1,483 @@ +* TOC +{:toc} + +# Конфигурационный файл и структура выходного проекта + +Конфигурационный файл (`sydr-fuzz.toml`) используется для задания опций +фаззера и Sydr. Все пути задаются либо абсолютно, либо относительно +директории, в которой расположен конфигурационный файл. Для настройки запуска +различных инструментов в этом файле указываются таблицы `[sydr]`, `[libfuzzer]`, +`[aflplusplus]` (или список таблиц `[[aflplusplus]]`), `[atheris]`, `[jazzer]`, `[jazzer_js]` и `[cov]`. Конфигурационный файл не может +одновременно содержать таблицы `[libfuzzer]` и `[aflplusplus]`, а также +`[atheris]`, `[jazzer]` и`[jazzer_js]` с какой-либо другой таблицей (на примере ниже приведены все таблицы +для краткости). + +```toml +exit-on-time = 7200 + +[sydr] +args = "-j 4" +target = "/target_sydr @@" +jobs = 3 + +[aflplusplus] +args = "-t 5000 -i /corpus" +target = "/target_afl @@" +jobs = 6 + +[libfuzzer] +path = "/target_fuzzer" +args = "-dict=/json.dict -jobs=6 /corpus" + +[atheris] +path = "/target.py" +args = "/corpus -jobs=4 -workers=4" + +[jazzer] +args = "--cp=/out --asan -jobs=4 /corpus" +target_class = "ExampleFuzzerNative" + +[jazzer_js] +path = "/target.js" +args = "-i=mylib /corpus -- -jobs=4 -workers=4" + +[cov] +target = "/instrumented_target @@" +``` + +**exit-on-time** - опциональный параметр указывает время в секундах. Если в +течение этого времени покрытие не растет, фаззинг автоматически завершается. + +**out** - опциональный параметр указывает путь до выходной директории с +проектом, где содержатся артефакты и результаты работы фаззинга. Если не +указывать эту опцию, то проект создастся в текущей директории с именем +`-out`. Данный параметр дублирует аргумент командной строки `--output`, +который считается более приоритетным, чем значение из конфигурационного файла. + +### Sydr + +```toml +[sydr] +args = "-j 4" +target = "/target_sydr @@" +jobs = 3 +timeout = 1000 +cache = true +optimistic = true +fuzzmem = false +wait_jobs = false +solving_limit = false +symaddr = 20 +[sydr.env] + CLASSIC_ENVVAR = "XXX" +``` + +Таблица `[sydr]` может содержать следующие параметры: + +**args** - аргументы Sydr. Опции `--sym-file` и `--log-file` задаются +автоматически, их указывать не надо. + +**target** - строка запуска обертки для Sydr. Вместо имени символьного входного +файла следует использовать `@@`. + +**jobs** - число процессов Sydr для запуска (по умолчанию 1). Всего запускается +**jobs** процессов Sydr в `-j` (задается в **args**) потоков каждый. + +**timeout** - тайм-аут в секундах, по истечении которого процесс Sydr будет +остановлен. Если параметр не указан, выставляется 20 минут (1200 секунд). + +**cache** - булевый параметр (по умолчанию включен), который включает кэш +инвертированных переходов. + +**optimistic** - булевый параметр (по умолчанию включен), который включает +оптимистичные решения. + +**fuzzmem** - булевый параметр (по умолчанию включен), который включает режим +фаззинга символьных адресов. + +**wait_jobs** - булевый параметр (по умолчанию включен), который включает +приостановление построения предиката пути, когда набрано достаточно +необработанных запросов к математическому решателю. + +**solving_limit** - булевый параметр (по умолчанию включен), который включает 60 +секундный тайм-аут на суммарное время, проведенное в решателе. + +**symaddr** - целочисленный параметр, который включает режим обработки символьных +адресов раз в N запусков Sydr (по умолчанию N = 25). Чтобы выключить этот режим, +необходимо указать N = 0. + +**[sydr.env]** - таблица, содержащая значения переменных окружения, которые будут +выставлены для каждого запускаемого процесса Sydr. Каждая строка таблицы задаёт +строковую переменную, имя которой совпадает с именем соответствующей переменной окружения. +Значения переменных окружения можно задавать также в системных переменных окружения. +При этом значения, заданные в файле конфигурации, более приоритетны, чем +значения, заданные в системных переменных окружения. + +### AFL++ + +```toml +[aflplusplus] +path = "/afl" +args = "-t 5000 -i /corpus" +target = "/target_afl @@" +cmin = 8 +jobs = 6 +foreign = ["/path/to/foreign_fuzzer/syncdir"] +[aflplusplus.env] + AFL_PRINT_FILENAMES = "1" + AFL_MAP_SIZE = "10000000" +``` + +Таблица `[aflplusplus]` может содержать следующие параметры: + +**args** - аргументы AFL++. Необходимым аргументом является опция `-i` для +указания входного корпуса. Дополнительно можно +указать опции для инструментации (`-Q`, `-O` для бинарной инструментации), +тайм-аутов (`-t 5000` миллисекунд) и другие. + +**target** - строка запуска обертки для AFL++. Вместо имени входного файла +следует использовать `@@`. Если обертка читает входные данные со стандартного +потока ввода, то `@@` указывать не нужно. + +**cmin** - булевый/целочисленный параметр (по умолчанию `true`), который включает минимизацию +входного корпуса при старте гибридного фаззинга. Этот параметр также может использоваться для +указания числа потоков для параллельного запуска утилиты `afl-cmin`. Если параметр установлен +в `true`, то используется половина всех доступных ядер на машине. Если указанное число потоков +больше, чем доступно ядер на машине, то для распараллеливания `afl-cmin` используются все ядра. +Если параметр выключен (`false` или `0`), то минимизация корпуса перед запуском гибридного +фаззинга не производится, а при вызове команды `cmin` используется половина всех доступных ядер. + +**jobs** - число процессов AFL++ для запуска (по умолчанию 1). + +Для таблицы `[aflplusplus]` запуск нескольких +процессов AFL++ осуществляется автоматически в соответствии с +[рекомендациями](https://github.com/AFLplusplus/AFLplusplus/blob/stable/docs/fuzzing_in_depth.md#c-using-multiple-cores): +запускается один основной фаззер (`afl_main-worker`) и `jobs-1` второстепенных процессов +(`afl_s-worker`), каждый второстепенный фаззер имеет свой набор +генерируемых автоматически опций с настройками фаззинга. + +Одновременно нельзя запустить более 64 процессов AFL++, так как это очень +неэффективная стратегия для гибридного фаззинга +([объяснение](https://github.com/AFLplusplus/AFLplusplus/blob/stable/docs/fuzzing_in_depth.md#c-using-multiple-cores)). + +**path** - путь до AFL++ и его утилит. Параметр не обязателен, если путь +добавлен в `$PATH` (в докере `sydr/ubuntu20.04-sydr-fuzz` уже добавлен). + +**foreign** - директории с очередью сторонних фаззеров (опция `-F` AFL++). Параметр может быть +строкой или массивом строк. Путь до директорий с очередью сторонних фаззеров может быть +указан относительно конфигурационного файла. Синхронизация со сторонними фаззерами доступна только +для главного процесса AFL++ (-M), поэтому при указании **foreign** требуется несколько запущенных +экземпляров AFL++ (**jobs** > 1). + +**[aflplusplus.env]** - таблица, содержащая значения переменных окружения, которые будут +выставлены для каждого запускаемого процесса AFL++. Каждая строка таблицы задаёт +строковую переменную, имя которой совпадает с именем соответствующей переменной окружения. + +Для настройки AFL++ можно использовать различные переменные окружения. Переменные +`AFL_SKIP_CPUFREQ=1`, `AFL_NO_UI=1`, `AFL_PRINT_FILENAMES`, `AFL_AUTORESUME`, +`AFL_MAP_SIZE=65536` выставляются автоматически по необходимости. `AFL_MAP_SIZE` +можно задать своим значением, однако это в большинстве случаев не требуется, т.к. +afl-fuzz определяет размер битовой карты автоматически. Переменная +`AFL_PRINT_FILENAMES=1` позволяет во время минимизации следить, какой файл +обрабатывается в данный момент. Это удобно, когда в корпусе находятся входные +файлы, приводящие к аварийному завершению, что приводит к ошибке работы +минимизации. При помощи `AFL_PRINT_FILENAMES=1` можно будет найти такие файлы +и удалить их. Также для тяжелых фаззинг целей можно выставить большое +значение переменной `AFL_FORKSRV_INIT_TMOUT`, отвечающей за максимальное время +инициализации форк-сервера AFL++, а также выставить переменную `AFL_MAP_SIZE=10000000`. +Для лучшего взаимодействия AFL++ и Sydr можно уменьшить интервал +синхронизации `AFL_SYNC_TIME` (указывается в минутах, по умолчанию 30 минут). +Также могут быть полезными переменные `AFL_DISABLE_TRIM`, `AFL_SHUFFLE_QUEUE`, +`AFL_NO_AFFINITY`. + +По умолчанию задаются также переменные среды + +`ASAN_OPTIONS="hard_rss_limit_mb=2048,abort_on_error=1,detect_leaks=0,` + +`malloc_context_size=0,symbolize=0,allocator_may_return_null=1"` + +`UBSAN_OPTIONS="halt_on_error=0,abort_on_error=0,malloc_context_size=0,` + +`allocator_may_return_null=1"` + +Значения по умолчанию можно менять путем переопределения их в таблице `[aflplusplus.env]` или в системных +переменных окружения. +При этом наибольший приоритет имеют значения, заданные в файле конфигурации; средний приоритет имеют +значения, заданные в системных переменных окружения; низший приоритет имеют значения по умолчанию. +Полный список переменных окружения приведен +[здесь](https://github.com/AFLplusplus/AFLplusplus/blob/stable/docs/env_variables.md). + +Значение некоторых параметров `ASAN_OPTIONS`: + +**hard_rss_limit_mb** - задает ограничение памяти анализируемого приложения в Мб (по +умолчанию 2 Гб). Чтобы снять ограничение памяти, можно указать 0. Данная опция +помогает Casr обнаруживать oom и отличать аварийное завершение от oom на шаге +`sydr-fuzz casr`. Однако AFL++ не поддерживает ограничение памяти через +`ASAN_OPTIONS`. Для обработки oom в AFL++ рекомендуется выключить swap. Тогда +программа будет убиваться системным OOM Killer. + +**detect_leaks** - булевый параметр (по умолчанию выключен), который включает +режим фаззинга, при котором срабатывания leak-санитайзера считаются аварийными +завершениями. + +**allocator_may_return_null** - булевый параметр (по умолчанию включен), который +разрешает аллокатору возвращать нулевой указатель. + +Задание параметров `halt_on_error=1,abort_on_error=1` для `UBSAN_OPTIONS` +включает режим фаззинга, при котором срабатывания ubsan-санитайзера приводят +к аварийным завершениям. + +Конфигурация AFL++ может быть задана как с помощью одной таблицы `[aflplusplus]`, +так и с помощью списка таблиц `[[aflplusplus]]`. В первом случае все параметры, +заданные в таблице, применяются ко всем процессам AFL++. Во втором случае первая +таблица является основной и задаёт параметры для основного (main) процесса AFL++ и некоторого +числа дополнительных (secondary) процессов, а каждая следующая таблица позволяет запустить +определённое число дополнительных (secondary) процессов фаззера со своими параметрами. + +Пример с несколькими таблицами: + +```toml +[[aflplusplus]] +path = "/afl" +args = "-t 5000 -i /corpus" +target = "/target_afl @@" +cmin = true +jobs = 6 +[aflplusplus.env] + AFL_PRINT_FILENAMES = "1" + +[[aflplusplus]] +args = "-t 10000" +target = "/target_afl_other @@" +jobs = 2 +[aflplusplus.env] + AFL_MAP_SIZE = "10000000" +``` + +Задание различных опций для дополнительных процессов фаззера +может быть полезно при использовании инструментации [CmpLog](https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.cmplog.md) ([RedQueen](https://github.com/RUB-SysSec/redqueen)) +или [laf-intel](https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.laf-intel.md) (COMPCOV). + +Пример с несколькими таблицами для CmpLog: + +```toml +[[aflplusplus]] +args = "-i /corpus -t 2000" +target = "/target_afl @@" +jobs = 4 + +[[aflplusplus]] +args = "-t 2000 -c /target_afl_cmplog -m none" +target = "/target_afl @@" +jobs = 2 +``` + +Первая таблица списка `[[aflplusplus]]` может содержать все перечисленные выше +параметры. Каждая дополнительная таблица списка `[[aflplusplus]]` может содержать +все перечисленные выше параметры, кроме **path** и **cmin** (эти параметры задаются +только для первой таблицы списка). + +При использовании списка `[[aflplusplus]]` директории для входного корпуса +(опция `-i` в **args**) должны совпадать во всех таблицах (кроме того, достаточно +задать опцию только для первой таблицы). + +Для первой таблицы списка запускается один основной фаззер (`afl_main-worker`) +и `jobs-1` второстепенных процессов (`afl_s-worker`), каждый второстепенный +фаззер имеет свой набор генерируемых автоматически опций с настройками фаззинга. +Для всех остальных таблиц списка `[[aflplusplus]]` производится запуск `jobs` +второстепенных процессов (`afl_s-worker`), каждый второстепенный фаззер +имеет одинаковый набор заданных в этой таблице опций. Опция **foreign** может +быть указана только для главной таблицы. + +### libFuzzer + +```toml +[libfuzzer] +path = "/target_fuzzer" +args = "-dict=/json.dict -jobs=6 /corpus" +cmin = true +set_cover_merge = true +[libfuzzer.env] + ASAN_OPTIONS = "allocator_may_return_null=0" +``` + +Таблица `[libfuzzer]` может содержать следующие параметры: + +**path** - путь до libFuzzer обертки. + +**args** - аргументы libFuzzer. В аргументах могут быть указаны входные +директории с корпусами. Выходная директория с корпусом автоматически создается в +каталоге с проектом (и подставляется в аргументы libFuzzer). В выходной корпус +будут минимизированы все входные корпуса. Число процессов libFuzzer можно +контролировать через опцию `-jobs=N`, +которая указывает на то, что должно быть выполнено N запусков фаззинга до конца +(пока не найден баг или исчерпан лимит времени/числа итераций). Запуски фаззинга +распределяются между несколькими процессами libFuzzer (по умолчанию используется +не больше половины доступных ядер), число которых можно задать через +`-workers=N`. Если цель для фаззинга аварийно завершается, имеет смысл +использовать опции `-jobs=M -workers=N`, где N - число процессов libFuzzer, а +M - число аварийных завершений, зависаний и oom, по достижению которого фаззинг +будет завершен. Подробное описание опций libFuzzer можно найти в его +[документации](https://www.llvm.org/docs/LibFuzzer.html). + +**cmin** - булевый/целочисленный параметр (по умолчанию `true`), который включает +минимизацию входных корпусов в выходной корпус проекта. Если параметр выключен, +то происходит просто копирование входных корпусов в выходной корпус проекта. +Минимизацию корпуса, например, можно выключить, когда libFuzzer не справляется +минимизировать корпус. + +**set_cover_merge** - булевый параметр (по умолчанию выключен), который +позволяет использовать для минимизации опцию libFuzzer `set_cover_merge`. Если +параметр выключен, для минимизации используется опция `merge`. + +**[libfuzzer.env]** - таблица, содержащая значения переменных окружения, которые будут +выставлены для каждого запускаемого процесса libFuzzer. Каждая строка таблицы задаёт +строковую переменную, имя которой совпадает с именем соответствующей переменной окружения. + +По умолчанию задаётся переменная среды `ASAN_OPTIONS="allocator_may_return_null=1"`. + +Значения по умолчанию можно менять путем переопределения их в таблице `[libfuzzer.env]` или в системных +переменных окружения. Значения опций `hard_rss_limit_mb` и `detect_leaks` нужно задавать только через +соответствующие аргументы libFuzzer: `-rss_limit_mb` и `-detect_leaks`. +При этом наибольший приоритет имеют значения, заданные в файле конфигурации; средний приоритет имеют +значения, заданные в системных переменных окружения; низший приоритет имеют значения по умолчанию. + +### Atheris + +```toml +[atheris] +path = "/target_fuzzer" +args = "-dict=/json.dict -jobs=6 /corpus" +cmin = true +set_cover_merge = true +ld_preload = false +[atheris.env] + ASAN_OPTIONS = "allocator_may_return_null=0" +``` + +Таблица `[atheris]`, помимо всех параметров таблицы `[libfuzzer]`, содержит один +дополнительный параметр: + +**ld_preload** - булевый параметр (по умолчанию включен), который позволяет при +запуске Python-кода для фаззинга, сбора покрытия или анализа аварийных +завершений устанавливать переменную среды `LD_PRELOAD` равной пути до библиотеки +`asan_with_fuzzer.so`, необходимой при работе с кодом, имеющим расширения на +языках C/C++, для их инструментации. + +Для Atheris по умолчанию задаётся переменная среды + +`ASAN_OPTIONS="hard_rss_limit_mb=0,abort_on_error=1,detect_leaks=0,malloc_context_size=0,` + +`allocator_may_return_null=1"` + +Значения по умолчанию можно менять путем переопределения их в таблице `[atheris.env]` или в системных +переменных окружения. +При этом наибольший приоритет имеют значения, заданные в файле конфигурации; средний приоритет имеют +значения, заданные в системных переменных окружения; низший приоритет имеют значения по умолчанию. + +### Jazzer + +```toml +[jazzer] +path = "/path/to/jazzer" +agent_path = "/path/to/jazzer_standalone_deploy.jar" +args = "--cp=/path/to/java/classes/ --asan -jobs=6 /corpus" +target_class = "TargetClass" +cmin = true +set_cover_merge = true +java = "/path/to/jvm/launcher/java" +jacocolib = "/path/to/jacoco/lib" +[jazzer.env] + LD_LIBRARY_PATH = "/path/to/native/libraries/" +``` + +**path** - путь до бинарного файла jazzer (по умолчанию: `/usr/local/bin/jazzer`). + +**agent_path** - путь до jazzer API (по умолчанию: `/usr/local/lib/jazzer_standalone_deploy.jar`). + +**args** - аргументы jazzer и libFuzzer. + +**target_class** - название Java класса с методом `fuzzerTestOneInput`. + +**cmin** и **set_cover_merge** - как у libFuzzer. + +**java** - путь до Java лаунчера (по умолчанию берется из `PATH`). + +**jacocolib** - путь до jar файлов библиотеки jacoco (необходимо для сбора +покрытия, по умолчанию: `/usr/local/lib/jacoco/lib`). + +Jazzer поддерживает фаззинг C/C++ библиотек, загруженных JVM, например, через `System.load()`. +Иногда требуется добавить пути, в которых будет производится поиск разделяемых +библиотек. Сделать это можно с помощью таблицы `[jazzer.env]`, указав значение +переменной среды `LD_LIBRARY_PATH`. + +Для Jazzer по умолчанию задаётся переменная среды + +`ASAN_OPTIONS="hard_rss_limit_mb=0,abort_on_error=1,detect_leaks=0,malloc_context_size=0,` + +`allocator_may_return_null=1"` + +Значения по умолчанию можно менять путем переопределения их в таблице `[jazzer.env]` или в системных +переменных окружения. +При этом наибольший приоритет имеют значения, заданные в файле конфигурации; средний приоритет имеют +значения, заданные в системных переменных окружения; низший приоритет имеют значения по умолчанию. + +### Jazzer.js + +```toml +[jazzer_js] +path = "/target_fuzzer" +args = "-i=target_lib /corpus -- -dict=/json.dict -jobs=6" +cmin = true +set_cover_merge = true +ld_preload = false +[jazzer_js.env] + ASAN_OPTIONS = "allocator_may_return_null=0" +``` + +**path** - путь до Jazzer.js обертки. + +**args** - аргументы Jazzer.js и libFuzzer. Сначала перечисляются аргументы +Jazzer.js, затем ставится разделитель "--", далее перечисляются аргументы +libFuzzer. + +**ld_preload** - булевый параметр (по умолчанию включен), который позволяет при +запуске JavaScript-кода для фаззинга, сбора покрытия или анализа аварийных +завершений устанавливать переменную среды `LD_PRELOAD` равной пути до библиотеки +`libclang_rt.asan-x86_64.so`, необходимой при работе с кодом, имеющим расширения на +языках C/C++, для их инструментации. + +Для Jazzer.js по умолчанию задаётся переменная среды + +`ASAN_OPTIONS="hard_rss_limit_mb=0,abort_on_error=1,detect_leaks=0,malloc_context_size=0,` + +`allocator_may_return_null=1"` + +Значения по умолчанию можно менять путем переопределения их в таблице `[jazzer_js.env]` или в системных +переменных окружения. +При этом наибольший приоритет имеют значения, заданные в файле конфигурации; средний приоритет имеют +значения, заданные в системных переменных окружения; низший приоритет имеют значения по умолчанию. + +### Coverage + +```toml +[cov] +target = "/instrumented_target @@" +[cov.env] + CLASSIC_ENVVAR = "XXX" +``` + +Таблица `[cov]` содержит следующие параметры: + +**target** - строка запуска инструментированного для сбора покрытия целевого +исполняемого файла. При сборке исполняемого файла следует использовать флаги: +`-fprofile-instr-generate -fcoverage-mapping`. + +**[cov.env]** - таблица, содержащая значения переменных окружения, которые будут +выставлены при сборе покрытия. Каждая строка таблицы задаёт строковую переменную, +имя которой совпадает с именем соответствующей переменной окружения. + +Значения переменных окружения можно задавать также в системных переменных окружения. +При этом значения, заданные в файле конфигурации, более приоритетны, чем +значения, заданные в системных переменных окружения. + diff --git a/docs/index.md b/docs/index.md index 1560a1f..ba889c3 100644 --- a/docs/index.md +++ b/docs/index.md @@ -28,3335 +28,19 @@ Гайды, публикации, презентации, трофеи, бенчмарки и другую полезную информацию можно найти на [сайте](https://sydr-fuzz.github.io). +# Документация + +- [docs/sydr-fuzz.md](docs/sydr-fuzz.md) - description, options and usage of Sydr-Fuzz framework. +- [docs/install.md](docs/install.md) - dependencies and installation of Sydr-Fuzz release. +- [docs/config.md](docs/config.md) - Sydr-Fuzz configuration file specification. +- [docs/sydr.md](docs/sydr.md) - documentation for Sydr - a DSE tool in Sydr-Fuzz framework. +- [docs/misc.md](docs/misc.md) - manual for creating fuzztargets and hybrid fuzzing setup. + # Трофеи Список трофеев можно найти в репозитории [OSS-Sydr-Fuzz](https://github.com/ispras/oss-sydr-fuzz/blob/master/TROPHIES.md). -# Оглавление - -* TOC -{:toc} - -# Минимальные системные требования - -- Операционная система: Ubuntu 18.04/20.04/22.04, Astra 1.7, ALT Workstation 10.0 и - аналоги - 64-bit. -- Процессор (CPU): Intel Core i3 или аналогичный AMD. -- Оперативная память (RAM): 4 ГБ. - -# Рекомендуемые системные требования - -- Операционная система: Ubuntu 18.04/20.04/22.04 - 64-bit. -- Процессор (CPU): Intel Core i7 (Desktop) или аналогичный AMD. -- Оперативная память (RAM): 32 ГБ и больше. - -# Зависимости - -Перед установкой инструмента установите следующие зависимости. - - $ sudo apt install gcc-multilib binutils lsb-release gdb lcov - -Для корректной работы лицензионного USB ключа требуется установить последнюю -версию -[Sentinel HASP/LDK Run-time Environment](https://supportportal.thalesgroup.com/csm?id=kb_search&u_related_product_names=50303b92db852e00d298728dae96199d&query=kbcat_drivers_%26_runtime_packages&_runtime_packages&spa=1&u_all_related_operating_systems=66689e154fe293409a523c728110c74c) -(перед установкой желательно вынуть USB ключ, и вставить его назад по завершению -установки): - - $ tar xf aksusbd*.tar.gz - $ cd aksusbd* - $ sudo ./dinst - -Для работы лицензионного ключа на Astra Linux требуется разрешить трассировку -ptrace: Пуск -> Панель управления -> Безопасность -> Политика безопасности -> -Настройка безопасности -> Системные параметры -> Снять галочку с "Блокировать -трассировку ptrace для всех пользователей". - -# Установка - -Для установки достаточно распаковать zip-архив. - - $ unzip sydr.zip - -# Использование sydr-fuzz - -Рекомендуется воспользоваться нашим докером `sydr/ubuntu20.04-sydr-fuzz`. -Докер можно выкачать с помощью команды: - - $ docker pull sydr/ubuntu20.04-sydr-fuzz - -`DockerFile` можно найти [тут](https://github.com/ispras/oss-sydr-fuzz/blob/master/docker/ubuntu20.04-sydr-fuzz/Dockerfile). -Затем запускать гибридный фаззинг внутри него. Дальнейшая документация -основывается на использовании нашего докера. Далее перечислены зависимости, -которые нужно установить, если запуск производится на другой системе. - -## Зависимости libFuzzer - -Sydr-fuzz можно запускать просто на системе (требуется LLVM 13+). Однако -настоятельно рекомендуем установить -[Docker](https://docs.docker.com/engine/install/) для сборки и запуска фаззинга -целей в изолированном окружении. - -Для корректного ранжирования входных данных, подающихся от libFuzzer к Sydr, -требуется сборка LLVM, содержащая добавленный нами -[коммит](https://github.com/llvm/llvm-project/commit/827ccc93b8f378c36a356a3025db65bbd1f031e8#diff-0bc43509353a4f382ac6e3d2847f195de7a51d44c74a7baa4f0f33da17451cc6). -Данные изменения добавляют печать входных данных от Sydr, которые увеличивают -покрытие кода с точки зрения фаззера. Эта функциональность присутствует с релиза -[LLVM 13.0.0](https://github.com/llvm/llvm-project/releases/tag/llvmorg-13.0.0). -Более ранние версии LLVM также поддерживаются, но ранжирование не будет -эффективным. - -## Зависимости AFL++ - -Фаззер AFL++ и все необходимые утилиты уже установлены в нашем докере -`sydr/ubuntu20.04-sydr-fuzz`. При запуске на другой системе потребуется -скачать и установить AFL++ (можно из [репозитория](https://github.com/AFLplusplus/AFLplusplus)). -AFL++ активно разрабатывается, поэтому желательно использовать наиболее новую версию. -Для запуска Sydr-fuzz с AFL++ также необходимы утилиты минимизации корпуса `afl-cmin` -и построения битовой карты `afl-showmap`. Вместе с фаззером afl-fuzz они должны находиться -в одной директории, путь до которой либо есть в `$PATH`, либо указан в конфигурационном файле. - -## Зависимости Atheris - -Библиотека фаззинга Atheris и все необходимые утилиты уже установлены в нашем докере -`sydr/ubuntu20.04-sydr-fuzz`. При запуске на другой системе потребуется скачать -и установить Atheris (можно из [репозитория](https://github.com/google/atheris)). -Для работы sydr-fuzz с Atheris также необходима библиотека сбора покрытия -[Coverage](https://coverage.readthedocs.io/en/latest/install.html). - -## Зависимости Jazzer - -Фаззер Jazzer и все необходимые утилиты уже установлены в нашем докере -`sydr/ubuntu20.04-sydr-fuzz`. При запуске на другой системе потребуется скачать -и установить Jazzer (можно из [репозитория](https://github.com/CodeIntelligenceTesting/jazzer)). -Для сбора покрытия понадобится библиотека [Jacoco](https://github.com/jacoco/jacoco). - -## Зависимости Jazzer.js - -Фаззер Jazzer.js и все необходимые утилиты уже установлены в нашем докере -`sydr/ubuntu20.04-sydr-fuzz`. При запуске на другой системе потребуется скачать -и установить Jazzer.js (можно из [репозитория](https://github.com/CodeIntelligenceTesting/jazzer.js)). - -## Опции - -Доступные опции: - - $ sydr-fuzz -h - ISP RAS - Continuous hybrid fuzzing and dynamic analysis for security development lifecycle - - USAGE: - sydr-fuzz [OPTIONS] - - OPTIONS: - -c, --config Configuration file [default: sydr-fuzz.toml] - -h, --help Print help information - -l, --log-level Logging level [default: info] [possible values: minimal, - info, debug, trace] - -o, --output Output project directory with artifacts [default: - -out] - -V, --version Print version information - - SUBCOMMANDS: - casr Triage, deduplicate, cluster, and create reports for crashes and - UBSAN runtime errors - cmin Minimize corpus - cov-export Collect and export corpus coverage in JSON or lcov trace file format - cov-html Generate HTML coverage report - cov-report Collect corpus coverage and display summary - cov-show Collect and show line by line corpus coverage - help Print this message or the help of the given subcommand(s) - jacov Collect and export corpus coverage in specified format for Java - targets - jscov Collect and export corpus coverage in specified format for JavaScript - targets - pycov Collect and export corpus coverage in specified format for Python - targets - rm-crashes Remove crashes from corpus - run Run hybrid fuzzing with Sydr and libFuzzer/AFL++, Python fuzzing - with Atheris, Java fuzzing with Jazzer, or JavaScript fuzzing with - Jazzer.js - security Check security predicates (out of bounds, integer overflow, division - by zero, etc.) for corpus seeds - -Опция **-c, \--config \** указывает путь к конфигурационному файлу в TOML -формате для запуска фаззинга (по умолчанию `sydr-fuzz.toml`). - -Опция **-l, \--log-level \** указывает уровень логирования (`info` по -умолчанию) для сообщений от sydr-fuzz (`sydr-fuzz.log`). Уровни логирования: -`minimal|info|debug|trace`. Уровень логирования `minimal` -позволяет печатать только самые информативные сообщения уровня -логирования `info`. - -Опция **-o, \--output \** указывает путь до выходной директории с -проектом, где содержатся артефакты и результаты работы фаззинга. Если не -указывать эту опцию, то проект создастся в текущей директории с именем -`-out`. - -### Опции запуска фаззинга - - $ sydr-fuzz run -h - sydr-fuzz-run - Run hybrid fuzzing with Sydr and libFuzzer/AFL++, Python fuzzing with Atheris, Java - fuzzing with Jazzer, or JavaScript fuzzing with Jazzer.js - - USAGE: - sydr-fuzz run [OPTIONS] - - OPTIONS: - -f, --force-remove Remove output project directory if it exists - -h, --help Print help information - --runs Stop sydr-fuzz after N Sydr runs - -s, --strategy Strategy for scheduling Sydr input seeds [default: - coverage] [possible values: coverage, random, file-info] - --use-sydr-inputs Use files generated by Sydr as new inputs for Sydr - (relevant only for libFuzzer random and file-info - strategies) - -Опция **-f, \--force-remove** перезаписывает всю выходную директорию с проектом. - -Нижеперечисленные опции для фаззинга Python-кода не поддерживаются. - -Опция **\--runs \** задает число запусков Sydr, после которого работа -sydr-fuzz будет завершена. - -Опция **-s, \--strategy \** указывает стратегию для выбора входных -файлов из очереди для запуска на них Sydr при гибридном фаззинге. Стратегия -`coverage` используется по умолчанию. В данной стратегии входные данные из -корпуса фаззера, которые принесли больше покрытия, позже созданы и имеют -меньший размер, имеют больший приоритет. Стратегия `file-info` учитывает только -время создания файла и размер (файлы созданные позже и меньшего размера имеют -приоритет выше). Стратегия `random` выбирает входные данные случайным образом. - -Опция **\--use-sydr-inputs** позволяет запускать Sydr на своих же входных данных -при гибридном фаззинге. Имеет эффект только вместе со стратегиями libFuzzer -`file-info` и `random`. - -### Опции генерации HTML отчета о покрытии (C/C++/Rust/Python/Go/Java/JavaScript) - - $ sydr-fuzz cov-html -h - sydr-fuzz-cov-html - Generate HTML coverage report - - USAGE: - sydr-fuzz cov-html [OPTIONS] - - OPTIONS: - -h, --help Print help information - -j, --jobs Number of parallel jobs to collect and merge raw LLVM coverage - [default: half of cpu cores] - -Опция **-j, \--jobs \** позволяет задать количество потоков для сбора данных -LLVM покрытия (не применяется для Python). -По умолчанию данное значение равно половине ядер процессора. - -При сборе покрытия Java-кода через переменную окружения `CASR_SOURCE_DIRS` -можно указать пути до исходного кода (список путей, разделенных через ':'). -Тогда информация о нем будет отражена в html отчете: - - $ export CASR_SOURCE_DIRS=/dir/with/sources/1:/dir/with/sources/2 - $ sydr-fuzz cov-html - -### Продвинутые опции сбора покрытия (C/C++/Rust) - -**sydr-fuzz cov-export** собирает покрытие и экспортирует его в JSON или lcov -формат - -**sydr-fuzz cov-report** собирает покрытие и выводит краткий отчет о покрытии в -процентах - -**sydr-fuzz cov-show** собирает и выводит покрытие по строкам - -Все три команды имеют одинаковый интерфейс задания дополнительных аргументов -после `--`: - - $ sydr-fuzz cov-report -h - sydr-fuzz-cov-report - Collect corpus coverage and display summary - - USAGE: - sydr-fuzz cov-report [OPTIONS] [-- ...] - - ARGS: - ... llvm-cov report extra options after -- - - OPTIONS: - -h, --help Print help information - -j, --jobs Number of parallel jobs to collect and merge raw coverage [default: - half of cpu cores] - -Опция **-j, \--jobs \** позволяет задать количество потоков для сбора данных покрытия. -По умолчанию данное значение равно половине ядер процессора. - -**cov-COMMAND** заимствованы от команд -[llvm-cov](https://llvm.org/docs/CommandGuide/llvm-cov.html). Дополнительные -аргументы **ARGS**, которые можно перечислить после `--`, представляют собой -соответствующие опции и аргументы для команд llvm-cov за тем исключением, что -целевой бинарный файл и опция **-instr-profile** заранее заданы. Например: - - $ sydr-fuzz cov-report -j 4 -- -use-color=true - -По умолчанию `llvm-cov` ищется в `PATH`. Однако можно указать свой путь до -`llvm-cov` в переменной среды `SYDR_LLVM_COV`. Тогда путь до `llvm-profdata` -составится автоматически на основе пути до `llvm-cov`. - -### Продвинутые опции сбора покрытия (Python) - - $ sydr-fuzz pycov -h - sydr-fuzz-pycov - Collect and export corpus coverage in specified format for Python targets - - USAGE: - sydr-fuzz pycov [-- ...] - - ARGS: - Coverage format (report, html, xml, json, lcov, etc.) - ... coverage FORMAT extra options after -- - - OPTIONS: - -h, --help Print help information - -Дополнительные аргументы ****, которые можно перечислить после `--`, -представляют собой соответствующие опции и аргументы -[Coverage](https://coverage.readthedocs.io/en/latest/cmd.html). - -### Продвинутые опции сбора покрытия (Java) - - $ sydr-fuzz jacov -h - sydr-fuzz-jacov - Collect and export corpus coverage in specified format for Java targets - - USAGE: - sydr-fuzz jacov [-- ...] - - ARGS: - Coverage format (html, xml, csv) [possible values: html, xml, csv] - ... Extra jacococli options after -- - - OPTIONS: - -h, --help Print help information - -Дополнительные аргументы ****, которые можно перечислить после `--`, -представляют собой соответствующие опции и аргументы -[jacococli report](https://www.eclemma.org/jacoco/trunk/doc/cli.html). - -Например, можно указать путь до исходного кода. Тогда информация о нем будет -отражена в html отчете: - - $ sydr-fuzz jacov html -- --sourcefiles - -Можно использовать переменную окружения `CASR_SOURCE_DIRS` для указания путей к -директориям, содержащим файлы исходного кода (список путей, разделенных через ':'). - -### Продвинутые опции сбора покрытия (JavaScript) - - $ sydr-fuzz jscov -h - sydr-fuzz-jscov - Collect and export corpus coverage in specified format for JavaScript targets - - USAGE: - sydr-fuzz jscov [-- ...] - - ARGS: - Coverage format (clover, cobertura, html-spa, html, json-summary, - json, lcov, lcovonly, teamcity, text-lcov, text-summary, text) - [possible values: clover, cobertura, html-spa, html, json-summary, - json, lcov, lcovonly, teamcity, text-lcov, text-summary, text] - ... Extra coverage options after -- - - OPTIONS: - -h, --help Print help information - -Дополнительные аргументы ****, которые можно перечислить после `--`, -представляют собой соответствующие опции и аргументы -[Jazzer.js](https://github.com/CodeIntelligenceTesting/jazzer.js/blob/main/docs/fuzz-targets.md#coverage-report-generation). - -### Сбор покрытия (Go) - -Сбор покрытия после фаззинга с помощью -[go-fuzz](https://github.com/dvyukov/go-fuzz) и движка libFuzzer (данный способ -фаззинга поддерживается через sydr-fuzz) осуществляется следующим образом: - -Переходим в директорию, содержащую исходный код проекта, для которого -осуществлялся фаззинг. Пример: - - # cd /image - -Копируем полученный после фаззинга корпус в директорию `corpus`, созданную в -корне репозитория с проектом. Пример: - - # cp -r /fuzz/webp-out/corpus /image/corpus - -Собираем цель для go-fuzz без поддержки libFuzzer: - - # go-fuzz-build -func=FuzzWebp -o fuzz_webp.zip - -Запускаем фаззинг с опцией сбора покрытия, ждём пока импортируется корпус. После -этого завершаем фаззинг. Можно нажать Ctrl+C, когда более 10 секунд не растет -покрытие `cover` и `corpus` не меньше размера корпуса в сообщениях вида -`2023/03/03 17:09:40 workers: 12, corpus: 834 (34s ago), crashers: 2, restarts: -1/5587, execs: 1033722 (21528/sec), cover: 1309, uptime: 48s` - - # go-fuzz -bin=fuzz_webp.zip -dumpcover - -Исправляем файл с покрытием с помощью sed: - - # sed -i '/0.0,1.1/d' coverprofile - -Генерируем отчёт о покрытии: - -``` -# go tool cover -html=coverprofile -HTML output written to /tmp/cover2240572277/coverage.html -``` - -### Опции проверки предикатов безопасности (C/C++/Rust/Go) - - $ sydr-fuzz security -h - sydr-fuzz-security - Check security predicates (out of bounds, integer overflow, division by zero, etc.) for - corpus seeds - - USAGE: - sydr-fuzz security [OPTIONS] - - OPTIONS: - -f, --force-remove Remove output project directory if it exists - -h, --help Print help information - -j, --jobs Number of Sydr jobs - --runs Check security predicates for N seeds from corpus - -t, --timeout Timeout (in seconds) for target execution [default: 30] - -Опция **-f, \--force-remove** перезаписывает всю выходную директорию с проектом. - -Опция **-j, \--jobs \** позволяет изменить количество запускаемых Sydr. - -Опция **\--runs \** задает число файлов из корпуса, на которых будет -запущена проверка предикатов безопасности. После заданного числа запусков -sydr-fuzz прекратит работу. - -Опция **-t, \--timeout \** устанавливает время выполнения фаззинг цели в секундах, которое -будет считаться тайм-аутом (по умолчанию 30 секунд). - -### Опции запуска анализа аварийных завершений и ошибок неопределенного поведения с помощью Casr - - $ sydr-fuzz casr -h - sydr-fuzz-casr - Triage, deduplicate, cluster, and create reports for crashes and UBSAN runtime errors - - USAGE: - sydr-fuzz casr [OPTIONS] - - OPTIONS: - --engagement - DefectDojo engagement name [default: TOML config name + datetime] - - -h, --help - Print help information - - --ignore - File with regular expressions for functions and file paths to filter in call - stacks - - -j, --jobs - Number of parallel jobs for crash triaging [default: half of cpu cores] - - --no-casr-gdb - Do not collect crash reports via casr-gdb - - --no-cluster - Do not cluster reports - - -p - Use PATH environment variable to find casr tools - - --product - DefectDojo product name (required when DefectDojo URL is provided) - - --san-force - Force casr-san run without sanitizers symbols check - - -t, --timeout - Timeout (in seconds) for target execution [set 0 to disable] [default: 30] - - --token - DefectDojo API key (required when DefectDojo URL is provided) - - --ubsan - Create and triage UndefinedBehaviorSanitizer reports - - --url - Upload new and unique CASR reports to DefectDojo at base URL - -Опция **\--ignore \** - позволяет задать файл с регулярными выражениями для функций и путей, -которые будут отфильтрованы в стекax вызовов. - -Опция **-j, \--jobs \** - позволяет задать число потоков для параллельного -анализа аварийных завершений. -По умолчанию данное значение равно половине ядер процессора. - -Опция **\--no-casr-gdb** - осуществление анализа без запуска casr-gdb. - -Опция **\--no-cluster** - осуществление анализа без запуска кластеризации отчетов об аварийных завершениях. - -Опция **-p** - поиск путей до casr инструментов с помощью переменной окружения PATH. - -Опция **\--san-force** отключает проверку наличия символов ASAN в фаззинг цели и -принудительно запускает `casr-san`. - -Опция **-t, \--timeout \** - позволяет установить тайм-аут на выполнение фаззинг -цели под casr-san/casr-gdb (по умолчанию 30 секунд). Чтобы отключить тайм-аут, -нужно значение опции равное 0. - -Опция **\--ubsan** включает анализ ошибок неопреденного поведения (UBSAN). - -При анализе аварийных завершений Java программ можно использовать переменную среды -`CASR_SOURCE_DIRS` (список путей, разделенных через ':') для указания путей к директориям, -содержащим файлы исходного кода. - -С помощью опции **\--url \** можно указать ссылку для экспорта полученных -CASR отчетов в DefectDojo. Использование данной опции инициирует процесс -экспорта. - -Опция **\--token \** позволяет задать DefectDojo API key. - -Опция **\--product \** позволяет указать название анализируемого продукта. - -Опция **\--engagement \** позволяет задать название очередной серии -анализа в рамках продукта (по умолчанию складывается из имени -конфигурационного файла и даты). - -### Опции удаления аварийных завершений из корпуса - - $ sydr-fuzz rm-crashes -h - sydr-fuzz-rm-crashes - Remove crashes from corpus - - USAGE: - sydr-fuzz rm-crashes [OPTIONS] - - ARGS: - Path to corpus directory. - - OPTIONS: - -h, --help Print help information - -j, --jobs Number of parallel jobs to run target on inputs [default: - half of cpu cores] - -t, --timeout Timeout (in seconds) for target execution [default: 30] - -Аргумент **** позволяет указать путь к корпусу. - -Опция **-j, --jobs ** - позволяет задавать число потоков для запуска фаззинг -цели на входных данных из корпуса. -По умолчанию данное значение равно половине ядер процессора. - -Опция **-t, \--timeout \** - позволяет установить тайм-аут на выполнение фаззинг -цели (по умолчанию 30 секунд). - -## Создание фаззинг целей - -Для осуществления гибридного фаззинга требуется подготовить отдельные обертки -для Sydr и фаззера. Все цели рекомендуется собирать с отладочной информацией -(`-g`), чтобы потом проще было анализировать аварийные завершения и срабатывания -предикатов безопасности. - -Фаззинг необходимо проводить в том же окружении (Docker), в котором -производилась сборка фаззинг целей. В противном случае возможны проблемы с -символами в выводе санитайзеров и поиском файлов с исходным кодом. - -### Обертка Sydr - -Обертка для Sydr представляет собой небольшую программу, которая читает входные данные (файл -либо стандартный поток ввода) и передает их в функцию, являющуюся целью фаззинга. Данную -обертку требуется собирать без каких либо санитайзеров (но оставить `-g`). Рекомендуется -запустить обертку под Sydr на каком-нибудь файле из очереди и убедиться, что Sydr генерирует -новые входные данные. Таким образом, можно проверить, что обертка написана верно. -Чтение входных данных в обертке должно происходить непосредственно перед их использованием. -Все остальные вычисления (инициализация глобального контекста и т.д.), которые не зависят от -входных данных, должны быть расположены до их чтения. В противном случае скорость интерпретации -программы может замедляться в разы. - -### Обертка libFuzzer - -Для подготовки libFuzzer обертки можно воспользоваться его -[документацией](https://www.llvm.org/docs/LibFuzzer.html). По сути требуется -реализовать функцию `LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)`, -которая принимает на вход мутированный буфер и передает его в функцию, -являющуюся целью фаззинга. Проект [OSS-Fuzz](https://github.com/google/oss-fuzz) -уже содержит libFuzzer обертки для большого числа проектов с открытым исходным -кодом. Обертку для фаззера следует собирать с санитайзерами и libFuzzer (который -тоже является санитайзером): - -`-g -fsanitize=fuzzer,address,integer,bounds,null,undefined,float-divide-by-zero` - -Важно не забыть собрать не только код обертки с санитайзерами, но и целевую -библиотеку, которую он использует. Для сборки библиотеки флаг `-fsanitize=fuzzer` -нужно заменить на `-fsanitize=fuzzer-no-link`. Если обертка требует инициализации -глобального контекста, то требуется добавить вызов `LLVMFuzzerInitialize`. - -Для облегчения работы, libFuzzer обертка может быть использована для создания -обертки Sydr. Достаточно добавить функцию `main`, которая читает входные данные -и передает их в `LLVMFuzzerInitialize` в виде буфера. Для этого можно слинковать -обертку libFuzzer с `main` следующего содержания: - -```cpp -#include -#include -#include - -// int LLVMFuzzerInitialize(int *argc, char ***argv); - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); - -int main(int argc, char** argv) -{ - // LLVMFuzzerInitialize(&argc, &argv); - - FILE* fd = fopen(argv[1], "rb"); - if (!fd) return 1; - fseek(fd, 0, SEEK_END); - long fsize = ftell(fd); - fseek(fd, 0, SEEK_SET); - - char* buffer = (char*)malloc(fsize); - fread(buffer, 1, fsize, fd); - fclose(fd); - - return LLVMFuzzerTestOneInput((const uint8_t*)buffer, fsize); -} -``` - -Примеры кода `main` находятся -[здесь](https://github.com/llvm/llvm-project/blob/main/compiler-rt/lib/fuzzer/standalone/StandaloneFuzzTargetMain.c) -и -[здесь](https://github.com/vanhauser-thc/qemu_driver/blob/master/qemu_driver.c). -Докер `sydr/ubuntu20.04-sydr-fuzz` уже содержит исходный код `main` в -файлах `/opt/StandaloneFuzzTargetMain.c` или `/opt/qemu_driver.c`. С их помощью -можно получить обертку для Sydr, например: - - $ clang -g fuzz_target.c /opt/StandaloneFuzzTargetMain.c -o sydr_target - -Таким же образом, из libFuzzer обертки можно получить обертки для AFL++. - -### Обертка AFL++ - -Для AFL++ написание отдельной обертки не требуется, можно полностью использовать -код обертки Sydr или libFuzzer. Отличие заключается только в сборке с другой инструментацией. - -Стоит отметить, что существует возможность вообще не производить никаких -дополнительных действий и просто взять собранную под Sydr обертку. В аргументах -AFL++ в таком случае необходимо указать использование бинарной инструментации -(`-Q` для режима QEMU и `-O` для FRIDA). Фаззинг с бинарной инструментацией -выполняется медленно и неэффективно, а отсутствие санитайзеров в сборке сводит -вероятность нахождения ошибок к минимуму. Настоятельно не рекомендутся использовать -этот вариант. Подробнее о фаззинге бинарных целей можно почитать -[здесь](https://github.com/AFLplusplus/AFLplusplus/blob/stable/docs/fuzzing_binary-only_targets.md). - -Чтобы собрать обертку с инструментацией фаззера, при сборке цели нужно -использовать компиляторы, поставляемые вместе с AFL++: `afl-clang`/`afl-clang++`, -`afl-clang-fast`/`afl-clang-fast++`, `afl-gcc`/`afl-g++`. Также при сборке нужно указать -санитайзеры и опцию для дебаг-информации: - -`-g -fsanitize=address,bounds,integer,undefined,null,float-divide-by-zero` - -Поробнее об инструментации фаззинг целей AFL++ написано -[здесь](https://github.com/AFLplusplus/AFLplusplus/blob/stable/docs/fuzzing_in_depth.md#1-instrumenting-the-target). - -Также можно использовать компиляторы `afl-clang-lto`/`afl-clang-lto++`. При -использовании этих компиляторов битовая карта, используемая при гибридном -фаззинге с AFL++, будет содержать меньше коллизий. - -Подробнее об LTO mode можно прочитать [здесь](https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.lto.md). - -Рекомендуется собирать обертку для работы AFL++ в Persistent mode. В этом режиме -AFL++ будет фаззить цель много раз в одном процессе, вместо того чтобы создавать -каждый раз процесс заново, что ускоряет фаззинг в несколько раз. - -Для сборки оберток AFL++ в Persistent mode можно воспользоваться оберткой -для libFuzzer. Для этого стоит собирать библиотеку и обертку вышеупомянутыми -компиляторами, при этом помимо санитайзеров указав `-fsanitize=fuzzer` во -флагах компиляции. В таком случае компиляторы от AFL++ самостоятельно создадут -функцию `main` с инструментацией для Persistent mode, вызвав оттуда -LLVMFuzzerTestOneInput из обертки для libFuzzer. При использовании флага -`-fsanitize=fuzzer` стоит использовать `@@` в поле `target` в таблице -`aflplusplus` в конфигурационном файле. - -Также можно собрать обертки AFL++ без `-fsanitize=fuzzer`, написав `main` -самостоятельно. Для этого нужно слинковать обертку для libFuzzer с `main` следующего содержания: - -```cpp -#include -#include -#include - -__AFL_FUZZ_INIT(); - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); -// extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv); - -int -main(int argc, char **argv) -{ - - // LLVMFuzzerInitialize(&argc, &argv); - -#ifdef __AFL_HAVE_MANUAL_CONTROL - __AFL_INIT(); -#endif - - uint8_t *data = __AFL_FUZZ_TESTCASE_BUF; - - while (__AFL_LOOP(1000)) - { - size_t size = __AFL_FUZZ_TESTCASE_LEN; - - LLVMFuzzerTestOneInput(data, size); - } - - return 0; -} -``` - -При использовании такой функции `main` `@@` в конфигурационном файле -использовать не надо, т.к. данные будут читаться из стандартного потока ввода. - -Подробнее о Persistent mode можно почитать [здесь](https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.persistent_mode.md). - -**Фаззинг аргументов командной строки** - -Гибридный фаззинг с AFL++ позволяет фаззить аргументы командной строки. Для -компиляции оберток для фаззинга аргументов командной строки необходимо -воспользоваться заголовочным файлом -[argv-fuzz-inl.h](https://github.com/AFLplusplus/AFLplusplus/blob/stable/utils/argv_fuzzing/argv-fuzz-inl.h). -Нужно добавить `#include "/path/to/argv-fuzz-inl.h"` в обертки для Sydr и AFL++. -Затем вызвать или макрос `AFL_INIT_ARGV();`, или макрос -`AFL_INIT_SET0("prog_name");` в самом начале функции `main`. Тогда данные со -стандартного потока ввода будут преобразованы в `argc` и `argv` соответственно. - -В случае использования `AFL_INIT_SET0` `argv[0]` всегда будет равен переданной в макрос -строке. - -Для фаззинга аргументов командной строки необходимо подавать на стандартный -поток ввода данные, разделенные нуль-терминатором. Например, данные `AAAA\0BBBB\0CCCC\0` -будут преобразованы в `argv[0] = "AAAA\0"`, `argv[1] = "BBBB\0"`, `argv[2] = "CCCC\0"`. - -При фаззинге аргументов командной строки цели Sydr и AFL++ принимают входные -данные со стандартного потока ввода, поэтому в аргументах Sydr стоит указать -аргумент `--sym-stdin`; `@@` для AFL++ указывать не надо. - -Пример конфигурации: - -```toml -[sydr] -args = "--sym-stdin" -target = "/target_sydr" - -[aflplusplus] -args = "-i /corpus -t 2000" -target = "/target_afl" -``` - -Стоит отметить, что использование [Persistent mode](https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.persistent_mode.md) -и фаззинга аргументов командной строки несовместимо. - -### Обертка Atheris - -Для подготовки Atheris обертки можно воспользоваться его -[документацией](https://github.com/google/atheris/blob/master/README.md). По -сути, требуется реализовать функцию `TestOneInput(data)`, которая принимает на -вход мутированный буфер и передает его в функцию, являющуюся целью фаззинга. -Проект [OSS-Fuzz](https://github.com/google/oss-fuzz) уже содержит Atheris -обертки для большого числа проектов с открытым исходным кодом. - -Также в начале обертки требуется использовать инструментацию целевой -библиотеки с помощью функции `atheris.instrument_imports()` (рекомендуется -инструментировать все используемые библиотеки). - -Для корректной работы обертки требуется выдать ей права на выполнение с помощью -утилиты `chmod +x` и указать путь до интрепретатора Python в начале обертки, -используя `#!`, например `#!/usr/bin/env python3`. - -Если целевая библиотека содержит расширения на языках C/C++, рекомендуется -инструментация исходных файлов при сборкe библиотеки. Для этого требуется -использовать флаг `-fsanitize=address,fuzzer-no-link` при сборке. Более подробно -об этом можно прочитать в -[документации](https://github.com/google/atheris/blob/master/native_extension_fuzzing.md) -Atheris. - -```py -#!/usr/bin/env python3 - -import atheris - -with atheris.instrument_imports(): - from ruamel import yaml as ryaml - import sys - -@atheris.instrument_func -def TestOneInput(data): - ryaml.load_all(data) - -if __name__ == "__main__": - atheris.Setup(sys.argv, TestOneInput) - atheris.Fuzz() -``` - -### Обертка Jazzer - -Для подготовки обертки можно воспользоваться -[гайдом OSS-Fuzz](https://google.github.io/oss-fuzz/getting-started/new-project-guide/jvm-lang/). -В простейшем случае необходимо реализовать класс с именем `*Fuzzer`, без -директивы `package` в заголовке файла. В самом классе должен быть реализован -статический метод `fuzzerTestOneInput(byte[])` или `fuzzerTestOneInput(FuzzedDataProvider)`. -`FuzzedDataProvider` упрощает процесс создания обертки, преобразуя необработанные входные байты, -полученные от фаззера, в примитивные типы Java. - -Для сборки обертки можно воспользоваться компилятором `javac`, которому -необходимо передать Java файл. Также в аргументе `-cp` (class path) могут быть -указаны пути до зависимостей. Например: - - $ javac -cp /usr/local/lib/jazzer_standalone_deploy.jar ExampleFuzzer.java - -Для использования `FuzzedDataProvider` необходимо -в начало файла поместить строку `import com.code_intelligence.jazzer.api.FuzzedDataProvider;` -и при сборке указать путь до jazzer API, как это сделано в примере выше. - -Если целевая библиотека содержит расширения на языках C/C++, рекомендуется -инструментация исходных файлов при сборкe библиотеки. Для этого требуется -использовать флаг `-fsanitize=address,fuzzer-no-link` при сборке C/C++ библиотек. -Более подробно об этом можно прочитать в -[документации](https://github.com/CodeIntelligenceTesting/jazzer/blob/main/docs/advanced.md) -Jazzer. - -```java -import com.code_intelligence.jazzer.api.FuzzedDataProvider; - -public class ExampleFuzzer { - public static void fuzzerTestOneInput(FuzzedDataProvider data) { - ... - // Call a function of the project under test with arguments derived from - // data and throw an exception if something unwanted happens. - ... - } -} -``` - -### Обертка Jazzer.js - -Для подготовки Jazzer.js обертки можно воспользоваться его -[документацией](https://github.com/CodeIntelligenceTesting/jazzer.js/blob/main/docs/fuzz-targets.md). -Требуется реализовать и экспортировать функцию `fuzz(data)`, которая принимает на -вход мутированный буфер и передает его в функцию, являющуюся целью фаззинга. - -Поскольку исходный тип данных буфера (Buffer) является не слишком удобным представлением данных, -Jazzer.js предоставляет класс FuzzedDataProvider, позволяющий извлекать примитивные типы из буфера. -Для использования FuzzedDataProvider необходимо подключить модуль @jazzer.js/core в начале обертки. - -Для корректной работы обертки требуется выдать ей права на выполнение с помощью -утилиты `chmod +x` и указать путь до интрепретатора npx с аргументом jazzer в начале обертки, -используя `#!`, например `#!/usr/bin/env -S npx jazzer`. - -Если целевая библиотека содержит расширения на языках C/C++, рекомендуется -инструментация исходных файлов при сборкe библиотеки. Для этого требуется -использовать флаг `-fsanitize=address,fuzzer-no-link` при сборке. - -```js -const { FuzzedDataProvider } = require("@jazzer.js/core"); - -module.exports.fuzz = function (fuzzerInputData) { - const data = new FuzzedDataProvider(fuzzerInputData); - const intParam = data.consumeIntegral(4); - const stringParam = data.consumeString(4, "utf-8"); - myAwesomeCode(intParam, stringParam); -}; -``` - -## Подготовка докера для гибридного фаззинга - -Докер файл отвечает за установку зависимостей для сборки цели, сборку целей под -фаззер и Sydr, создание начального корпуса для фаззинга и т.д. -В начальный корпус рекомендуется добавлять файлы размером меньше 1 Мб. В -противном случае фаззинг будет неэффективным, а Sydr будет использовать большой -объем оперативной памяти. -Ниже приводится пример возможного Dockerfile с комментариями: - -```docker -# Подготовленный нами докер с собранным LLVM -FROM sydr/ubuntu20.04-sydr-fuzz - -# Автор -MAINTAINER John Doe - -# Установка зависимостей для сборки -RUN apt-get update && apt-get install -y libssl-dev - -# Клонирование целевого репозитория -RUN git clone https://github.com/target/project - -# Сборка фаззинг целей -## Копирование оберток для libFuzzer/AFL++, Sydr и скрипта сборки -COPY target_fuzzer.c target_sydr.c build.sh / -## Сборка целей для libFuzzer/AFL++ и Sydr -RUN ./build.sh - -# Создание начального корпуса -RUN mkdir corpus && find /project -name "*.json" -exec cp {} /corpus \; -``` - -Сборка докера: - - $ sudo docker build -t sydr-fuzz-target . - -## Конфигурационный файл и структура выходного проекта - -Конфигурационный файл (`sydr-fuzz.toml`) используется для задания опций -фаззера и Sydr. Все пути задаются либо абсолютно, либо относительно -директории, в которой расположен конфигурационный файл. Для настройки запуска -различных инструментов в этом файле указываются таблицы `[sydr]`, `[libfuzzer]`, -`[aflplusplus]` (или список таблиц `[[aflplusplus]]`), `[atheris]`, `[jazzer]`, `[jazzer_js]` и `[cov]`. Конфигурационный файл не может -одновременно содержать таблицы `[libfuzzer]` и `[aflplusplus]`, а также -`[atheris]`, `[jazzer]` и`[jazzer_js]` с какой-либо другой таблицей (на примере ниже приведены все таблицы -для краткости). - -```toml -exit-on-time = 7200 - -[sydr] -args = "-j 4" -target = "/target_sydr @@" -jobs = 3 - -[libfuzzer] -path = "/target_fuzzer" -args = "-dict=/json.dict -jobs=6 /corpus" - -[atheris] -path = "/target.py" -args = "/corpus -jobs=4 -workers=4" - -[jazzer] -args = "--cp=/out --asan -jobs=4 /corpus" -target_class = "ExampleFuzzerNative" - -[jazzer_js] -path = "/target.js" -args = "-i=mylib /corpus -- -jobs=4 -workers=4" - -[aflplusplus] -args = "-t 5000 -i /corpus" -target = "/target_afl @@" -jobs = 6 - -[cov] -target = "/instrumented_target @@" -``` - -**exit-on-time** - опциональный параметр указывает время в секундах. Если в -течение этого времени покрытие не растет, фаззинг автоматически завершается. - -**out** - опциональный параметр указывает путь до выходной директории с -проектом, где содержатся артефакты и результаты работы фаззинга. Если не -указывать эту опцию, то проект создастся в текущей директории с именем -`-out`. Данный параметр дублирует аргумент командной строки `--output`, -который считается более приоритетным, чем значение из конфигурационного файла. - -### Sydr - -```toml -[sydr] -args = "-j 4" -target = "/target_sydr @@" -jobs = 3 -timeout = 1000 -cache = true -optimistic = true -fuzzmem = false -wait_jobs = false -solving_limit = false -symaddr = 20 -[sydr.env] - CLASSIC_ENVVAR = "XXX" -``` - -Таблица `[sydr]` может содержать следующие параметры: - -**args** - аргументы Sydr. Опции `--sym-file` и `--log-file` задаются -автоматически, их указывать не надо. - -**target** - строка запуска обертки для Sydr. Вместо имени символьного входного -файла следует использовать `@@`. - -**jobs** - число процессов Sydr для запуска (по умолчанию 1). Всего запускается -**jobs** процессов Sydr в `-j` (задается в **args**) потоков каждый. - -**timeout** - тайм-аут в секундах, по истечении которого процесс Sydr будет -остановлен. Если параметр не указан, выставляется 20 минут (1200 секунд). - -**cache** - булевый параметр (по умолчанию включен), который включает кэш -инвертированных переходов. - -**optimistic** - булевый параметр (по умолчанию включен), который включает -оптимистичные решения. - -**fuzzmem** - булевый параметр (по умолчанию включен), который включает режим -фаззинга символьных адресов. - -**wait_jobs** - булевый параметр (по умолчанию включен), который включает -приостановление построения предиката пути, когда набрано достаточно -необработанных запросов к математическому решателю. - -**solving_limit** - булевый параметр (по умолчанию включен), который включает 60 -секундный тайм-аут на суммарное время, проведенное в решателе. - -**symaddr** - целочисленный параметр, который включает режим обработки символьных -адресов раз в N запусков Sydr (по умолчанию N = 25). Чтобы выключить этот режим, -необходимо указать N = 0. - -**[sydr.env]** - таблица, содержащая значения переменных окружения, которые будут -выставлены для каждого запускаемого процесса Sydr. Каждая строка таблицы задаёт -строковую переменную, имя которой совпадает с именем соответствующей переменной окружения. -Значения переменных окружения можно задавать также в системных переменных окружения. -При этом значения, заданные в файле конфигурации, более приоритетны, чем -значения, заданные в системных переменных окружения. - -### libFuzzer - -```toml -[libfuzzer] -path = "/target_fuzzer" -args = "-dict=/json.dict -jobs=6 /corpus" -cmin = true -set_cover_merge = true -[libfuzzer.env] - ASAN_OPTIONS = "allocator_may_return_null=0" -``` - -Таблица `[libfuzzer]` может содержать следующие параметры: - -**path** - путь до libFuzzer обертки. - -**args** - аргументы libFuzzer. В аргументах могут быть указаны входные -директории с корпусами. Выходная директория с корпусом автоматически создается в -каталоге с проектом (и подставляется в аргументы libFuzzer). В выходной корпус -будут минимизированы все входные корпуса. Число процессов libFuzzer можно -контролировать через опцию `-jobs=N`, -которая указывает на то, что должно быть выполнено N запусков фаззинга до конца -(пока не найден баг или исчерпан лимит времени/числа итераций). Запуски фаззинга -распределяются между несколькими процессами libFuzzer (по умолчанию используется -не больше половины доступных ядер), число которых можно задать через -`-workers=N`. Если цель для фаззинга аварийно завершается, имеет смысл -использовать опции `-jobs=M -workers=N`, где N - число процессов libFuzzer, а -M - число аварийных завершений, зависаний и oom, по достижению которого фаззинг -будет завершен. Подробное описание опций libFuzzer можно найти в его -[документации](https://www.llvm.org/docs/LibFuzzer.html). - -**cmin** - булевый/целочисленный параметр (по умолчанию `true`), который включает -минимизацию входных корпусов в выходной корпус проекта. Если параметр выключен, -то происходит просто копирование входных корпусов в выходной корпус проекта. -Минимизацию корпуса, например, можно выключить, когда libFuzzer не справляется -минимизировать корпус. - -**set_cover_merge** - булевый параметр (по умолчанию выключен), который -позволяет использовать для минимизации опцию libFuzzer `set_cover_merge`. Если -параметр выключен, для минимизации используется опция `merge`. - -**[libfuzzer.env]** - таблица, содержащая значения переменных окружения, которые будут -выставлены для каждого запускаемого процесса libFuzzer. Каждая строка таблицы задаёт -строковую переменную, имя которой совпадает с именем соответствующей переменной окружения. - -По умолчанию задаётся переменная среды `ASAN_OPTIONS="allocator_may_return_null=1"`. - -Значения по умолчанию можно менять путем переопределения их в таблице `[libfuzzer.env]` или в системных -переменных окружения. Значения опций `hard_rss_limit_mb` и `detect_leaks` нужно задавать только через -соответствующие аргументы libFuzzer: `-rss_limit_mb` и `-detect_leaks`. -При этом наибольший приоритет имеют значения, заданные в файле конфигурации; средний приоритет имеют -значения, заданные в системных переменных окружения; низший приоритет имеют значения по умолчанию. - -### Atheris - -```toml -[atheris] -path = "/target_fuzzer" -args = "-dict=/json.dict -jobs=6 /corpus" -cmin = true -set_cover_merge = true -ld_preload = false -[atheris.env] - ASAN_OPTIONS = "allocator_may_return_null=0" -``` - -Таблица `[atheris]`, помимо всех параметров таблицы `[libfuzzer]`, содержит один -дополнительный параметр: - -**ld_preload** - булевый параметр (по умолчанию включен), который позволяет при -запуске Python-кода для фаззинга, сбора покрытия или анализа аварийных -завершений устанавливать переменную среды `LD_PRELOAD` равной пути до библиотеки -`asan_with_fuzzer.so`, необходимой при работе с кодом, имеющим расширения на -языках C/C++, для их инструментации. - -Для Atheris по умолчанию задаётся переменная среды - -`ASAN_OPTIONS="hard_rss_limit_mb=0,abort_on_error=1,detect_leaks=0,malloc_context_size=0,` - -`allocator_may_return_null=1"` - -Значения по умолчанию можно менять путем переопределения их в таблице `[atheris.env]` или в системных -переменных окружения. -При этом наибольший приоритет имеют значения, заданные в файле конфигурации; средний приоритет имеют -значения, заданные в системных переменных окружения; низший приоритет имеют значения по умолчанию. - -### Jazzer - -```toml -[jazzer] -path = "/path/to/jazzer" -agent_path = "/path/to/jazzer_standalone_deploy.jar" -args = "--cp=/path/to/java/classes/ --asan -jobs=6 /corpus" -target_class = "TargetClass" -cmin = true -set_cover_merge = true -java = "/path/to/jvm/launcher/java" -jacocolib = "/path/to/jacoco/lib" -[jazzer.env] - LD_LIBRARY_PATH = "/path/to/native/libraries/" -``` - -**path** - путь до бинарного файла jazzer (по умолчанию: `/usr/local/bin/jazzer`). - -**agent_path** - путь до jazzer API (по умолчанию: `/usr/local/lib/jazzer_standalone_deploy.jar`). - -**args** - аргументы jazzer и libFuzzer. - -**target_class** - название Java класса с методом `fuzzerTestOneInput`. - -**cmin** и **set_cover_merge** - как у libFuzzer. - -**java** - путь до Java лаунчера (по умолчанию берется из `PATH`). - -**jacocolib** - путь до jar файлов библиотеки jacoco (необходимо для сбора -покрытия, по умолчанию: `/usr/local/lib/jacoco/lib`). - -Jazzer поддерживает фаззинг C/C++ библиотек, загруженных JVM, например, через `System.load()`. -Иногда требуется добавить пути, в которых будет производится поиск разделяемых -библиотек. Сделать это можно с помощью таблицы `[jazzer.env]`, указав значение -переменной среды `LD_LIBRARY_PATH`. - -Для Jazzer по умолчанию задаётся переменная среды - -`ASAN_OPTIONS="hard_rss_limit_mb=0,abort_on_error=1,detect_leaks=0,malloc_context_size=0,` - -`allocator_may_return_null=1"` - -Значения по умолчанию можно менять путем переопределения их в таблице `[jazzer.env]` или в системных -переменных окружения. -При этом наибольший приоритет имеют значения, заданные в файле конфигурации; средний приоритет имеют -значения, заданные в системных переменных окружения; низший приоритет имеют значения по умолчанию. - -### Jazzer.js - -```toml -[jazzer_js] -path = "/target_fuzzer" -args = "-i=target_lib /corpus -- -dict=/json.dict -jobs=6" -cmin = true -set_cover_merge = true -ld_preload = false -[jazzer_js.env] - ASAN_OPTIONS = "allocator_may_return_null=0" -``` - -**path** - путь до Jazzer.js обертки. - -**args** - аргументы Jazzer.js и libFuzzer. Сначала перечисляются аргументы -Jazzer.js, затем ставится разделитель "--", далее перечисляются аргументы -libFuzzer. - -**ld_preload** - булевый параметр (по умолчанию включен), который позволяет при -запуске JavaScript-кода для фаззинга, сбора покрытия или анализа аварийных -завершений устанавливать переменную среды `LD_PRELOAD` равной пути до библиотеки -`libclang_rt.asan-x86_64.so`, необходимой при работе с кодом, имеющим расширения на -языках C/C++, для их инструментации. - -Для Jazzer.js по умолчанию задаётся переменная среды - -`ASAN_OPTIONS="hard_rss_limit_mb=0,abort_on_error=1,detect_leaks=0,malloc_context_size=0,` - -`allocator_may_return_null=1"` - -Значения по умолчанию можно менять путем переопределения их в таблице `[jazzer_js.env]` или в системных -переменных окружения. -При этом наибольший приоритет имеют значения, заданные в файле конфигурации; средний приоритет имеют -значения, заданные в системных переменных окружения; низший приоритет имеют значения по умолчанию. - -### AFL++ - -```toml -[aflplusplus] -path = "/afl" -args = "-t 5000 -i /corpus" -target = "/target_afl @@" -cmin = 8 -jobs = 6 -foreign = ["/path/to/foreign_fuzzer/syncdir"] -[aflplusplus.env] - AFL_PRINT_FILENAMES = "1" - AFL_MAP_SIZE = "10000000" -``` - -Таблица `[aflplusplus]` может содержать следующие параметры: - -**args** - аргументы AFL++. Необходимым аргументом является опция `-i` для -указания входного корпуса. Дополнительно можно -указать опции для инструментации (`-Q`, `-O` для бинарной инструментации), -тайм-аутов (`-t 5000` миллисекунд) и другие. - -**target** - строка запуска обертки для AFL++. Вместо имени входного файла -следует использовать `@@`. Если обертка читает входные данные со стандартного -потока ввода, то `@@` указывать не нужно. - -**cmin** - булевый/целочисленный параметр (по умолчанию `true`), который включает минимизацию -входного корпуса при старте гибридного фаззинга. Этот параметр также может использоваться для -указания числа потоков для параллельного запуска утилиты `afl-cmin`. Если параметр установлен -в `true`, то используется половина всех доступных ядер на машине. Если указанное число потоков -больше, чем доступно ядер на машине, то для распараллеливания `afl-cmin` используются все ядра. -Если параметр выключен (`false` или `0`), то минимизация корпуса перед запуском гибридного -фаззинга не производится, а при вызове команды `cmin` используется половина всех доступных ядер. - -**jobs** - число процессов AFL++ для запуска (по умолчанию 1). - -Для таблицы `[aflplusplus]` запуск нескольких -процессов AFL++ осуществляется автоматически в соответствии с -[рекомендациями](https://github.com/AFLplusplus/AFLplusplus/blob/stable/docs/fuzzing_in_depth.md#c-using-multiple-cores): -запускается один основной фаззер (`afl_main-worker`) и `jobs-1` второстепенных процессов -(`afl_s-worker`), каждый второстепенный фаззер имеет свой набор -генерируемых автоматически опций с настройками фаззинга. - -Одновременно нельзя запустить более 64 процессов AFL++, так как это очень -неэффективная стратегия для гибридного фаззинга -([объяснение](https://github.com/AFLplusplus/AFLplusplus/blob/stable/docs/fuzzing_in_depth.md#c-using-multiple-cores)). - -**path** - путь до AFL++ и его утилит. Параметр не обязателен, если путь -добавлен в `$PATH` (в докере `sydr/ubuntu20.04-sydr-fuzz` уже добавлен). - -**foreign** - директории с очередью сторонних фаззеров (опция `-F` AFL++). Параметр может быть -строкой или массивом строк. Путь до директорий с очередью сторонних фаззеров может быть -указан относительно конфигурационного файла. Синхронизация со сторонними фаззерами доступна только -для главного процесса AFL++ (-M), поэтому при указании **foreign** требуется несколько запущенных -экземпляров AFL++ (**jobs** > 1). - -**[aflplusplus.env]** - таблица, содержащая значения переменных окружения, которые будут -выставлены для каждого запускаемого процесса AFL++. Каждая строка таблицы задаёт -строковую переменную, имя которой совпадает с именем соответствующей переменной окружения. - -Для настройки AFL++ можно использовать различные переменные окружения. Переменные -`AFL_SKIP_CPUFREQ=1`, `AFL_NO_UI=1`, `AFL_PRINT_FILENAMES`, `AFL_AUTORESUME`, -`AFL_MAP_SIZE=65536` выставляются автоматически по необходимости. `AFL_MAP_SIZE` -можно задать своим значением, однако это в большинстве случаев не требуется, т.к. -afl-fuzz определяет размер битовой карты автоматически. Переменная -`AFL_PRINT_FILENAMES=1` позволяет во время минимизации следить, какой файл -обрабатывается в данный момент. Это удобно, когда в корпусе находятся входные -файлы, приводящие к аварийному завершению, что приводит к ошибке работы -минимизации. При помощи `AFL_PRINT_FILENAMES=1` можно будет найти такие файлы -и удалить их. Также для тяжелых фаззинг целей можно выставить большое -значение переменной `AFL_FORKSRV_INIT_TMOUT`, отвечающей за максимальное время -инициализации форк-сервера AFL++, а также выставить переменную `AFL_MAP_SIZE=10000000`. -Для лучшего взаимодействия AFL++ и Sydr можно уменьшить интервал -синхронизации `AFL_SYNC_TIME` (указывается в минутах, по умолчанию 30 минут). -Также могут быть полезными переменные `AFL_DISABLE_TRIM`, `AFL_SHUFFLE_QUEUE`, -`AFL_NO_AFFINITY`. - -По умолчанию задаются также переменные среды - -`ASAN_OPTIONS="hard_rss_limit_mb=2048,abort_on_error=1,detect_leaks=0,` - -`malloc_context_size=0,symbolize=0,allocator_may_return_null=1"` - -`UBSAN_OPTIONS="halt_on_error=0,abort_on_error=0,malloc_context_size=0,` - -`allocator_may_return_null=1"` - -Значения по умолчанию можно менять путем переопределения их в таблице `[aflplusplus.env]` или в системных -переменных окружения. -При этом наибольший приоритет имеют значения, заданные в файле конфигурации; средний приоритет имеют -значения, заданные в системных переменных окружения; низший приоритет имеют значения по умолчанию. -Полный список переменных окружения приведен -[здесь](https://github.com/AFLplusplus/AFLplusplus/blob/stable/docs/env_variables.md). - -Значение некоторых параметров `ASAN_OPTIONS`: - -**hard_rss_limit_mb** - задает ограничение памяти анализируемого приложения в Мб (по -умолчанию 2 Гб). Чтобы снять ограничение памяти, можно указать 0. Данная опция -помогает Casr обнаруживать oom и отличать аварийное завершение от oom на шаге -`sydr-fuzz casr`. Однако AFL++ не поддерживает ограничение памяти через -`ASAN_OPTIONS`. Для обработки oom в AFL++ рекомендуется выключить swap. Тогда -программа будет убиваться системным OOM Killer. - -**detect_leaks** - булевый параметр (по умолчанию выключен), который включает -режим фаззинга, при котором срабатывания leak-санитайзера считаются аварийными -завершениями. - -**allocator_may_return_null** - булевый параметр (по умолчанию включен), который -разрешает аллокатору возвращать нулевой указатель. - -Задание параметров `halt_on_error=1,abort_on_error=1` для `UBSAN_OPTIONS` -включает режим фаззинга, при котором срабатывания ubsan-санитайзера приводят -к аварийным завершениям. - -Конфигурация AFL++ может быть задана как с помощью одной таблицы `[aflplusplus]`, -так и с помощью списка таблиц `[[aflplusplus]]`. В первом случае все параметры, -заданные в таблице, применяются ко всем процессам AFL++. Во втором случае первая -таблица является основной и задаёт параметры для основного (main) процесса AFL++ и некоторого -числа дополнительных (secondary) процессов, а каждая следующая таблица позволяет запустить -определённое число дополнительных (secondary) процессов фаззера со своими параметрами. - -Пример с несколькими таблицами: - -```toml -[[aflplusplus]] -path = "/afl" -args = "-t 5000 -i /corpus" -target = "/target_afl @@" -cmin = true -jobs = 6 -[aflplusplus.env] - AFL_PRINT_FILENAMES = "1" - -[[aflplusplus]] -args = "-t 10000" -target = "/target_afl_other @@" -jobs = 2 -[aflplusplus.env] - AFL_MAP_SIZE = "10000000" -``` - -Задание различных опций для дополнительных процессов фаззера -может быть полезно при использовании инструментации [CmpLog](https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.cmplog.md) ([RedQueen](https://github.com/RUB-SysSec/redqueen)) -или [laf-intel](https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.laf-intel.md) (COMPCOV). - -Пример с несколькими таблицами для CmpLog: - -```toml -[[aflplusplus]] -args = "-i /corpus -t 2000" -target = "/target_afl @@" -jobs = 4 - -[[aflplusplus]] -args = "-t 2000 -c /target_afl_cmplog -m none" -target = "/target_afl @@" -jobs = 2 -``` - -Первая таблица списка `[[aflplusplus]]` может содержать все перечисленные выше -параметры. Каждая дополнительная таблица списка `[[aflplusplus]]` может содержать -все перечисленные выше параметры, кроме **path** и **cmin** (эти параметры задаются -только для первой таблицы списка). - -При использовании списка `[[aflplusplus]]` директории для входного корпуса -(опция `-i` в **args**) должны совпадать во всех таблицах (кроме того, достаточно -задать опцию только для первой таблицы). - -Для первой таблицы списка запускается один основной фаззер (`afl_main-worker`) -и `jobs-1` второстепенных процессов (`afl_s-worker`), каждый второстепенный -фаззер имеет свой набор генерируемых автоматически опций с настройками фаззинга. -Для всех остальных таблиц списка `[[aflplusplus]]` производится запуск `jobs` -второстепенных процессов (`afl_s-worker`), каждый второстепенный фаззер -имеет одинаковый набор заданных в этой таблице опций. Опция **foreign** может -быть указана только для главной таблицы. - -### cov - -```toml -[cov] -target = "/instrumented_target @@" -[cov.env] - CLASSIC_ENVVAR = "XXX" -``` - -Таблица `[cov]` содержит следующие параметры: - -**target** - строка запуска инструментированного для сбора покрытия целевого -исполняемого файла. При сборке исполняемого файла следует использовать флаги: -`-fprofile-instr-generate -fcoverage-mapping`. - -**[cov.env]** - таблица, содержащая значения переменных окружения, которые будут -выставлены при сборе покрытия. Каждая строка таблицы задаёт строковую переменную, -имя которой совпадает с именем соответствующей переменной окружения. - -Значения переменных окружения можно задавать также в системных переменных окружения. -При этом значения, заданные в файле конфигурации, более приоритетны, чем -значения, заданные в системных переменных окружения. - -### Результаты фаззинга - -Результаты фаззинга и промежуточные артефакты сохраняются в директории проекта. -Путь до директории с выходным проектом может быть задан пользователем с помощью -опции `-o` перед командой запуска (`run`, `security`). Если опцию `-o` не задавать, -то директория с проектом автоматически создаcтся в текущей директории со -следующим именем: `-out`. Директория с проектом имеет следующий вид: - - sydr-fuzz-out/ - ├── crashes - │ ├── crash-deadbeaf - │ ├── oom-cafebabe - │ └── timeout-cafecafe - ├── corpus - │ └── seed - ├── corpus-old - │ └── seed - ├── libfuzzer - │ └── fuzz-0.log - ├── aflplusplus - │ ├── afl_main-worker - │ │ ├── crashes - │ │ ├── hangs - │ │ └── queue - │ ├── afl_s01-worker - │ │ ├── crashes - │ │ ├── hangs - │ │ └── queue - │ ├── sydr-worker - │ │ ├── crashes - │ │ └── queue - │ └── logs - │ ├── afl_main.log - │ └── afl_s01.log - ├── sydr - │ ├── cache - │ ├── logs - │ │ └── log_seed.txt - │ ├── stats - │ │ └── stats_seed.json - │ ├── annotated-logs - │ │ └── log_seed.txt - │ └── seeds - │ └── seed - ├── coverage - │ └── cov.profdata - ├── casr - │ ├── cl1 - │ │ ├── crash-deadbeaf1 - │ │ ├── crash-deadbeaf1.casrep - │ │ └── crash-deadbeaf1.gdb.casrep - │ ├── cl2 - │ │ ├── crash-deadbeaf2 - │ │ ├── crash-deadbeaf2.casrep - │ │ └── crash-deadbeaf2.gdb.casrep - │ ├── oom - │ │ └── oom-deadbeaf3 - │ ├── timeout - │ │ └── timeout-deadbeaf4 - │ └── ubsan - │ ├── corus_seed - │ ├── corus_seed_src_1_1.casrep - │ └── corus_seed_src_2_1.casrep - ├── security - │ └── sydr_file0_out_of_bounds_0 - ├── security-verified - │ └── sydr_file0_out_of_bounds_0 - ├── security-unique - │ └── sydr_file0_out_of_bounds_0 - ├── sydr-fuzz.log - ├── sydr-fuzz-cmin.log - ├── sydr-fuzz-security.log - └── sydr-fuzz-coverage.log - - -В директории `crashes` будут помещены все найденные c помощью фаззера и Sydr ошибки -(crash-\*, oom-\*, timeout-\*, leak-\*). При фаззинге с AFL++ ошибки также сохраняются в -выходных директориях фаззеров (`sydr-fuzz-out/aflplusplus/*-worker/(crashes|hangs)`). - -Директория `corpus` содержит стартовый корпус фаззинга. В начале анализа все -указанные в опциях фаззера исходные корпуса минимизируются (можно отключить -параметром `cmin` в таблице фаззера) и сохраняются в `corpus`. Для libFuzzer -эта директория является рабочей, и по окончании фаззинга она содержит полный -корпус фаззинга. Для AFL++ `corpus` является только стартовым набором файлов и -по окончании фаззинга не содержит новых файлов. Рабочие директории AFL++ расположены -в `aflplusplus/*-worker/queue`, чтобы собрать все корпуса вместе, требуется -запустить команду `sydr-fuzz cmin`. После запуска команды минимизации корпуса, -директория `corpus` содержит выходной минимизированный корпус, достигнутый -в процессе фаззинга. Полный не минимизированный корпус сохраняется в директории -`corpus-old`. - -В зависимости от конфигурации гибридного фаззинга, директория проекта содержит -либо `libfuzzer`, либо `aflplusplus`. В директории `libfuzzer` хранятся логи libFuzzer'а. -Директория `aflplusplus` является общей выходной директорией для AFL++ и содержит -директории `aflplusplus/*-worker` для каждого запущенного процесса AFL++ и Sydr -(`sydr-worker` требуется для синхронизации между AFL++ и Sydr). Кажая worker-директория -содержит директории с рабочи корпусом (`queue`), найденными аварийными завершениями -(`crashes`) и зависаниями (`hangs`). В директории `aflplusplus/logs` хранятся логи AFL++. - -`sydr` является рабочей директорией для всего пула Sydr'ов. В этой директории -хранятся логи (`sydr/logs/log_.txt`), аннотированные логи -(`sydr/annotated-logs/log_.txt`), которые были проаннотированы -во время верификации результатов режима проверки предикатов безопасности, -исходные входные данные для Sydr (`sydr/seeds/`) и файлы со статистикой Sydr -(`sydr/stats/stats_.json`). Также хранится общий кэш (`cache`). - -В директории `coverage` хранятся данные о покрытии на сгенерированном корпусе. - -В директории `casr` хранятся размеченные по кластерам аварийные завершения, обнаруженные -в процессе фаззинга. В директории каждого кластера `cl` находятся входной файл -для воспроизведения и \*.casrep файлы с подробной информацией об ошибке. Т.к. -AFL++ не отличает аварийное завершение от out of memory, приводящие к oom файлы -обнаруживаются с помощью Casr и сохраняются в директорию `casr/oom`. При достижении -тайм-аута во время работы casr-san соответствующий входной файл будет помещен -в директорию `casr/timeout`. В директории `casr/ubsan` хранятся отчёты об -ошибках неопределенного поведения. - -В директории `security` хранятся результаты работы Sydr в режиме проверки предикатов -безопасности. В директории `security-verified` хранятся верифицированные результаты работы -Sydr в режиме проверки предикатов безопасности. В директории `security-unique` -хранятся уникальные верифицированные результаты работы Sydr в режиме проверки -предикатов безопасности. - -Логи запусков sydr-fuzz в режиме `run`, `cmin`, `security` и `cov-*` лежат в корне проекта -(`sydr-fuzz.log`, `sydr-fuzz-cmin.log`, `sydr-fuzz-security.log`, `sydr-fuzz-coverage.log`). - -## Гибридный фаззинг с помощью sydr-fuzz - -Распакуйте Sydr в директории с конфигурационным файлом sydr-fuzz: - - $ unzip sydr.zip - -Запустите подготовленный докер и примонтируйте директорию с конфигурационным -файлом sydr-fuzz в директорию `/fuzz` внутри докера (`--privileged` необходим -для работы Casr, а также позволяет -докеру видеть локальный лицензионный USB ключ, `--network host` - сетевой ключ, -также в докер пробрасывается время системы, -`-v /var/hasplm:/var/hasplm -v /etc/hasplm:/etc/hasplm` требуется для -[пробрасывания](https://docs.sentinel.thalesgroup.com/ldk/LDKdocs/SPNL/LDK_SLnP_Guide/Appendixes/Docker_containers.htm) -драйвера Sentinel в докер): - - $ sudo docker run --privileged --network host -v /etc/localtime:/etc/localtime:ro \ - -v /var/hasplm:/var/hasplm -v /etc/hasplm:/etc/hasplm \ - --rm -it -v $PWD:/fuzz sydr-fuzz-target /bin/bash - -Зайдите в директорию `/fuzz`: - - # cd /fuzz - -Запустите фаззинг: - - # sydr-fuzz run - -Если конфигурационный файл называется иначе чем `sydr-fuzz.toml`, то его можно -явно указать: - - # sydr-fuzz -c name.toml run - -В случае фаззинга с libFuzzer, можно дополнительно проверить, что обертка собрана -корректно. Для этого следует по логу убедиться, что покрытие (cov) растет. Если оно -не растет, то, возможно, либо входные данные не попадают в целевую функцию, либо -целевая библиотека собрана без инструментации libFuzzer. - -При фаззинге с AFL++ имеется возможность -[отслеживать]((https://github.com/AFLplusplus/AFLplusplus/blob/stable/docs/fuzzing_in_depth.md#e-the-status-of-the-fuzz-campaign)) -состояние AFL++ с помощью утилит `afl-whatsup` и `afl-plot`. Утилита `afl-whatsup` -показывает подробную статистику фаззинга для каждого запущенного процесса AFL++, -для этого достаточно указать общую директорию `aflplusplus`: - - $ afl-whatsup name-out/aflplusplus - -Утилита `afl-plot` позволяет строить графики для статистики работы AFL++, для этого -следует указать директорию конкретного процесса AFL++ и директорию для сохранения -построенных графиков: - - $ afl-plot name-out/aflplusplus/afl_main-worker plot_dir - -Число входных данных от Sydr, которые принесли покрытие фаззеру, печатается в -логе как "[SYDR] Files reloaded by libFuzzer: {}, unique {}" для libFuzzer и -"[SYDR] Files imported by AFL++: {}" для AFL++. Для libFuzzer дополнительно -печатается число уникальных полезных файлов, поскольку каждый запущенный -инстанс libFuzzer'а анализирует файлы независимо и один и тот же файл Sydr'а -может учитываться несколько раз. - -Сами полезные файлы можно найти следующим образом. - -Для libFuzzer: - - $ find name-out/libfuzzer -name "fuzz-*.log" | xargs -I {} grep -H --color "Reloaded.*sydr_" {} - -Для AFL++: - - $ ls name-out/aflplusplus/afl_main-worker/queue | grep "sync:sydr-worker" - -## Минимизация корпуса - -Чтобы минимизировать корпус, надо запустить команду `cmin`: - - $ sydr-fuzz -c name.toml cmin - -После этого содержимое оригинального корпуса будет помещено в директорию -`name-out/corpus-old`, минимизированный корпус будет в директории `name/corpus`. -Минимизация корпуса может быть запущена в несколько параллельных потоков, при -условии что утилита `afl-cmin` поддерживает такую функцию. Число параллельных -потоков указывается с помощью параметра `cmin` таблицы `[aflplusplus]` в конфигурационном -файле. По умолчанию используется половина всех доступных ядер на машине. - -## Сбор покрытия (C/C++/Rust) - -Sydr-fuzz позволяет собирать покрытие на корпусе для целевого приложения -и выполнять его обработку с помощью комманд llvm-cov. Для этого можно добавить -секцию `[cov]` в конфигурационный файл. Для AFL++ перед сбором -покрытия обязательно нужно провести минимизацию корпуса `sydr-fuzz cmin`, чтобы -собрать рабочие корпуса от всех процессов фаззера в одном месте. - -```toml -[sydr] -target = "/target_sydr @@" - -[libfuzzer] -path = "/target_fuzzer" - -[cov] -target = "/instrumented_target @@" -``` - -**target** - строка запуска инструментированного для сбора покрытия целевого исполняемого -файла. При сборке исполняемого файла следует использовать флаги: -`-fprofile-instr-generate -fcoverage-mapping`. Если `@@` отсутствует в строке запуска, то -входные данные принимаются из стандартного потока ввода. - -Для генерации HTML отчета о покрытии можно воспользоваться следующей командой: - - $ sydr-fuzz -c name.toml cov-html - -Для запуска сбора покрытия на корпусе проекта и вывода краткого отчёта с цветной разметкой -можно выполнить следующую команду: - - $ sydr-fuzz -c name.toml cov-report -- -use-color=true - -Для получения отчёта о покрытии в одном файле html (не рекомендуется для больших -проектов) можно воспользоваться следующей командой: - - $ sydr-fuzz -c name.toml cov-show -- -format=html > index.html - -Более того, можно получить покрытие в формате LCOV с его дальнейшей конвертацией -в html, что позволяет более гибко задавать опции: - - $ sydr-fuzz -c name.toml cov-export -- -format=lcov > name.lcov - $ genhtml -o name-cov-html name.lcov - -Если `genhtml` выдает ошибку `ERROR: cannot read /path/to/file`, то можно -запустить его с опцией `--ignore-errors source`. - -## Сбор покрытия (Python/Java/JavaScript) - -Sydr-fuzz позволяет собирать покрытие на корпусе для целевого Python-, Java- или JavaScript-кода, -выполнять его обработку и получать отчет в формате html. Для этого достаточно -использовать команду - - $ sydr-fuzz -c name.toml cov-html - -При сборе покрытия Java-кода через переменную окружения `CASR_SOURCE_DIRS` -можно указать пути до исходного кода (список путей, разделенных через ':'). -Тогда информация о нем будет отражена в html отчете: - - $ export CASR_SOURCE_DIRS=/dir/with/sources/1:/dir/with/sources/2 - $ sydr-fuzz cov-html - -## Сбор покрытия (Go) - -Sydr-fuzz позволяет собирать покрытие на корпусе для целевого Go-приложения. -Для этого можно добавить секцию `[cov]` в конфигурационный файл: - -```toml -[sydr] -target = "/target_sydr @@" - -[libfuzzer] -path = "/target_fuzzer" - -[cov] -target = "/target_cov.zip" -``` - -**target** - путь до инструментированной для сбора покрытия фаззинг-цели. Для -сборки следует использовать команду: - - $ go-fuzz-build -func=FuzzTest -o target_cov.zip - -Для генерации HTML отчета о покрытии можно воспользоваться следующей командой: - - $ sydr-fuzz -c name.toml cov-html - -## Чтение символьных данных в Sydr из стандартного потока ввода (C/C++/Rust/Go) - -Иногда может потребоваться написать обертку для Sydr, которая принимает входные -данные из стандартного потока ввода. Для этого необходимо указать `--sym-stdin` -в аргументах Sydr и не использовать `@@` в командной строке запуска обертки для -Sydr: - -```toml -[sydr] -args = "--sym-stdin" -target = "/target_sydr" -``` - -## Отдельный запуск фаззера (C/C++/Rust/Go) - -Sydr-fuzz поддерживает запуск фаззера без Sydr. Для этого необходимо заполнить -только секцию `[libfuzzer]`: - -```toml -exit-on-time = 7200 - -[libfuzzer] -path = "/target_fuzzer" -args = "-dict=/json.dict -jobs=6 /corpus" -``` - - или `[aflplusplus]`: - -```toml -exit-on-time = 7200 - -[aflplusplus] -args = "-t 5000 -i /corpus" -target = "/target_afl @@" -jobs = 6 -``` - -## Итеративный анализ Sydr (C/C++/Rust/Go) - -Sydr-fuzz поддерживает итеративный запуск Sydr без фаззера. Таким образом, Sydr -будет запускаться на файлах из корпуса и на сгенерированных новых входных данных -от предыдущих запусков Sydr. Для этого необходимо указать корпус в параметре -таблицы `[sydr]` **corpus**: - -```toml -[sydr] -args = "-n 2048 -j 4" -target = "/target_sydr @@" -corpus = "/corpus" -jobs = 3 -``` - -Файлы из директории, указанной в таблице `[sydr]` **corpus**, также будут -скопированы в директорию `corpus` внутри проекта. - -## Проверка предикатов безопасности (C/C++/Rust/Go) - -Sydr-fuzz позволяет запускать предикаты безопасности на корпусе из директории -проекта (`name-out/corpus`). - -Перед запуском проверки предикатов безопасности стоит минимизировать корпус (для -AFL++ этот шаг является обязательным): - - $ sydr-fuzz -c name.toml cmin - -Для запуска проверки предикатов безопасности можно выполнить следующую команду: - - $ sydr-fuzz -c name.toml security - -Sydr-fuzz самостоятельно изменит опции запуска Sydr для проверки предикатов -безопасности. - -Результаты запуска будут сохранены в директорию `/fuzz/name-out/security`. -Результаты, верифицированные санитайзерами, будут сохранены в директорию -`/fuzz/name-out/security-verified`. Уникальные верифицированные результаты будут -сохранены в директорию `/fuzz/name-out/security-unique`. Если результат, полученный с помощью -проверки предикатов безопасности, приводит к аварийному завершению программы, -результат будет сохранен в `/fuzz/name-out/crashes`. Логи, которые были проаннотированы во время -верификации, будут сохранены в директорию `/fuzz/name-out/sydr/annotated-logs`. - -Для запуска на произвольном входном корпусе можно использовать следующий -конфигурационный файл: - -```toml -[sydr] -args = "--security --no-invert" -target = "/target_sydr @@" -corpus = "/corpus" -jobs = 3 -``` - -**corpus** - директория с корпусом. - -Файлы из директории, указанной в таблице `[sydr]` **corpus**, также будут -скопированы в директорию `corpus` внутри проекта. - -## Анализ аварийных завершений и ошибок неопределенного поведения с помощью Casr - -Sydr-fuzz дает возможность осуществлять анализ аварийных завершений после фаззинга: -создание отчетов об аварийных завершениях, их дедупликация и кластеризация, а -также создание отчётов об ошибках неопределенного поведения. -Для этого должна существовать непустая директория `name-out/crashes` с входными данными. -Конфигурационный файл может выглядеть следующим образом (может быть использован -тот же конфиг, на основе которого производился фаззинг, возможно и с `[aflplusplus]`): - -```toml -[sydr] -target = "./target_sydr @@" - -[libfuzzer] -path = "./target_fuzzer" -``` - -Для запуска анализа Casr следует выполнить: - - $ sydr-fuzz -c name.toml casr - -В результате работы инструмента будет создана директория `name-out/casr`, в которой -по умолчанию будут находится кластеры, содержащие схожие отчеты об авариных завершениях `target_fuzzer` -после срабатывания санитайзера и отчеты об авариных завершениях `target_sydr` (если не указана опция `--no-casr-gdb`). -Также вместе с каждым отчетом будут лежать входные данные, вызвавшие соотвествующее аварийное завершение. -Создание кластеров или запуск `casr-gdb` можно пропустить, задав необходимые опции. - -AFL++ не отличает аварийное завершение от out of memory, поэтому приводящие к -oom файлы обнаруживаются с помощью Casr и сохраняются в директорию `casr/oom`. -Файлы, на которых произошел тайм-аут, сохраняются в директорию `casr/timeout`. - -Для того чтобы также производился анализ ошибок неопределенного поведения следует выполнить: - - $ sydr-fuzz -c name.toml casr --ubsan - -Отчёты будут составлены для всех срабатываний UBSAN на файлах из `name-out/casr` -(т.е. дедуплицированные и кластеризованные аварийные завершения), -`name-out/corpus` и `name-out/security-unique`. Поэтому перед использованием -данной команды рекомендуется провести минимизацию корпуса, т.е. запустить -`cmin`, а также `security` для получения отчётов для срабатываний предикатов -безопасности. При этом отчёты будут дедуплицироваться по строчке аварийного -завершения, т.е. в случае когда несколько ошибок произошло в одной и той же -строке, отчёт будет составлен только для первой из них со следующим приоритетом -(в порядке убывания): `name-out/security-unique`, `name-out/casr`, -`name-out/corpus`. Все ошибки неопределенного поведения имеют класс критичности -**NOT_EXPLIOTABLE** - -Для удобного просмотра отчетов можно воспользоваться специальным инструментом `casr-cli`: - - $ casr-cli name-out/casr/cl1/crash-deadbeef.casrep - -Можно выбрать другой вид отчета с помощью аргумента **--view**: - - $ casr-cli --view slider name-out/casr/cl1/crash-deadbeef.casrep - -Вывод отчета в stdout: - - $ casr-cli --view stdout name-out/casr/cl1/crash-deadbeef.casrep - -Также инструментом можно воспользоваться для просмотра общей статистики Casr директории, -содержащей отчеты или кластеры: - - $ casr-cli name-out/casr - -## DefectDojo - -Sydr-fuzz дает возможность выгружать уникальные CASR отчеты в систему DefectDojo. -[DefectDojo](https://github.com/DefectDojo/django-DefectDojo) -— это платформа для организации безопасности и управления уязвимостями. -Уникальность отчетов (за исключением UBSAN) определяется на основе стеков вызовов -в соответствии с алгоритмом дедупликации, представленным в CASR. -Дедупликация UBSAN отчетов производится по строчке исходного кода, в которой -произошло аварийное завершение (путь до файла с исходным кодом + номер строки). -Анализ выполняется в соответствии со следующими этапами: - -1. Указываются необходимые [API параметры](https://demo.defectdojo.org/api/v2/oa3/swagger-ui/) - DefectDojo (url, токен и имя продукта). -2. Для данного продукта будут получены все уже имеющие в - системе аварийные завершения, будет произведена дедупликация новых аварийных - завершений (из директории `out/casr`) и только уникальные - (с точки зрения наших алгоритмов) будут загружены в систему. -3. Каждый загружаемый элемент будет иметь описание с полями из CASR отчета - такими как строчка исходного кода, в которой произошло аварийное завершение, - критичность, описание ошибки, стек вызовов и проч. Также вместе с каждым CASR - отчетом в DefectDojo будет загружен отчет GDB CASR (если он есть) и файл - с входными данными, которые привели к рассматриваемому аварийному завершению. - -Подробные инструкции по установке DefectDojo могут быть найдены -[тут](https://github.com/DefectDojo/django-DefectDojo/blob/dev/readme-docs/DOCKER.md). -Для начала работы можно выполнить следующие команды: - - # git clone https://github.com/DefectDojo/django-DefectDojo.git - # cd django-DefectDojo - # ./dc-build.sh - # ./dc-up.sh - # # Wait for complete initialization: django-defectdojo_initializer_1 exited with code 0 - # # Get password for user "admin": - # docker-compose logs initializer | grep "Admin password:" - -Пример запуска `sydr-fuzz casr` с экспортом аварийных завершений в DefectDojo: - - # sydr-fuzz casr --url http://localhost:8080 --token 382f5dfdf2a339f7c3bb35442f9deb9b788a98d5 --product xlnt - -## Классы критичности - -В этой секции описаны классы критичности аварийных завершений. Классы аварийных завершений собраны в три группы: *критичные, потенциально критичные, отказ в обслуживании*. Некоторые прототипы классов взяты из библиотеки с открытым исходный кодом [gdb-exploitable](https://github.com/jfoote/exploitable.git). - -**Критичные (EXPLOITABLE)** - -Критичные аварийные завершения являются самыми опасными, исправлять такие аварийные завершения рекомендуется в первую очередь. Такие аварийные завершения могут легко привести к перехвату потока управления. - -Список классов: - -1. **SegFaultOnPc**. Попытка выполнить инструкцию по адресу, который не доступен для выполнения. Это может указывать на то, что атакующий уже контролирует счётчик команд. -2. **ReturnAv**. Аварийное завершение при выполнении инструкции возврата. Указывает на то, что произошла перезапись адреса возврата на стеке. -3. **BranchAv**. Аварийное завершение при выполнении инструкции ветвления. Указывает на то, что атакующий контролирует целевой адрес перехода. -4. **CallAv**. Аварийное завершение при выполнении инструкции вызова. Указывает на то, что атакующий контролирует целевой адрес вызова. -5. **DestAv**. Аварийное завершение при попытке записи в память машинного слова. Указывает на то, что вероятно атакующий контролирует адрес записи в память и потенциально записываемое значение (CWE-123). -6. **heap-buffer-overflow(write)**. Аварийное завершение при попытке записи за границами выделенного на куче буфера. -7. **global-buffer-overflow(write)**. Аварийное завершение при попытке записи за границами глобального буфера. -8. **stack-use-after-scope(write)**. Аварийное завершение при при записи по адресу стека за пределами лексической области времени существования переменной. -9. **stack-use-after-return(write)**. Аварийное завершение при записи в объект стека после возврата функции, в которой этот объект был определен. -10. **stack-buffer-overflow(write)**. Аварийное завершение при попытке записи за верхней границей выделенного на стеке буфера. -11. **stack-buffer-underflow(write)**. Аварийное завершение при попытке записи за нижней границей выделенного на стеке буфера. -12. **heap-use-after-free(write)**. Аварийное завершение при попытке записи в освобожденную память. -13. **container-overflow(write)**. Аварийное завершение при попытке записи в память внутри выделенного региона, но за текущими границами контейнера. -14. **param-overlap**. Вызов функции, запрещающей перекрывающиеся диапазоны памяти. - -**Потенциально критичные (PROBABLY_EXPLOITABLE)** - -Потенциально критичные аварийные классы требуют некоторого дополнительного (часто ручного) анализа, чтобы определить критичные они или нет. - -Список классов: - -1. **SourceAv**. Аварийное завершение при попытке чтения из памяти машинного слова. -2. **BadInstruction**. Невозомжно декодировать команду или выполнить привилегированную инструкцию. Это может указывать на то, что нарушитель перехватил управление, или же такую ситуацию создают искуственно программисты (аналог вызов функции `abort()`). -3. **SegFaultOnPcNearNull**. Попытка выполнить инструкцию по адресу, который не доступен для выполнения. Это может указывать на то, что атакующий уже контролирует счётчик команд, или же это происходит разыменование нулевого указателя. -4. **BranchAvNull**. Аварийное завершение при выполнении инструкции ветвления. Указывает на то, что атакующий контролирует целевой адрес перехода, или же это просто разыменование нулевого указателя. -5. **CallAvNearNull**. Аварийное завершение при выполнении инструкции вызова. Указывает на то, что атакующий контролирует целевой адрес вызова, или же это просто разыменование нулевого указателя. -6. **HeapError**. Аварийное завершение, порождённое вызывом функции `abort()` из кода менедежера динамической памяти. Частой причиной является переполнение буфера. -7. **StackGuard**. Произошла перезапись "канарейки" на стеке. -8. **DestAvNearNull**. Аварийное завершение при попытке записи в память машинного слова. Указывает на то, что вероятно атакующий контролирует адрес записи, или же это просто разыменование нулевого указателя. -9. **heap-buffer-overflow**. Аварийное завершение при попытке чтения или записи за границами выделенного на куче буфера. -10. **global-buffer-overflow**. Аварийное завершение при попытке чтения или записи за границами глобального буфера. -11. **stack-use-after-scope**. Аварийное завершение при использовании адреса стека за пределами лексической области времени существования переменной. -12. **use-after-poison**. Аварийное завершение при попытке использования памяти, которая была помечена с помощью специальных функций, как недоступная (poisoned memory). -13. **stack-use-after-return**. Аварийное завершение при попытке использования объекта стека после возврата функции, в которой этот объект был определен. -14. **stack-buffer-overflow**. Аварийное завершение при попытке чтения или записи за верхней границей выделенного на стеке буфера. -15. **stack-buffer-underflow**. Аварийное завершение при попытке чтения или записи за нижней границей выделенного на стеке буфера. -16. **heap-use-after-free**. Аварийное завершение при попытке использования освобожденной памяти. -17. **container-overflow**. Аварийное завершение при попытке использования памяти внутри выделенного региона, но за текущими границами контейнера. -18. **negaotive-size-param**. Использование отрицательного значения размера при доступе в память. -19. **calloc-overflow**. Переполение параметров функции `calloc`. -20. **readllocarray-overflow**. Переполение параметров функции `recalloc`. -21. **pvalloc-overflow**. Переполение параметров функции `pvalloc`. -22. **overwrites-const-input**. Аварийное завершение при попытке перезаписи неизменяемых входных данных. - -**Отказ в обслуживании (NOT_EXPLOITABLE)** - -Для классов отказов в обслуживании требуется дополнительный ручной анализ, для того чтобы установить, является ли аврийное завершение критичным или нет. -Также в эту группу входят аварийные завершения, которые с большой вероятностью не являются критичными с точки зрения перехвата потока управления. - -Список классов: - -1. **AbortSignal**. Программа получила сигнал SIGABRT. SIGABRTы часто генерируются библиотекой libc и встроенными защитами от переполнения буфера и т.д. -2. **AccessViolation**. Аварийное завершение при доступе к памяти. Требуется дополнительный анализ от разработчика для уточнения степени критичности. -3. **SourceAvNearNull**. Аварийное завершение при попытке чтения из памяти машинного слова, или же это просто разыменование нулевого указателя. -4. **SafeFunctionCheck**. Получение сигнала SIGABRT из-за срабатывания защиты внутри безопасной функции: `_chk()`. -5. **FPE**. Аварийное завершение при обработке арифметической инструкции с плавающей точкой. -6. **StackOverflow**. Аварийное завершение при попытке доступа в память. Последняя инструкция и указатель стека сигнализируют о возможной ошибке переполнения стека. -7. **double-free**. Аварийное завершение при попытке освободить уже освобожденную память. -8. **bad-free**. Аварийное завершение при попытке освободить невыделенную память. -9. **alloc-dealloc-mismatch**. Несоответствие API выеделения и освобождения. -10. **heap-buffer-overflow(read)**. Аварийное завершение при попытке чтения за границами выделенного на куче буфера. -11. **global-buffer-overflow(read)**. Аварийное завершение при попытке чтения за границами глобального буфера. -12. **stack-use-after-scope(read)**. Аварийное завершение при чтении с адреса стека за пределами лексической области времени существования переменной. -13. **stack-use-after-return(read)**. Аварийное завершение при попытке чтения объекта стека после возврата функции, в которой этот объект был определен. -14. **stack-buffer-overflow(read)**. Аварийное завершение при попытке чтения за верхней границей выделенного на стеке буфера. -15. **stack-buffer-underflow(read)**. Аварийное завершение при попытке чтения за нижней границей выделенного на стеке буфера. -16. **heap-use-after-free(read)**. Аварийное завершение при попытке чтения из освобожденной памяти. -17. **container-overflow(read)**. Аварийное завершение при попытке чтения из памяти внутри выделенного региона, но за текущими границами контейнера. -18. **initialization-order-fiasco**. Инициализатор для глобальной переменной обращается к динамически инициализируемой глобальной переменной из другой единицы трансляции, которая еще не инициализирована. -19. **new-delete-type-mismatch**. Размер выделенной памяти отличаестя от размера освобождаемой. -20. **bad-malloc_usable_size**. Неверный аргумент для функции `bad-malloc_usable_size`. -21. **odr-violation**. Определение одного и того же символа в различных модулях. -22. **memory-leaks**. Возникновение утечек памяти вследствие недостаточного отслеживания и освобождения выделенной памяти после ее использования. -23. **invalid-allocation-alignment**. Неверное выравнивание при выделении памяти. -24. **invalid-aligned-alloc-alignment**. Неверное выравнивание при вызове `aligned_alloc`. -25. **invalid-posix-memalign-alignment**. Неверное выравнивание при вызове `posix_memalign`. -26. **allocation-size-too-big**. Запрашиваемый размер памяти превышает максимально поддерживаемый. -27. **out-of-memory**. Аварийное завершение при превышении лимита памяти. -28. **fuzz target exited**. Завершение работы целевой программы. -29. **timeout**. Аварийное завершение при превышении лимита времени выполнения. - -# Sydr: Symbolic DynamoRIO - -Sydr - инструмент динамической символьной интерпретации на базе символьного -фреймворка [Triton](https://github.com/JonathanSalwan/Triton) и динамического -инструментатора [DynamoRIO](https://github.com/DynamoRIO/dynamorio). Инструмент -позволяет получить наборы входных данных для инвертирования условных переходов, -которые встретились по ходу выполнения программы. Более того, Sydr реализует -различные символьные предикаты безопасности для поиска ошибок выхода за границы -буфера, целочисленного переполнения, деления на нуль и др. - -Схема работы инструмента выглядит следующим образом: - -- Запуск программы на имеющихся наборах входных данных с целью построения - предиката пути (системы уравнений, описывающей поток управления программы). - Условие каждого перехода, зависящего от входных данных, добавляется в предикат - пути. -- Инвертирование переходов из предиката пути с использованием математического - решателя. В результате получаются новые входные данные, расширяющие покрытие - программы. Переходы инвертируются асинхронно одновременно с построением - предиката пути. - -Стек инструментов: - -- 4 уровень: инструмент динамической символьной интерпретации Sydr детектирует - входные данные, строит предикат пути, разрешает косвенные передачи управления - (switch), производит слайсинг предиката пути, инвертирует переходы, проверяет - ошибочные ситуации (предикаты безопасности), генерирует новые входные данные -- 3 уровень: символьный фреймворк - [Triton](https://github.com/JonathanSalwan/Triton) транслирует инструкции в - формулы, хранит символьное состояние регистров и памяти -- 2 уровень: математический решатель [Bitwuzla](https://bitwuzla.github.io) - проверяет - выполнимость формул, для выполнимых формул предоставляет модель (набор значений - переменных, при которых формула выполнима) -- 1 уровень: динамический инструментатор - [DynamoRIO](https://github.com/DynamoRIO/dynamorio) выполняет программу, - детектирует системные вызовы, предоставляет выполнявшиеся инструкции, значения - регистров и памяти - -# Использование Sydr - -В этом разделе представлено руководство пользователя инструмента Sydr. - -## Опции Sydr - - $ ./sydr --help - Usage: ./sydr [-h] [-v] [-f FILE] - [--sym-socket [=SOCKET(=*:*)]] - [--sym-argv] [--sym-arg N] - [--sym-env ENV_VAR] - [--sym-stdin [STDIN_MASK]] - [--sym-mem MEMORY] - [-o DIRECTORY (=out)] [--flat [TAG]] - [-r] [-d] [--dump-smt-failed] - [--python] [-t] [--no-edge-trace] - [-c DIRECTORY] [--config FILE] - [--wait-jobs [=N(=200)]] - [--follow-fork-mode MODE] - [--symbolize-address [=MODE(=address)]] - [--max-table-size ENTRIES (=200)] - [--table TABLE] [--fuzzmem [=NUM(=10)]] - [--fuzzmem-models [=NUM(=1000)]] - [--no-invert] [-b BRANCH] [-n N] - [--strategy DISTRIBUTION (=direct)] - [-j N (=1)] [--optimistic] [-p] - [--solving-timeout SECONDS (=10)] - [-s SECONDS] [--bad-chars CHARS] - [--models N (=1)] - [--security [=CHECKERS(=all)]] - [-l LEVEL (=info)] [--log-file FILE] - [--stats-file FILE] [--no-console-log] - [-m MEGABYTES] [--seed SEED] -- app - [args] - Sydr options: - - Generic options: - -h [ --help ] Show help. - -v [ --version ] Show version. - - Input: - -f [ --sym-file ] FILE Symbolic input file. Argument format: - '[,mask=]'. See the - full description at the end. - --sym-socket [=SOCKET(=*:*)] Symbolic socket. Argument format: - '[,mask=]'. See the - full description at the end. - --sym-argv Symbolic command line arguments. - --sym-arg N Symbolic N-th (starting from 1) command - line argument. - --sym-env ENV_VAR Symbolic environment variable. Argument - format: '[,mask=]'. - See the full description at the end. - --sym-stdin [STDIN_MASK] Symbolic stdin data. A path to mask - file may be specified as STDIN_MASK. - --sym-mem MEMORY Symbolic memory buffer. Argument - format: '[:],< - MEMORY_ACCESS>'. See the full - description at the end. - - Output: - -o [ --output-dir ] DIRECTORY (=out) Output directory to store generated - inputs. - --flat [TAG] Make flat output directory without - subdirectories for every input set. - Only one input source is supported for - the flat mode. This option also sets - --no-edge-trace. Generated input name - contains TAG. - -r [ --remove ] Remove output directory before run. - -d [ --dump-smt ] Dump SMT statements of execution - artifacts. - --dump-smt-failed Dump SMT statements for TIMEOUT, - OUTOFMEM, and UNKNOWN solver queries. - --python Use Python representation for formulas. - -t [ --trace ] Save instruction trace. - --no-edge-trace Do not save edge traces. - - Cache: - -c [ --cache ] DIRECTORY Directory to store Sydr shared cache. - Sydr skips already traversed branches - and found errors by security - predicates. Cache supported only with - direct inversion strategy. - - Config: - --config FILE Read options from configuration FILE. - If not specified, options are read from - sydr.toml (if it exists in current - directory). - - Symbolic interpretation: - --wait-jobs [=N(=200)] Stop path predicate builder thread when - there are already N scheduled jobs. - Resume the thread when all jobs are - processed. - --follow-fork-mode MODE Perform symbolic interpretation only of - parent|child process. - - Symbolic addresses: - --symbolize-address [=MODE(=address)] Enable symbolic address processing for - memory load operations. MODE - address|memory defines how symbolic - values would be handled. In address - mode only symbolic addresses are - processed, while all symbolic memory - cells are concretized. Memory mode - allows to handle symbolic memory cells - too. - --max-table-size ENTRIES (=200) Max table size in entries for both - symbolic addresses and jump tables. - Restricts memory region that - potentially can be accessed via - symbolic address. - --table TABLE Memory table location for symbolic - addresses and jump tables. Table - described by module, start address, and - length in bytes. Argument format: - ',,' or - ','. is a - hex or decimal value. - --fuzzmem [=NUM(=10)] Fuzz symbolic addresses on memory reads - and writes with SMT solver. Picking up - different symbolic address values until - solver returns UNSAT or NUM different - values are generated. - --fuzzmem-models [=NUM(=1000)] Maximum models generated for symbolized - addresses fuzzing in one Sydr run. - - Branch selection: - --no-invert Do not invert branches. - -b [ --invert-branch ] BRANCH A program branch to invert. Argument - format: ',' - or ''. - -n [ --invert-n ] N Try to invert N branches and stop. - --strategy DISTRIBUTION (=direct) Branches inversion order and selection - strategy direct|reverse|uniform. Invert - branches in direct order from first to - last, invert branches in reverse order, - or random shuffle branches order - uniformly. - - Solving: - -j [ --jobs ] N (=1) Number of parallel solving jobs. - --optimistic Enable optimistic solving. Try to solve - only target branch constraint on - failure. Moreover, try eliminating - constraints from non-nested branches - and function calls. - -p [ --path-predicate ] Solve path predicate. - --solving-timeout SECONDS (=10) Timeout for one solver query. - -s [ --solving-limit ] SECONDS Total solving time limit. - --bad-chars CHARS Restricted characters in symbolic input - that should be avoided. Argument - format: '[,]'. - BAD_CHARS define a specific character - (32 or 0x20) or a range of characters - (9-13). Optionally characters may be - restricted for specified symbolic input - OFFSET (0x123 or 10-100). - --models N (=1) Maximum number of models to generate - for each branch or security predicate. - - Security predicates: - --security [=CHECKERS(=all)] Run with checking comma-separated - security predicates: zerodiv - division - by zero; bounds - out of bounds access; - null - null pointer dereference; - intoverflow - integer overflow; - intoverflow-inst - integer overflow - sink is instruction; intoverflow-func - - integer overflow sink is function - argument; intoverflow-func-risk - - integer overflow in risky function - argument; invalid-heap - invalid free, - double free, or invalid realloc; - negsize - negative size argument in - allocation and string functions; trunc - - numeric truncation error; - injection - OS command injection; - format - controlled format string - injection. -. - - Logging: - -l [ --log-level ] LEVEL (=info) Specify logging level - fatal|error|warning|info|debug|trace. - --log-file FILE Save log to FILE. If not specified, log - is saved to sydr.log in output - directory. - --stats-file FILE Save stats to FILE. If not specified, - stats file is saved to stats.json in - output directory. - --no-console-log Do not print log to console. - - Parameters: - -m [ --memory-limit ] MEGABYTES Maximum memory consumption. - --seed SEED Pseudo-random number generator seed. - - Suboptions: - --sym-env [,mask=] - - ENV_VAR Symbolic environment variable name. - mask=MASK_FILE Environment variable mask. - - --sym-file [,mask=] - - FILE Symbolic file name. - mask=MASK_FILE File mask. - - --sym-mem , - - LOCATION Instruction module name and instruction - address. LOCATION format: '[:]'. - MEMORY_ACCESS Expression containing symbolic memory b - uffer address and size. MEMORY_ACCESS f - ormat: 'v(
,)' or '(,)', where '
' and '< - size>' can contain arithmetic operation - s (+, -, *) on MEMORY_ACCESS expression - s, registers (rax, eax, r8, ...), and c - onstants (decimal: 12, hex: 0x12, oct: - 012). - - --sym-socket [,mask=] - - SOCKET Symbolic socket: :. May be wi - ldcard: *:*. - mask=MASK_FILE Socket mask. - - MASK_FILE - file each line of which contains points or intervals (delimited by - '-') of symbolic bytes. Only these bytes will be symbolized. - -Опции можно задавать как в командной строке, так и в файле конфигурации с помощью опции командной строки `--config`. При отсутствии опции `--config` в командной строке файлом конфигурации по умолчанию считается `sydr.toml`, если такой файл существует в текущей директории. - -Опции, определённые в командной строке, считаются более приоритетными, чем опции, определённые в файле конфигурации. -При определении опции с одним и тем же именем и в командной строке, и в файле конфигурации будет -выбрано значение, определённое в командной строке. Однако существуют опции, которые можно задавать -только в файле конфигурации, например, эмуляция задаётся таблицей `emu`. -Подробное описание задания опций через конфигурационный файл можно найти в разделе "Формат конфигурационного файла". - -### Символьные входные данные - -Опция **-f [ \--sym-file ] FILE** указывает на путь к файлу, который считается -символьным (его содержимое будет подбираться в рамках символьной интерпретации). -Если программа на вход получает несколько файлов, то можно также отметить -несколько файлов как символьные. Для этого нужно повторить опцию необходимое -количество раз. - -Опция **\--sym-socket [SOCKET]** указывает на символьное сетевое соединение. -Данные, полученные программой с соответствующего ip-адреса и порта, будут -считаться символьными. Опция **\--sym-socket** без дополнительных параметров -указывает, что все данные, полученные по сети, являются символьными. - -Опция **\--sym-argv** указывает, что все аргументы, полученные программой (вся -строка), считаются символьными. - -Опция **\--sym-arg N** указывает, что конкретный аргумент является символьным. -Аргументы нумеруются с **единицы**. Опция может повторяться с различными номерами -нужное количество раз. - -Опция **\--sym-env ENV_VAR** указывает, что переменная среды с именем `ENV_VAR` -становится символьной. Эта опция может повторяться требуемое число раз. - -Опция **\--sym-stdin [STDIN_MASK]** указывает, что входные данные, полученные со -стандартного потока ввода, являются символьными. - -Опция **\--sym-mem [MODULE_NAME:]INSTR_ADDR,MEMORY_ACCESS** указывает, что буфер -на инструкции по адресу `[MODULE_NAME:]INSTR_ADDR` является символьным (содержит -входные данные). Адрес инструкции внутри модуля указывается с учётом базы -загрузки (image base). Адрес и размер буфера указывается в `MEMORY_ACCESS`. -Формат `MEMORY_ACCESS`: `v(address, size)` или `(address, size)`, где `address` -и `size` могут содержать арифметические операции (+, -, \*) над выражениями -`MEMORY_ACCESS`, регистрами (rax, eax, r8, ...) и константами (десятичными 12, -шестнадцатеричными 0x12 и восьмеричными 012). - -### Выходные данные - -Опция **-o [ \--output-dir ] DIRECTORY** является обязательной. Путь до -директории с результатами. Директория создастся автоматически. Если директория -уже создана, будет выведено сообщение об ошибке. Инструмент в целях -непреднамеренной перезаписи результатов требует отсутствие директории, в которую -будут записаны текущие результаты. - -Опция **\--flat** позволяет сделать выходную директорию плоской. Каждый новый набор -входных данных будет генерироваться не в отдельной поддиректории, а в общей выходной -директории. Такой режим удобен для использования в гибридном фаззинге, где требуется -создавать только корпус новых файлов без какой-либо дополнительной информации. Опция -поддерживает только работу с одним источником символьных данных (файл, стандартный -поток ввода или буфер в памяти). Файлы лога `sydr.log` и статистики `stats.json` -будут также созданы в выходной директории, если не указать другой путь с помощью опций -`--log-file` и `--stats-file`. Опция `--flat` имеет параметр `TAG`, который добавляется -в имена сгенерированных файлов (а также в `sydr_tag.log` и `stats_tag.json`, если не указано -иного через соответствующие опции). Добавление тега к именам файлов позволяет безопасно -использовать одну и ту же выходную директорию при запуске нескольких процессов Sydr -подряд или одновременно. Обычно в качестве тега указывается уникальное имя входного -файла, на котором был запущен Sydr (по умолчанию тег не задан). При включении опции -`--flat` автоматически выключается генерация trace-файлов. Имена новых файлов имеют -следующий формат: `sydr__