An open API service indexing awesome lists of open source software.

https://github.com/googleprojectzero/drsancov

DynamoRIO plugin to get ASAN and SanitizerCoverage compatible output for closed-source executables
https://github.com/googleprojectzero/drsancov

Last synced: 5 months ago
JSON representation

DynamoRIO plugin to get ASAN and SanitizerCoverage compatible output for closed-source executables

Awesome Lists containing this project

README

          

# DrSancov

DrSancov is a small DBI module based on [DynamoRIO](https://github.com/DynamoRIO/dynamorio), which aims to combine the basic functionality of [AddressSanitizer](https://clang.llvm.org/docs/AddressSanitizer.html) and [SanitizerCoverage](https://clang.llvm.org/docs/SanitizerCoverage.html), while being similar to [DrCov](http://dynamorio.org/docs/page_drcov.html) (hence the name). In other words, it mimics the behavior of the two compiler instrumentations, by printing out ASAN-like reports upon SIGSEGV and similar program crashes, and saving code coverage information to `.sancov` files compatible with those generated by SanitizerCoverage. The purpose of the tool is to make it easier to test closed-source software using existing fuzzing pipelines which expect the target to be compiled with ASAN/SanitizerCoverage. It works with x86 and x86-64 applications.

Please note that the project does not improve memory error detection; it only produces ASAN compatible reports for conditions that would result in a hard crash anyway. For better sanitization of heap memory accesses in compiled binaries, check e.g. AFL's [libdislocator](https://github.com/google/AFL/tree/master/libdislocator).

The code coverage information is collected with a basic block granularity.

## Building

A Makefile for GNU/Linux is provided, and the end result is a `libdrsancov.so` library. The Makefile assumes that DynamoRIO resides in a `../dynamorio` directory relative to itself, for example:

```
.
|-- code
| |-- common.cc
| |-- common.h
| |-- drsancov.cc
| |-- Makefile
| |-- tokenizer.cc
| `-- tokenizer.h
|-- dynamorio
| |-- ACKNOWLEDGEMENTS
| |-- bin32
| | |-- drconfig
| | |-- drconfig.debug
[...]
```

Then, compilation should run smoothly as follows:

```
$ cd code
$ make
clang++ -c -o drsancov.o drsancov.cc -O2 -fPIC -I../dynamorio/include -I../dynamorio/ext/include -DX86_64 -DLINUX -fno-stack-protector
clang++ -c -o common.o common.cc -O2 -fPIC -I../dynamorio/include -I../dynamorio/ext/include -DX86_64 -DLINUX -fno-stack-protector
clang++ -c -o tokenizer.o tokenizer.cc -O2 -fPIC -I../dynamorio/include -I../dynamorio/ext/include -DX86_64 -DLINUX -fno-stack-protector
clang++ -shared -o libdrsancov.so drsancov.o common.o tokenizer.o -Wl,-hash-style=both ../dynamorio/lib64/debug/libdynamorio.so ../dynamorio/ext/lib64/debug/libdrsyms.so ../dynamorio/ext/lib64/debug/libdrmgr.so
$
```

## Usage

In order to use DrSancov, prepend the usual target command line with `drrun -c libdrsancov.so -- `, which will run the program under our instrumentation. Let's consider the following program:

```
$ cat -n tests/test.cc
1 #include
2 #include
3
4 int main(int argc, char **argv) {
5 if (argc >= 2 && argv[1][0] == 'F' && argv[1][1] == 'U' && argv[1][2] == 'Z' && argv[1][3] == 'Z') {
6 int *x = (int *)0x12345678;
7 *x = 0x41414141;
8 }
9
10 return 0;
11 }
$ g++ tests/test.cc -o tests/test
$
```

For argument "FUZZ", we'd typically see a standard "Segmentation fault" message:

```
$ tests/test FUZZ
Segmentation fault
$
```

With DrSancov enabled, we get a familiar report:

```
$ dynamorio/bin64/drrun -c code/libdrsancov.so -- tests/test FUZZ
ASAN:SIGSEGV
=================================================================
==7548==ERROR: AddressSanitizer: SEGV on unknown address 0x12345678 (pc 0x7f114701a196 sp 0x7ffe0837a830 bp 0x7ffe0837a830 T0)
#0 0x7f114701a196 in test+1196

==7548==CONTEXT
rax=0000000012345678 rbx=0000000000000000 rcx=0000000000000080 rdx=00007ffe0837a930
rsi=00007ffe0837a918 rdi=0000000000000002 rsp=00007ffe0837a830 rbp=00007ffe0837a830
r8=00007f1149d8ad80 r9=0000000000000000 r10=00007f114701f010 r11=0000000000000000
r12=00007f114701a040 r13=00007ffe0837a910 r14=0000000000000000 r15=0000000000000000
rip=00007f1137b63a18 rflags=0000000000010246
Accessed address: 0x12345678
Faulting code:
0x00007f1137b63a18 mov dword ptr [rax], 0x41414141

==7548==ABORTING
$
```

In addition to the somewhat standarized ASAN header, there is also extra information printed out in the "context" section.

Similarly to ASAN, DrSancov can be controlled with the `ASAN_OPTIONS` environment variable. The currently supported switches are `coverage`, `exitcode`, `log_path` and `coverage_dir`. Let's try to obtain some code coverage for two inputs:

```
$ ASAN_OPTIONS=coverage=1 dynamorio/bin64/drrun -c code/libdrsancov.so -- tests/test FU
DrSanitizerCoverage: ./test.20345.sancov: 25 PCs written
$ ASAN_OPTIONS=coverage=1 dynamorio/bin64/drrun -c code/libdrsancov.so -- tests/test FUZ
DrSanitizerCoverage: ./test.20361.sancov: 26 PCs written
$ xxd -e -g8 -c8 test.20345.sancov | awk '{print $2}' >cov1
$ xxd -e -g8 -c8 test.20361.sancov | awk '{print $2}' >cov2
$ diff cov1 cov2
19a20
> 0000000000001174
$
```

Here, we can see that the difference in coverage between "FU" and "FUZ" is a single basic block at offset 0x1174, which turns out to be the verification of the final letter of the parameter:

```
$ objdump -d tests/test
[...]
1174: 48 8b 45 e0 mov -0x20(%rbp),%rax
1178: 48 83 c0 08 add $0x8,%rax
117c: 48 8b 00 mov (%rax),%rax
117f: 48 83 c0 03 add $0x3,%rax
1183: 0f b6 00 movzbl (%rax),%eax
1186: 3c 5a cmp $0x5a,%al
1188: 75 12 jne 119c
[...]
```

This demonstrates basic output compatibility between the DBI and the Sanitizer-family instrumentations.