Libfuzzer
libfuzzer¶
LLVM version of AFL
Example for Damn Vulnerable C Program¶
Compiling the Program:
>>> clang -fsanitize=fuzzer,address,undefined -g imgRead_libfuzzer.c -o imgRead_libfuzzer
imgRead_libfuzzer.c:86:1: warning: non-void function does not return a value in all control paths [-Wreturn-type]
}
^
1 warning generated.
Run the program:
>>> ./imgRead_libfuzzer
INFO: Seed: 2569578062
INFO: Loaded 1 modules (86 inline 8-bit counters): 86 [0x56004f453148, 0x56004f45319e),
INFO: Loaded 1 PC tables (86 PCs): 86 [0x56004f4531a0,0x56004f453700),
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes
INFO: A corpus is not provided, starting from an empty corpus
#2 INITED cov: 2 ft: 2 corp: 1/1b exec/s: 0 rss: 30Mb
=================================================================
==1805179==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000819e at pc 0x56004f3db28c bp 0x7ffd712987f0 sp 0x7ffd71297fa0
READ of size 10 at 0x60200000819e thread T0
#0 0x56004f3db28b in __asan_memcpy (/tmp/Damn_Vulnerable_C_Program/imgRead_libfuzzer+0x10f28b)
#1 0x56004f4127a5 in LLVMFuzzerTestOneInput /tmp/Damn_Vulnerable_C_Program/imgRead_libfuzzer.c:35:3
#2 0x56004f315f0f in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/tmp/Damn_Vulnerable_C_Program/imgRead_libfuzzer+0x49f0f)
#3 0x56004f317ba0 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) (/tmp/Damn_Vulnerable_C_Program/imgRead_libfuzzer+0x4bba0)
#4 0x56004f3184e9 in fuzzer::Fuzzer::MutateAndTestOne() (/tmp/Damn_Vulnerable_C_Program/imgRead_libfuzzer+0x4c4e9)
#5 0x56004f319e37 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) (/tmp/Damn_Vulnerable_C_Program/imgRead_libfuzzer+0x4de37)
#6 0x56004f30182d in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/tmp/Damn_Vulnerable_C_Program/imgRead_libfuzzer+0x3582d)
#7 0x56004f2f12f3 in main (/tmp/Damn_Vulnerable_C_Program/imgRead_libfuzzer+0x252f3)
#8 0x7facc26bf151 in __libc_start_main (/usr/lib/libc.so.6+0x28151)
#9 0x56004f2f134d in _start (/tmp/Damn_Vulnerable_C_Program/imgRead_libfuzzer+0x2534d)
0x60200000819e is located 0 bytes to the right of 14-byte region [0x602000008190,0x60200000819e)
allocated by thread T0 here:
#0 0x56004f3dc349 in malloc (/tmp/Damn_Vulnerable_C_Program/imgRead_libfuzzer+0x110349)
#1 0x7facc2a98539 in operator new(unsigned long) /build/gcc/src/gcc/libstdc++-v3/libsupc++/new_op.cc:50:22
#2 0x56004f317ba0 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) (/tmp/Damn_Vulnerable_C_Program/imgRead_libfuzzer+0x4bba0)
#3 0x56004f3184e9 in fuzzer::Fuzzer::MutateAndTestOne() (/tmp/Damn_Vulnerable_C_Program/imgRead_libfuzzer+0x4c4e9)
#4 0x56004f319e37 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) (/tmp/Damn_Vulnerable_C_Program/imgRead_libfuzzer+0x4de37)
#5 0x56004f30182d in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/tmp/Damn_Vulnerable_C_Program/imgRead_libfuzzer+0x3582d)
#6 0x56004f2f12f3 in main (/tmp/Damn_Vulnerable_C_Program/imgRead_libfuzzer+0x252f3)
#7 0x7facc26bf151 in __libc_start_main (/usr/lib/libc.so.6+0x28151)
SUMMARY: AddressSanitizer: heap-buffer-overflow (/tmp/Damn_Vulnerable_C_Program/imgRead_libfuzzer+0x10f28b) in __asan_memcpy
Shadow bytes around the buggy address:
0x0c047fff8fe0: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fd
0x0c047fff8ff0: fa fa fd fd fa fa fd fd fa fa fd fa fa fa fd fa
0x0c047fff9000: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa
0x0c047fff9010: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa
0x0c047fff9020: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa
=>0x0c047fff9030: fa fa 00[06]fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9060: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9070: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==1805179==ABORTING
MS: 4 InsertByte-CopyPart-ChangeBit-CrossOver-; base unit: adc83b19e793491b1c6ea0fd8b46cd9f32e592fc
0xa,0x58,0x83,0x0,0x0,0xa,0xa,0x0,0xa,0x0,0xa,0x0,0x0,0x0,
\x0aX\x83\x00\x00\x0a\x0a\x00\x0a\x00\x0a\x00\x00\x00
artifact_prefix='./'; Test unit written to ./crash-5b3e359967a560d8422b9557a5cbd4d6f2cdd3ff
Base64: CliDAAAKCgAKAAoAAAA=
Tutorial¶
Example Testfile:
#include <lib/parse_image.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size){
free(ParseImage(data,size));
return 0;
}
Example Compile:
#Add the AddressSanitizer, ThreadSanitizer, MemorySanitizer, and UndefinedBehaviourSanitizer
clang++ -std=c++11 -fsanitize=address,thread,memory,undefined,fuzzer fuzzer.cc library/*.cc
./fuzzer corpusdir