1*90e502c7SAndroid Build Coastguard Worker# libsrt fuzzer 2*90e502c7SAndroid Build Coastguard Worker 3*90e502c7SAndroid Build Coastguard WorkerBy Guido Vranken <[email protected]> -- https://guidovranken.wordpress.com/ 4*90e502c7SAndroid Build Coastguard Worker 5*90e502c7SAndroid Build Coastguard WorkerThis is an advanced fuzzer for libSRTP (https://github.com/cisco/libsrtp). It implements several special techniques, described below, that are not often found in fuzzers or elsewhere. All are encouraged to transpose these ideas to their own fuzzers for the betterment of software security. 6*90e502c7SAndroid Build Coastguard Worker 7*90e502c7SAndroid Build Coastguard WorkerFeel free to contact me for business enquiries. 8*90e502c7SAndroid Build Coastguard Worker 9*90e502c7SAndroid Build Coastguard Worker## Building 10*90e502c7SAndroid Build Coastguard Worker 11*90e502c7SAndroid Build Coastguard WorkerFrom the repository's root directory: 12*90e502c7SAndroid Build Coastguard Worker 13*90e502c7SAndroid Build Coastguard Worker```sh 14*90e502c7SAndroid Build Coastguard WorkerCC=clang CXX=clang++ CXXFLAGS="-fsanitize=fuzzer-no-link,address,undefined -g -O3" CFLAGS="-fsanitize=fuzzer-no-link,address,undefined -g -O3" LDFLAGS="-fsanitize=fuzzer-no-link,address,undefined" ./configure 15*90e502c7SAndroid Build Coastguard WorkerLIBFUZZER="-fsanitize=fuzzer" make srtp-fuzzer 16*90e502c7SAndroid Build Coastguard Worker``` 17*90e502c7SAndroid Build Coastguard Worker 18*90e502c7SAndroid Build Coastguard Worker## Features 19*90e502c7SAndroid Build Coastguard Worker 20*90e502c7SAndroid Build Coastguard Worker### Portable PRNG 21*90e502c7SAndroid Build Coastguard Worker 22*90e502c7SAndroid Build Coastguard Worker```mt19937.c``` exports the C++11 Mersenne Twister implementaton. Hence, a modern C++ compiler is required to compile this file. 23*90e502c7SAndroid Build Coastguard Worker 24*90e502c7SAndroid Build Coastguard WorkerThis approach has the following advantages: 25*90e502c7SAndroid Build Coastguard Worker 26*90e502c7SAndroid Build Coastguard Worker- rand() is fickle -- its behavior eg. the sequence of numbers that it generates for a given seed, may differ across systems and libc's. 27*90e502c7SAndroid Build Coastguard Worker- C++11 mt19937 is portable, meaning that its behavior will be consistent across platforms. This is important to keep the fuzzing corpus portable. 28*90e502c7SAndroid Build Coastguard Worker- No need to implement a portable PRNG ourselves, or risk license incompatability by importing it from other projects. 29*90e502c7SAndroid Build Coastguard Worker 30*90e502c7SAndroid Build Coastguard Worker### Size 0 allocations 31*90e502c7SAndroid Build Coastguard Worker 32*90e502c7SAndroid Build Coastguard WorkerTo test whether allocations of size 0 eg. ```malloc(0)``` are ever dereferenced and written to, the custom allocater will return an intentionally invalid pointer pointer address for these requests. 33*90e502c7SAndroid Build Coastguard Worker 34*90e502c7SAndroid Build Coastguard WorkerFor more information, see the comments in ```fuzz_alloc()```. 35*90e502c7SAndroid Build Coastguard Worker 36*90e502c7SAndroid Build Coastguard Worker### Random allocation failures 37*90e502c7SAndroid Build Coastguard Worker 38*90e502c7SAndroid Build Coastguard WorkerThe custom allocator will periodically return ```NULL``` for heap requests. This tests the library's resilience and correct operation in the event of global memory shortages. 39*90e502c7SAndroid Build Coastguard Worker 40*90e502c7SAndroid Build Coastguard WorkerThe interval of ```NULL``` return values is deterministic as it relies on the PRNG, so for a given fuzzer input (that encodes the PRNG seed as well), behavior of that input with regards to allocator behaviour is consistent, allowing for reliable reproduction of bugs. 41*90e502c7SAndroid Build Coastguard Worker 42*90e502c7SAndroid Build Coastguard Worker### Detecting inadequate pointer arithmetic 43*90e502c7SAndroid Build Coastguard Worker 44*90e502c7SAndroid Build Coastguard WorkerThis feature is only available on 32 bit builds. 45*90e502c7SAndroid Build Coastguard Worker 46*90e502c7SAndroid Build Coastguard WorkerUnless the ```--no_mmap``` flag is given, the fuzzer will use a special allocation technique for some of the allocation requests. It will use ```mmap()``` to reserve memory at the extremities of the virtual address space -- sometimes at 0x00010000 and sometimes at 0xFFFF0000. This approach can assist in detecting invalid or inadequate pointer arithmetic. For example, consider the following code: 47*90e502c7SAndroid Build Coastguard Worker 48*90e502c7SAndroid Build Coastguard Worker```c 49*90e502c7SAndroid Build Coastguard Workerif ( start + n < end ) { 50*90e502c7SAndroid Build Coastguard Worker memset(start, 0, n); 51*90e502c7SAndroid Build Coastguard Worker} 52*90e502c7SAndroid Build Coastguard Worker``` 53*90e502c7SAndroid Build Coastguard Worker 54*90e502c7SAndroid Build Coastguard Workerwhere ```start``` and ```end``` demarcate a memory region, and ```n``` is some positive integer. 55*90e502c7SAndroid Build Coastguard WorkerIf ```n``` is a sufficiently large value, a pointer addition overflow will occur, leading to a page fault. By routinely placing allocations at the high virtual address ```0xFFFF0000```, the chances of detecting this bug are increased. So let's say ```start``` was previously allocated at ```0xFFFF0000```, and ```end``` is ```0xFFFF1000```, and ```n``` is 0xFFFFF. Then the expression effectively becomes: 56*90e502c7SAndroid Build Coastguard Worker 57*90e502c7SAndroid Build Coastguard Worker```c 58*90e502c7SAndroid Build Coastguard Workerif ( 0xFFFF0000 + 0x000FFFFF < 0xFFFF1000 ) { 59*90e502c7SAndroid Build Coastguard Worker memset(0xFFFF0000, 0, 0x000FFFF); 60*90e502c7SAndroid Build Coastguard Worker} 61*90e502c7SAndroid Build Coastguard Worker``` 62*90e502c7SAndroid Build Coastguard Worker 63*90e502c7SAndroid Build Coastguard WorkerThe addition ```0xFFFF0000 + 0x000FFFFF``` overflows so the result is ```0x000EFFFF```. Hence: 64*90e502c7SAndroid Build Coastguard Worker 65*90e502c7SAndroid Build Coastguard Worker```c 66*90e502c7SAndroid Build Coastguard Workerif ( 0x000EFFFF < 0xFFFF1000 ) { // Expression resolves as true ! 67*90e502c7SAndroid Build Coastguard Worker``` 68*90e502c7SAndroid Build Coastguard Worker 69*90e502c7SAndroid Build Coastguard WorkerThe subsequent ```memset``` is executed contrary to the programmer's intentions, and a segmentation fault will occur. 70*90e502c7SAndroid Build Coastguard Worker 71*90e502c7SAndroid Build Coastguard WorkerWhile this is a corner case, it can not be ruled out that it might occur in a production environment. What's more, the analyst examining the crash can reason about how the value of ```n``` comes about in the first place, and concoct a crafted input that leads to a very high ```n``` value, making the "exploit" succeed even with average virtual addresses. 72*90e502c7SAndroid Build Coastguard Worker 73*90e502c7SAndroid Build Coastguard WorkerAside from using ```mmap``` to allocate at address ```0xFFFF0000```, the fuzzer will also place allocations at the low virtual address ```0x00010000``` to detect invalid pointer arithmetic involving subtraction: 74*90e502c7SAndroid Build Coastguard Worker 75*90e502c7SAndroid Build Coastguard Worker```c 76*90e502c7SAndroid Build Coastguard Workerif ( end - n > start ) { 77*90e502c7SAndroid Build Coastguard Worker``` 78*90e502c7SAndroid Build Coastguard Worker 79*90e502c7SAndroid Build Coastguard Worker### Output memory testing 80*90e502c7SAndroid Build Coastguard Worker 81*90e502c7SAndroid Build Coastguard Worker```testmem.c``` exports ```fuzz_testmem```. All this function does is copy the input buffer to a newly allocated heap region, and then free that heap region. If AddressSanitizer is enabled, this ensures that the input buffer to ```fuzz_testmem``` is a legal memory region. 82*90e502c7SAndroid Build Coastguard WorkerIf MemorySanitizer is enabled, then ``fuzz_testmem``` calls ```fuzz_testmem_msan````. The latter function writes the data at hand to ```/dev/null```. This is an nice trick to make MemorySanitizer evaluate this data, and crash if it contains uninitialized bytes. 83*90e502c7SAndroid Build Coastguard WorkerThis function has been implemented in a separate file for a reason: from the perspective of an optimizing compiler, this is a meaningless operation, and as such it might be optimized away. Hence, this file must be compiled without optimizations (```-O0``` flag). 84*90e502c7SAndroid Build Coastguard Worker 85*90e502c7SAndroid Build Coastguard Worker## Contributing 86*90e502c7SAndroid Build Coastguard Worker 87*90e502c7SAndroid Build Coastguard WorkerWhen extending the current fuzzer, use variable types whose width is consistent across systems where possible. This is necessary to retain corpus portability. For example, use ```uint64_t``` rather than ```unsigned long```. 88*90e502c7SAndroid Build Coastguard Worker 89