
Шаблонно-управляемый фаззер бинарных форматов, который генерирует и разбирает корректные тестовые входные данные с высокой скоростью, с интеграцией AFL++ для фаззинга, управляемого покрытием.
FormatFuzzer — это фреймворк для высокоэффективной и высококачественной генерации и разбора бинарных входных данных.
Он принимает бинарный шаблон, описывающий формат бинарного ввода, и создает исполняемый файл, который производит и разбирает заданный бинарный формат.
Например, из бинарного шаблона для GIF FormatFuzzer создает генератор GIF — также известный как фаззер GIF.
Создаваемые FormatFuzzer генераторы чрезвычайно эффективны: они производят тысячи корректных тестовых входных данных в секунду — в резком контрасте с мутационными фаззерами, где подавляющее большинство входных данных является недопустимым. Входные данные, генерируемые FormatFuzzer, не зависят от тестируемой программы (или вообще от любой программы), поэтому их можно использовать и в условиях black-box. Однако FormatFuzzer также интегрируется с AFL++ для создания корректных входных данных, которые также стремятся к максимальному покрытию. В наших экспериментах этот подход «лучшее из двух миров» превзошел все остальные конфигурации; подробности см. в нашей статье.
Бинарные шаблоны, используемые FormatFuzzer, взяты из 010 editor.
Существует более 170 бинарных шаблонов, которые можно использовать напрямую для FormatFuzzer или адаптировать для его нужд. «Из коробки» FormatFuzzer поддерживает такие форматы, как AVI, BMP, GIF, JPG, MIDI, MP3, MP4, PCAP, PNG, WAV и ZIP; и мы еженедельно пополняем этот список.
Участники приветствуются! Посетите страницу проекта FormatFuzzer, чтобы оставить идеи и сообщить о проблемах или добавить pull request. Подробности о том, как работает FormatFuzzer и как он сравнивается с другими инструментами, читайте в нашей статье.
FormatFuzzer доступен на странице проекта FormatFuzzer. Вы можете скачать и распаковать последний релиз со страницы релизов.
Для самого последнего и самого лучшего вы также можете клонировать его git-репозиторий:
git clone https://github.com/uds-se/FormatFuzzer.git
Все дальнейшие действия выполняются в его основной папке:
cd FormatFuzzer
Для запуска FormatFuzzer необходимо следующее:
getopt_long()), такой как clang или gccpy010parser, six и intervaltreezlib (для функций сжатия)boost (для функций контрольных сумм)Если вы планируете редактировать сценарии сборки и настройки (файлы .ac и .am), вам также понадобятся
sudo apt install git g++ make automake python3-full zlib1g-dev libboost-dev
python3 -m venv ~/fuzz
source ~/fuzz/bin/activate
pip3 install py010parser six intervaltree
xcode-select --install
brew install python3 automake boost
pip3 install py010parser six intervaltree
На всех системах с помощью pip:
pip install py010parser
pip install six
pip install intervaltree
Примечание: все команды сборки требуют, чтобы вы находились в той же папке, где находится этот файл README. Сборка фаззера вне этой папки пока не поддерживается.
Существует скрипт build.sh, который автоматизирует все этапы построения.
Просто выполните
./build.sh gif
чтобы создать фаззер GIF.
Это работает для всех форматов файлов, предоставленных в templates/; если есть файл templates/FOO.bt, то ./build.sh FOO соберет фаззер.
Существует Makefile (исходник в Makefile.am), который автоматизирует все этапы построения.
(Требуется GNU make.)
Сначала выполните
touch configure Makefile.in
затем
./configure
и затем
make gif-fuzzer
чтобы создать фаззер GIF.
Это работает для всех форматов файлов, предоставленных в templates/; если есть файл templates/FOO.bt, то make FOO-fuzzer соберет фаззер.
Если описанный выше метод make не работает или вы хотите больше контроля, возможно, вам придется действовать вручную.
Запустите компилятор ffcompile, чтобы скомпилировать бинарный шаблон в код C++. Он принимает два аргумента: файл .bt бинарного шаблона и файл .cpp, который будет сгенерирован.
./ffcompile templates/gif.bt gif.cpp
Используйте следующие команды для создания фаззера gif-fuzzer.
Сначала скомпилируйте универсальный драйвер командной строки:
g++ -c -I . -std=c++17 -g -O3 -Wall fuzzer.cpp
(-I . указывает расположение файла bt.h; -std=c++17 задает стандарт C++.)
Затем скомпилируйте парсер/генератор бинарного формата:
g++ -c -I . -std=c++17 -g -O3 -Wall gif.cpp
Наконец, скомпонуйте парсер/генератор с драйвером командной строки, чтобы получить исполняемый файл. Если вы используете какие-либо дополнительные библиотеки (например, -lz), обязательно укажите их здесь.
g++ -O3 gif.o fuzzer.o -o gif-fuzzer -lz
FormatFuzzer может использоваться как самостоятельный парсер, генератор или мутатор конкретных форматов. Кроме того, он может вызываться универсальными фаззерами, такими как AFL++, для интеграции функций, специфичных для формата, в процесс фаззинга (см. раздел ниже об интеграции с AFL++).
Сгенерированный фаззер принимает команду в качестве первого аргумента, за которой следуют параметры и аргументы этой команды.
Самой важной командой является fuzz, предназначенная для создания выходных данных. Ее аргументами являются файлы, которые нужно сгенерировать в соответствующем формате.
Запустите генератор как
./gif-fuzzer fuzz output.gif
чтобы создать случайный бинарный файл output.gif, или
./gif-fuzzer fuzz out1.gif out2.gif out3.gif
чтобы создать три файла GIF: out1.gif, out2.gif и out3.gif.
Обратите внимание, что предоставленный нами шаблон gif.bt дополнен специальными функциями, упрощающими создание корректных файлов. Если вы используете оригинальные файлы .bt без адаптации, вы можете получить предупреждения во время генерации и создать некорректные файлы.
Вы также можете запустить фаззер как парсер бинарных файлов, используя команду parse. Это полезно, если вы хотите проверить точность бинарного шаблона или если вы хотите мутировать входные данные (см. раздел «Файлы решений» ниже).
Чтобы запустить парсер, выполните
./gif-fuzzer parse input.gif
Вы увидите сообщения об ошибках, если input.gif не может быть успешно разобран.
Во время разбора вы также можете сохранить все решения, принимаемые при разборе (т.е. какие альтернативы разбора были выбраны) в файл решений. Это последовательность байтов, перечисляющая принятые решения.
Каждый байт представляет собой одно решение о разборе. Значение байта 0 означает, что была выбрана первая альтернатива, значение 1 — вторая, и так далее.
Вы можете сгенерировать такой файл решений при разборе входного файла:
./gif-fuzzer parse --decisions input.dec input.gif
Здесь input.dec сохраняет решения, принятые для разбора input.gif.