Комбинируйте размытие с отслеживанием пути выполнения

#c #c #clang #llvm #fuzzing

Вопрос:

Я хочу отследить пути выполнения программы для нескольких входов. Для генерации входных данных я в настоящее время использую фаззинг с управлением охватом-сначала я попробовал AFL, а теперь использую Libfuzzer. Чтобы записать пути выполнения, я посмотрел на XRay и SanitizerCoverage, которые, насколько я понял, используют инструментарий LLVM; последний используется внутри Libfuzzer для своих показателей покрытия.

Если я использую XRay с Libfuzzer, я получаю сообщения об ошибках из-за нескольких определений функций:

 #include <xray/xray_log_interface.h>

extern "C" {
    int LLVMFuzzerRunDriver(int *argc, char ***argv, int (*UserCb)(const uint8_t *Data, size_t Size));
};

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
    return 0;
}

int main(int argc, char** argv) {
    return LLVMFuzzerRunDriver(amp;argc, amp;argv, amp;LLVMFuzzerTestOneInput);
}
 
 clang  -13 -o test test.cpp -fxray-instrument -fxray-instruction-threshold=1 -fsanitize=fuzzer-no-link -L /usr/lib/clang/13.0.0/lib/linux/ -l clang_rt.fuzzer_no_main-x86_64
 

Если я использую Libfuzzer с обратным вызовом SanitizerCoverage:

 #include <cstdlib>
#include <inttypes.h>
#include <sanitizer/coverage_interface.h>

extern "C" void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
  if (!*guard) return;
  return;
}

extern "C" {
    int LLVMFuzzerRunDriver(int *argc, char ***argv, int (*UserCb)(const uint8_t *Data, size_t Size));
};

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
    return 0;
}

int main(int argc, char** argv) {
    return LLVMFuzzerRunDriver(amp;argc, amp;argv, amp;LLVMFuzzerTestOneInput);
}
 
 $ clang  -13 -o test2 test2.cpp -fsanitize=fuzzer-no-link -fsanitize-coverage=trace-pc-guard -L /usr/lib/clang/13.0.0/lib/linux/ -l clang_rt.fuzzer_no_main-x86_64

/usr/bin/ld: /usr/lib/clang/13.0.0/lib/linux//libclang_rt.fuzzer_no_main-x86_64.a(fuzzer_no_main.o): in function `__sanitizer_cov_trace_pc_guard':
(.text.__sanitizer_cov_trace_pc_guard 0x0): multiple definition of `__sanitizer_cov_trace_pc_guard'; /tmp/test2-047590.o:test2.cpp:(.text 0x0): first defined here
 

Можно ли совместить готовое размытие (для создания «интересных» входных данных) и трассировку пути выполнения, или мне придется прибегнуть к чему-то более сложному, например, написать свой собственный пропуск LLVM.

Комментарии:

1. Я не уверен, что понимаю вашу цель. С помощью AFL вы можете проверить все края, на которые он попадает, с помощью afl-showmap и использовать afl-cov для получения результата gcov. это то, чего ты хочешь?

2. Насколько я понял результаты покрытия afl, я не получаю отдельных следов для входных данных, т. Е. Я знаю, что функции foo (), bar() и baz() покрываются во время выполнения, но я не знаю, в каком порядке функции были выполнены, с помощью каких входных данных

3. ах, справедливо — это звучит дорого с точки зрения производительности. Возможно, вам захочется немного ознакомиться с AFLGo, который вычисляет функциональное расстояние до цели перед кампанией по размыванию.