Применение AFL++ для фаззинга целей подготовленных для LibFuzzer в QEMU: различия между версиями
Andrei (обсуждение | вклад) (Новая страница: «В AFL++ есть поддержка фаззинг-целей подготовленных для LibFuzzer. Сравнение скорости фаззинга для разных фаззеров») |
Andrei (обсуждение | вклад) Нет описания правки |
||
(не показаны 2 промежуточные версии этого же участника) | |||
Строка 1: | Строка 1: | ||
В AFL++ есть поддержка фаззинг-целей подготовленных для LibFuzzer. | [[Category:SDL]] | ||
В AFL++ есть [https://github.com/AFLplusplus/AFLplusplus/blob/stable/utils/aflpp_driver/README.md поддержка] фаззинг-целей подготовленных для LibFuzzer. | |||
Поэтому сборка целей LibFuzzer&AFL++ для qemu выглядит таким образом: | |||
'''1) Подготовка исходников QEMU&Meson'''<br> | |||
Скачиваем meson, копилируем. Qemu скачиваем из репозитория ALT и подготавливаем. | |||
<source lang="sh"> | |||
RUN wget https://github.com/mesonbuild/meson/releases/download/0.61.3/meson-0.61.3.tar.gz && \ | |||
tar -xf meson-0.61.3.tar.gz | |||
RUN git clone http://git.altlinux.org/gears/q/qemu.git && \ | |||
cd qemu && \ | |||
git checkout 8.0.0-alt1.p10 && \ | |||
gear --commit --rpmbuild -- rpmbuild --buildroot=/home/$cuidname/fuzz_target -bp | |||
</source> | |||
'''2) Задаём в переменных окружения компилятор AFL++'''<br> | |||
Иногда для проектов могут потребоваться задания линковщика как afl-clang-lto или afl-ld-lto, но мы соберем с LD=lld: | |||
<source lang="sh"> | |||
ENV CC=afl-clang-fast | |||
ENV CXX=afl-clang-fast++ | |||
#ENV LD=afl-clang-lto | |||
#ENV LD=afl-ld-lto | |||
ENV LD=lld | |||
</source> | |||
'''3) Запускаем компиляцию QEMU с afl-clang'''<br> | |||
Компилируем исходники подготовленные gear на первом шаге: | |||
<source lang="sh"> | |||
RUN cd /home/$cuidname/RPM/BUILD/qemu-8.0.0 && \ | |||
mkdir build_afl && cd build_afl && \ | |||
../configure --enable-fuzzing --disable-strip --disable-werror --meson=/home/user/meson-0.61.3/meson.py \ | |||
&& ninja -j8 qemu-fuzz-i386 | |||
</source> | |||
'''4) Готовим исполняемые файлы для фаззинга на основе скомпилированного qemu-fuzz-i386'''<br> | |||
AFL++ в текущем виде(4.08с) умеет работать с одиночными целями LibFuzzer. А в qemu-fuzz-i386 собраны несколько целей[https://github.com/qemu/qemu/blob/master/tests/qtest/fuzz/fuzz.c подробнее], и AFL++ не может корректно распознать их по параметру -target, зато распознаёт цели по имени исполняемого файла. Поэтому нужно собрать возможные цели и создать копии qemu-fuzz-i386 с именем цели в названии файла: | |||
<source lang="sh"> | |||
targets=$(./qemu-fuzz-i386 | grep generic-fuzz | awk '$1 ~ /\*/ {print $2}') && \ | |||
targets+=" " && targets+=$(./qemu-fuzz-i386 | grep -v generic | grep virtio- | awk '$1 ~ /\*/ {print $2}') && \ | |||
targets+=" " && targets+=$(./qemu-fuzz-i386 | grep -v generic | grep i440fx- | awk '$1 ~ /\*/ {print $2}') && \ | |||
for tgt in $targets ; do echo "Copy qemu-fuzz-i386 to /home/user/afl_fuzz_target with target name ${tgt}" ; \ | |||
cp qemu-fuzz-i386 /home/user/afl_fuzz_target/qemu-fuzz-i386-target-${tgt} ;\ | |||
cp -f qemu-fuzz-i386 qemu-fuzz-i386-target-${tgt} ; done | |||
</source> | |||
'''5) Запуск фаззинга AFL++&LibFuzzer'''<br> | |||
К сожалению, сейчас AFL++ не совсем корректно работает с фаззингом цели LibFuzzer в QEMU. При запуске переходит shmem и уходит в бесконечный цикл и таймаут. Похоже AFL ждёт, пока выполнится очередной инпут, а LibFuzzer уходит в режим фаззинга. Мы можем обойти эту ошибку отключив проверку исполняемого файла при запуске фаззига в AFL++: | |||
<source lang="sh"> | |||
AFL_SKIP_BIN_CHECK=1 AFL_MAP_SIZE=300000 AFL_SKIP_CPUFREQ=1 AFL_AUTORESUME=1 AFL_SKIP_CPUFREQ=1 afl-fuzz -t 500000 -i ${input_dir} -o ${OUT_DIR}/afl -S ${target_name} -- ${exec_target} @@" | |||
</source> | |||
'''Выбор версий компилятора и фаззера'''<br> | |||
К сожалению, не со всеми версиями clang&aflplusplus подобный подход работает. В моём случае получилось собрать с версиями clang-15(ALT Linux Team clang version 15.0.7), afl++ 4.08-9(commit hash: 61e27c6b54f7641a168b6acc6ecffb1754c10918), meson-0.61.3, qemu 8.0.0-alt1.p10. | |||
'''Результаты применения AFL++ для фаззинга целей LibFuzzer в QEMU'''<br> | |||
Требовалось оценить, получится ли с использованием AFL++ значительно повысить прирост покрытия при фаззинге целей, которые уже до этого фаззились с помощью LibFuzzer в течении нескольких(3-4) месяцев. При этом новое покрыти уже практически не находилось фаззером для этих целей. | |||
Эксперимент показал, что за месяц фаззинга прирост новых edges небольшой. В пределах 10-20. Тем не менее, он есть и этому частично способствует обмен корпусом между разными потоками фаззинга, которые фаззят разные цели LibFuzzer. | |||
Результаты прироста покрытия по целям. В зачёт идут только новые найденные потоком пути, не учитывая корпус полученным в рамках обмена между целями. | |||
: | |||
<source lang="sh"> | |||
i440fx-qtest-reboot-fuzz/fuzzer_stats:corpus_found : 10 | |||
i440fx-qos-noreset-fuzz/fuzzer_stats:corpus_found : 226 | |||
generic-fuzz-ahci-hd/fuzzer_stats:corpus_found : 11 | |||
generic-fuzz-virtio-rng/fuzzer_stats:corpus_found : 13 | |||
generic-fuzz/fuzzer_stats:corpus_found : 2 | |||
generic-fuzz-es1370/fuzzer_stats:corpus_found : 11 | |||
generic-fuzz-virtio-blk/fuzzer_stats:corpus_found : 9 | |||
master/fuzzer_stats:corpus_found : 0 | |||
generic-fuzz-xhci/fuzzer_stats:corpus_found : 11 | |||
generic-fuzz-cs4231a/fuzzer_stats:corpus_found : 9 | |||
generic-fuzz-ne2k_pci/fuzzer_stats:corpus_found : 7 | |||
generic-fuzz-floppy/fuzzer_stats:corpus_found : 5 | |||
generic-fuzz-virtio-serial/fuzzer_stats:corpus_found : 14 | |||
generic-fuzz-virtio-balloon/fuzzer_stats:corpus_found : 11 | |||
generic-fuzz-sb16/fuzzer_stats:corpus_found : 7 | |||
generic-fuzz-cirrus-vga/fuzzer_stats:corpus_found : 8 | |||
generic-fuzz-am53c974/fuzzer_stats:corpus_found : 11 | |||
generic-fuzz-ide-hd/fuzzer_stats:corpus_found : 14 | |||
generic-fuzz-virtio-9p-synth/fuzzer_stats:corpus_found : 13 | |||
generic-fuzz-vmxnet3/fuzzer_stats:corpus_found : 7 | |||
generic-fuzz-ahci-atapi/fuzzer_stats:corpus_found : 6 | |||
qemu-img_chain/fuzzer_stats:corpus_found : 312 | |||
virtio-blk-flags-fuzz/fuzzer_stats:corpus_found : 24 | |||
generic-fuzz-igb/fuzzer_stats:corpus_found : 9 | |||
generic-fuzz-rtl8139/fuzzer_stats:corpus_found : 7 | |||
generic-fuzz-virtio-scsi/fuzzer_stats:corpus_found : 7 | |||
generic-fuzz-intel-hda/fuzzer_stats:corpus_found : 16 | |||
generic-fuzz-virtio-9p/fuzzer_stats:corpus_found : 10 | |||
generic-fuzz-megaraid/fuzzer_stats:corpus_found : 16 | |||
generic-fuzz-pcnet/fuzzer_stats:corpus_found : 9 | |||
generic-fuzz-ide-atapi/fuzzer_stats:corpus_found : 7 | |||
generic-fuzz-pc-q35/fuzzer_stats:corpus_found : 7 | |||
generic-fuzz-ehci/fuzzer_stats:corpus_found : 15 | |||
virtio-net-socket-check-used/fuzzer_stats:corpus_found : 13 | |||
generic-fuzz-i82550/fuzzer_stats:corpus_found : 8 | |||
generic-fuzz-virtio-mouse/fuzzer_stats:corpus_found : 15 | |||
generic-fuzz-virtio-gpu/fuzzer_stats:corpus_found : 9 | |||
generic-fuzz-e1000/fuzzer_stats:corpus_found : 12 | |||
generic-fuzz-sdhci-v3/fuzzer_stats:corpus_found : 11 | |||
generic-fuzz-e1000e/fuzzer_stats:corpus_found : 6 | |||
generic-fuzz-ac97/fuzzer_stats:corpus_found : 11 | |||
generic-fuzz-parallel/fuzzer_stats:corpus_found : 14 | |||
generic-fuzz-bochs-display/fuzzer_stats:corpus_found : 12 | |||
generic-fuzz-ohci/fuzzer_stats:corpus_found : 13 | |||
generic-fuzz-pc-i440fx/fuzzer_stats:corpus_found : 8 | |||
virtio-scsi-flags-fuzz/fuzzer_stats:corpus_found : 22 | |||
generic-fuzz-virtio-vga/fuzzer_stats:corpus_found : 8 | |||
</source> | |||
'''Выводы'''<br> | |||
Эксперимент показал, что нахождение нового покрытия с подключение AFL++ возможно. Однако в рамках текущей конфигурации прирост будет не слишком высоким. | |||
Причины этого: | |||
1) Достаточно глубокое покрытие целей фаззером LibFuzzer. Поскольку большей частью цели не слишком "сложные", они и так достаточно качественно фаззятся. | |||
2) Медленная работа AFL++ в текущей конфигурации. Поскольку для фаззинга приходится выключать форк-сервер и обмен данными через оперативную память, то скорость фаззинга падает значительно. | |||
3) Проблемы с оценкой прироста покрытия в LibFuzzer и AFL++. При использовании корпуса наработанного в LibFuzzer в качестве начального для AFL++, значительная часть корпуса отбрасывается как не добавляющая покрытия. Это странно, с учётом того, что LibFuzzer считал эти файлы значимыми и добавляющими покрытие. Возможно в текущей конфигурации часть исполняемого файла не инструментирована AFL++ или на оценку влияют еще какие-то неучтённые факторы. | |||
Тем не менее, имеет смысл запускать фаззинг AFL++ для новых целей хотя бы для того, чтоб убедится в отсутствии прироста покрытия для них. Возможно имеет смысл использовать дополнительные средства инструментации, но этот вопрос требует дополнительного изучения. | |||
[[https://arxiv.org/pdf/2212.09519.pdf|Сравнение скорости фаззинга для разных фаззеров]] | [[https://arxiv.org/pdf/2212.09519.pdf|Сравнение скорости фаззинга для разных фаззеров]] |
Текущая версия от 12:01, 18 января 2024
В AFL++ есть поддержка фаззинг-целей подготовленных для LibFuzzer.
Поэтому сборка целей LibFuzzer&AFL++ для qemu выглядит таким образом:
1) Подготовка исходников QEMU&Meson
Скачиваем meson, копилируем. Qemu скачиваем из репозитория ALT и подготавливаем.
RUN wget https://github.com/mesonbuild/meson/releases/download/0.61.3/meson-0.61.3.tar.gz && \
tar -xf meson-0.61.3.tar.gz
RUN git clone http://git.altlinux.org/gears/q/qemu.git && \
cd qemu && \
git checkout 8.0.0-alt1.p10 && \
gear --commit --rpmbuild -- rpmbuild --buildroot=/home/$cuidname/fuzz_target -bp
2) Задаём в переменных окружения компилятор AFL++
Иногда для проектов могут потребоваться задания линковщика как afl-clang-lto или afl-ld-lto, но мы соберем с LD=lld:
ENV CC=afl-clang-fast
ENV CXX=afl-clang-fast++
#ENV LD=afl-clang-lto
#ENV LD=afl-ld-lto
ENV LD=lld
3) Запускаем компиляцию QEMU с afl-clang
Компилируем исходники подготовленные gear на первом шаге:
RUN cd /home/$cuidname/RPM/BUILD/qemu-8.0.0 && \
mkdir build_afl && cd build_afl && \
../configure --enable-fuzzing --disable-strip --disable-werror --meson=/home/user/meson-0.61.3/meson.py \
&& ninja -j8 qemu-fuzz-i386
4) Готовим исполняемые файлы для фаззинга на основе скомпилированного qemu-fuzz-i386
AFL++ в текущем виде(4.08с) умеет работать с одиночными целями LibFuzzer. А в qemu-fuzz-i386 собраны несколько целейподробнее, и AFL++ не может корректно распознать их по параметру -target, зато распознаёт цели по имени исполняемого файла. Поэтому нужно собрать возможные цели и создать копии qemu-fuzz-i386 с именем цели в названии файла:
targets=$(./qemu-fuzz-i386 | grep generic-fuzz | awk '$1 ~ /\*/ {print $2}') && \
targets+=" " && targets+=$(./qemu-fuzz-i386 | grep -v generic | grep virtio- | awk '$1 ~ /\*/ {print $2}') && \
targets+=" " && targets+=$(./qemu-fuzz-i386 | grep -v generic | grep i440fx- | awk '$1 ~ /\*/ {print $2}') && \
for tgt in $targets ; do echo "Copy qemu-fuzz-i386 to /home/user/afl_fuzz_target with target name ${tgt}" ; \
cp qemu-fuzz-i386 /home/user/afl_fuzz_target/qemu-fuzz-i386-target-${tgt} ;\
cp -f qemu-fuzz-i386 qemu-fuzz-i386-target-${tgt} ; done
5) Запуск фаззинга AFL++&LibFuzzer
К сожалению, сейчас AFL++ не совсем корректно работает с фаззингом цели LibFuzzer в QEMU. При запуске переходит shmem и уходит в бесконечный цикл и таймаут. Похоже AFL ждёт, пока выполнится очередной инпут, а LibFuzzer уходит в режим фаззинга. Мы можем обойти эту ошибку отключив проверку исполняемого файла при запуске фаззига в AFL++:
AFL_SKIP_BIN_CHECK=1 AFL_MAP_SIZE=300000 AFL_SKIP_CPUFREQ=1 AFL_AUTORESUME=1 AFL_SKIP_CPUFREQ=1 afl-fuzz -t 500000 -i ${input_dir} -o ${OUT_DIR}/afl -S ${target_name} -- ${exec_target} @@"
Выбор версий компилятора и фаззера
К сожалению, не со всеми версиями clang&aflplusplus подобный подход работает. В моём случае получилось собрать с версиями clang-15(ALT Linux Team clang version 15.0.7), afl++ 4.08-9(commit hash: 61e27c6b54f7641a168b6acc6ecffb1754c10918), meson-0.61.3, qemu 8.0.0-alt1.p10.
Результаты применения AFL++ для фаззинга целей LibFuzzer в QEMU
Требовалось оценить, получится ли с использованием AFL++ значительно повысить прирост покрытия при фаззинге целей, которые уже до этого фаззились с помощью LibFuzzer в течении нескольких(3-4) месяцев. При этом новое покрыти уже практически не находилось фаззером для этих целей.
Эксперимент показал, что за месяц фаззинга прирост новых edges небольшой. В пределах 10-20. Тем не менее, он есть и этому частично способствует обмен корпусом между разными потоками фаззинга, которые фаззят разные цели LibFuzzer. Результаты прироста покрытия по целям. В зачёт идут только новые найденные потоком пути, не учитывая корпус полученным в рамках обмена между целями.
i440fx-qtest-reboot-fuzz/fuzzer_stats:corpus_found : 10
i440fx-qos-noreset-fuzz/fuzzer_stats:corpus_found : 226
generic-fuzz-ahci-hd/fuzzer_stats:corpus_found : 11
generic-fuzz-virtio-rng/fuzzer_stats:corpus_found : 13
generic-fuzz/fuzzer_stats:corpus_found : 2
generic-fuzz-es1370/fuzzer_stats:corpus_found : 11
generic-fuzz-virtio-blk/fuzzer_stats:corpus_found : 9
master/fuzzer_stats:corpus_found : 0
generic-fuzz-xhci/fuzzer_stats:corpus_found : 11
generic-fuzz-cs4231a/fuzzer_stats:corpus_found : 9
generic-fuzz-ne2k_pci/fuzzer_stats:corpus_found : 7
generic-fuzz-floppy/fuzzer_stats:corpus_found : 5
generic-fuzz-virtio-serial/fuzzer_stats:corpus_found : 14
generic-fuzz-virtio-balloon/fuzzer_stats:corpus_found : 11
generic-fuzz-sb16/fuzzer_stats:corpus_found : 7
generic-fuzz-cirrus-vga/fuzzer_stats:corpus_found : 8
generic-fuzz-am53c974/fuzzer_stats:corpus_found : 11
generic-fuzz-ide-hd/fuzzer_stats:corpus_found : 14
generic-fuzz-virtio-9p-synth/fuzzer_stats:corpus_found : 13
generic-fuzz-vmxnet3/fuzzer_stats:corpus_found : 7
generic-fuzz-ahci-atapi/fuzzer_stats:corpus_found : 6
qemu-img_chain/fuzzer_stats:corpus_found : 312
virtio-blk-flags-fuzz/fuzzer_stats:corpus_found : 24
generic-fuzz-igb/fuzzer_stats:corpus_found : 9
generic-fuzz-rtl8139/fuzzer_stats:corpus_found : 7
generic-fuzz-virtio-scsi/fuzzer_stats:corpus_found : 7
generic-fuzz-intel-hda/fuzzer_stats:corpus_found : 16
generic-fuzz-virtio-9p/fuzzer_stats:corpus_found : 10
generic-fuzz-megaraid/fuzzer_stats:corpus_found : 16
generic-fuzz-pcnet/fuzzer_stats:corpus_found : 9
generic-fuzz-ide-atapi/fuzzer_stats:corpus_found : 7
generic-fuzz-pc-q35/fuzzer_stats:corpus_found : 7
generic-fuzz-ehci/fuzzer_stats:corpus_found : 15
virtio-net-socket-check-used/fuzzer_stats:corpus_found : 13
generic-fuzz-i82550/fuzzer_stats:corpus_found : 8
generic-fuzz-virtio-mouse/fuzzer_stats:corpus_found : 15
generic-fuzz-virtio-gpu/fuzzer_stats:corpus_found : 9
generic-fuzz-e1000/fuzzer_stats:corpus_found : 12
generic-fuzz-sdhci-v3/fuzzer_stats:corpus_found : 11
generic-fuzz-e1000e/fuzzer_stats:corpus_found : 6
generic-fuzz-ac97/fuzzer_stats:corpus_found : 11
generic-fuzz-parallel/fuzzer_stats:corpus_found : 14
generic-fuzz-bochs-display/fuzzer_stats:corpus_found : 12
generic-fuzz-ohci/fuzzer_stats:corpus_found : 13
generic-fuzz-pc-i440fx/fuzzer_stats:corpus_found : 8
virtio-scsi-flags-fuzz/fuzzer_stats:corpus_found : 22
generic-fuzz-virtio-vga/fuzzer_stats:corpus_found : 8
Выводы
Эксперимент показал, что нахождение нового покрытия с подключение AFL++ возможно. Однако в рамках текущей конфигурации прирост будет не слишком высоким.
Причины этого:
1) Достаточно глубокое покрытие целей фаззером LibFuzzer. Поскольку большей частью цели не слишком "сложные", они и так достаточно качественно фаззятся.
2) Медленная работа AFL++ в текущей конфигурации. Поскольку для фаззинга приходится выключать форк-сервер и обмен данными через оперативную память, то скорость фаззинга падает значительно.
3) Проблемы с оценкой прироста покрытия в LibFuzzer и AFL++. При использовании корпуса наработанного в LibFuzzer в качестве начального для AFL++, значительная часть корпуса отбрасывается как не добавляющая покрытия. Это странно, с учётом того, что LibFuzzer считал эти файлы значимыми и добавляющими покрытие. Возможно в текущей конфигурации часть исполняемого файла не инструментирована AFL++ или на оценку влияют еще какие-то неучтённые факторы.
Тем не менее, имеет смысл запускать фаззинг AFL++ для новых целей хотя бы для того, чтоб убедится в отсутствии прироста покрытия для них. Возможно имеет смысл использовать дополнительные средства инструментации, но этот вопрос требует дополнительного изучения.