Futag
Futag copied to clipboard
Генерируются слишком сложные фаззинг обертки
Тестируемый проект: https://github.com/mz-automation/libiec61850
Конфигурация запуска Futag'a стандартная:
build_test = Builder(
FUTAG_PATH,
lib_path,
clean=True,
)
build_test.auto_build()
build_test.analyze()
generator = Generator(
FUTAG_PATH,
lib_path,
)
generator.gen_targets(
anonymous=False,
max_wrappers= 10
)
generator.compile_targets(
4,
)
По итогу получил более 5 тысяч фаззинг целей, но их реализация достаточно запутанная и иногда даже сломанная.
Для примера сгенерированная фаззинг цель MmsValue_decodeMmsData:
int LLVMFuzzerTestOneInput(uint8_t * Fuzz_Data, size_t Fuzz_Size){
if (Fuzz_Size < 1 * sizeof(char) + sizeof(int) + sizeof(int)) return 0;
size_t dyn_cstring_buffer = (size_t) (Fuzz_Size + 1*sizeof(char) - (1 * sizeof(char) + sizeof(int) + sizeof(int) ));
//generate random array of dynamic string sizes
size_t dyn_cstring_size[1];
dyn_cstring_size[0] = dyn_cstring_buffer;
//end of generation random array of dynamic string sizes
uint8_t * futag_pos = Fuzz_Data;
//GEN_CSTRING1
unsigned char * str_buffer = (unsigned char *) malloc((dyn_cstring_size[0] + 1)* sizeof(char));
memset(str_buffer, 0, dyn_cstring_size[0] + 1);
memcpy(str_buffer, futag_pos, dyn_cstring_size[0]);
futag_pos += dyn_cstring_size[0];
//GEN_SIZE
int sz_bufPos = (int) dyn_cstring_size[0];
//GEN_BUILTIN
int b_bufferLength;
memcpy(&b_bufferLength, futag_pos, sizeof(int));
futag_pos += sizeof(int);
//GEN_BUILTIN
int b__endBufPos;
memcpy(&b__endBufPos, futag_pos, sizeof(int));
futag_pos += sizeof(int);
//GEN_POINTER
int * p_b__endBufPos = & b__endBufPos;
//FUNCTION_CALL
MmsValue_decodeMmsData(str_buffer ,sz_bufPos ,b_bufferLength ,p_b__endBufPos );
//FREE
if (str_buffer) {
free(str_buffer);
str_buffer = NULL;
}
return 0;
}
При первом же запуске на любых данных получаю падение т.е. оно вызвано ошибкой реализации харнесса. Если взять готовую реализацию на эту же функцию из репозитория:
int LLVMFuzzerTestOneInput(const char *data, size_t size) {
int out;
MmsValue* value = NULL;
value = MmsValue_decodeMmsData(data, 0, size, &out);
if (value != NULL) {
MmsValue_delete(value);
}
return 0;
}
Данная реализация заметно более читаемая и не вызывает ложные крэши.
Как возможно решить данную проблему?
Тестируемый проект: https://github.com/mz-automation/libiec61850
Конфигурация запуска Futag'a стандартная:
build_test = Builder( FUTAG_PATH, lib_path, clean=True, ) build_test.auto_build() build_test.analyze() generator = Generator( FUTAG_PATH, lib_path, ) generator.gen_targets( anonymous=False, max_wrappers= 10 ) generator.compile_targets( 4, )По итогу получил более 5 тысяч фаззинг целей, но их реализация достаточно запутанная и иногда даже сломанная.
Для примера сгенерированная фаззинг цель MmsValue_decodeMmsData:
int LLVMFuzzerTestOneInput(uint8_t * Fuzz_Data, size_t Fuzz_Size){ if (Fuzz_Size < 1 * sizeof(char) + sizeof(int) + sizeof(int)) return 0; size_t dyn_cstring_buffer = (size_t) (Fuzz_Size + 1*sizeof(char) - (1 * sizeof(char) + sizeof(int) + sizeof(int) )); //generate random array of dynamic string sizes size_t dyn_cstring_size[1]; dyn_cstring_size[0] = dyn_cstring_buffer; //end of generation random array of dynamic string sizes uint8_t * futag_pos = Fuzz_Data; //GEN_CSTRING1 unsigned char * str_buffer = (unsigned char *) malloc((dyn_cstring_size[0] + 1)* sizeof(char)); memset(str_buffer, 0, dyn_cstring_size[0] + 1); memcpy(str_buffer, futag_pos, dyn_cstring_size[0]); futag_pos += dyn_cstring_size[0]; //GEN_SIZE int sz_bufPos = (int) dyn_cstring_size[0]; //GEN_BUILTIN int b_bufferLength; memcpy(&b_bufferLength, futag_pos, sizeof(int)); futag_pos += sizeof(int); //GEN_BUILTIN int b__endBufPos; memcpy(&b__endBufPos, futag_pos, sizeof(int)); futag_pos += sizeof(int); //GEN_POINTER int * p_b__endBufPos = & b__endBufPos; //FUNCTION_CALL MmsValue_decodeMmsData(str_buffer ,sz_bufPos ,b_bufferLength ,p_b__endBufPos ); //FREE if (str_buffer) { free(str_buffer); str_buffer = NULL; } return 0; }При первом же запуске на любых данных получаю падение т.е. оно вызвано ошибкой реализации харнесса. Если взять готовую реализацию на эту же функцию из репозитория:
int LLVMFuzzerTestOneInput(const char *data, size_t size) { int out; MmsValue* value = NULL; value = MmsValue_decodeMmsData(data, 0, size, &out); if (value != NULL) { MmsValue_delete(value); } return 0; }Данная реализация заметно более читаемая и не вызывает ложные крэши.
Как возможно решить данную проблему?
Это еще несложная обертка ) В данном случае после аргумента buffer типа строки идет аргумент bufPos типа целого числа Futag постарается угадать, что это комбинация строки и ее длины. Затем разделит входный буфер для передачи всем аргументам.