Skip to content

Commit

Permalink
Initial import
Browse files Browse the repository at this point in the history
  • Loading branch information
rpaleari committed Feb 2, 2015
1 parent f157749 commit 3da1854
Show file tree
Hide file tree
Showing 35 changed files with 1,950 additions and 0 deletions.
14 changes: 14 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
*pyc
tracer/pin/bbtrace.pb.*
tracer/pin/obj-intel64
tracer/pin/pin.log
tracer/common/bbtrace.pb.*
tracer/common/*.o
tracer/common/libtracer.a
tracer/bts/*.o
tracer/bts/bts_trace
tracer/bts/bts_trace
tests/bisect
tests/quicksort
tests/test?
viewer/bbtrace_pb2.py
72 changes: 72 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
FuzzTrace is a "general-purpose" tracing tool for closed-source applications,
aimed at generating a concise execution trace that can be used to support the
fuzz-testing activity or other analyses.

At the time of writing, we provide two tracing back-ends, based on Intel BTS
and PIN respectively. In any case, the execution trace is serialized to a
[protobuf](https://code.google.com/p/protobuf/) object, that can then be
processed off-line. Available back-ends are briefly described in the next
paragraphs, together with some usage examples.

On a Debian/Ubuntu system, use the following commands to install the required
dependencies (these are common to all the back-ends available):

roby@gimli:~$ sudo apt-get install protobuf-compiler python-protobuf libprotobuf-dev

## Back-ends ##

### BTS-based execution tracers ###

The BTS back-end is an efficient tracer that leverages Intel "Branch Trace
Store" (BTS) technology. The source code for this back-end is located under
`tracer/bts`. To compile this back-end module enter directory `tracer/bin` and
run `make`.

Hopefully, everything will go fine. You should now be able to trace your target
application using the `bts_trace` binary:

roby@gimli:~/projects/fuzztrace/tracer/bts$ ./bts_trace -f /dev/shm/trace.bin -- /bin/ls -la >/dev/null
[*] Got 108684 events (4967 CFG edges)
[*] Serializing to /dev/shm/trace.bin

### PIN-based execution tracers ###

The PIN back-end is a
[PIN](https://software.intel.com/en-us/articles/pin-a-dynamic-binary-instrumentation-tool)
extension to monitor the execution of a binary application and record its
"execution trace". FuzzTrace/PIN lives in directory `fuzztrace/tracer/pin`. To
compile the PIN module, set the `PIN_ROOT` environment variable and launch
`make` from the `tracer/pin` directory, e.g.:

roby@gimli:~/apps/pin$ export PIN_ROOT=$(pwd)
roby@gimli:~/apps/pin$ cd ~/projects/fuzztrace/tracer-pin
roby@gimli:~/projects/fuzztrace/tracer/pin$ make


You should be able to trace your target program using the `pintrace` PIN tool:

roby@gimli:~/projects/fuzztrace/tracer/pin$ ${PIN_ROOT}/pin.sh -t obj-intel64/pintrace.so -o /dev/shm/trace.bin -- /bin/ls

## Trace viewer ##

The `viewer` directory provides a basic trace viewer, which parses a saved
execution traces and displays recorded branches.

Before using the viewer, compile the `bbtrace.proto` file:

roby@gimli:~/projects/fuzztrace/viewer$ protoc --python_out=. bbtrace.proto

After that, usage is quite straightforward:

roby@gimli:~/projects/fuzztrace/viewer$ python trace.py /dev/shm/trace.bin
#### Trace '/dev/shm/trace.bin' ####
[/dev/shm/trace.bin] cmd: test, data: 0 bytes, time: 2015-01-29 22:47:52, hash: 3c31f, edges(s): 708, exception(s): 0

- CFG edges
[00402168 -> 00402178] 1 hit
[00402178 -> 0040217d] 1 hit
[0040217d -> 00412513] 1 hit
[00402190 -> 004124e0] 1 hit
...


20 changes: 20 additions & 0 deletions tests/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
TESTS_ASM := $(basename $(wildcard *.S))
TESTS_C := $(basename $(wildcard *.c))
TESTS = $(TESTS_ASM) $(TESTS_C)
TRACES = $(TESTS:=.trace)

tests: $(TESTS)
all: tests
clean:
-rm $(TESTS)

traces: $(TRACES)

$(TRACES): %.trace: %
../tracer/bts/bts_trace -f /dev/shm/$@ ./$^

$(TESTS_ASM): %: %.S
$(CC) -nostdlib -o $@ $^

$(TESTS_C): %: %.c
$(CC) -o $@ $^
92 changes: 92 additions & 0 deletions tests/bisect.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

#define ARRAY_SIZE 1024

static int bisect(int v[], int size, int key) {
int start, end, middle, pos;

start = 0;
end = size-1;
pos = -1;
while (start <= end) {
middle = (end+start)/2;

#if 0
printf("Searching [%d - %d] for key %d, middle %d\n",
start, end, key, middle);
#endif

if (v[middle] > key) {
end = middle-1;
} else if (v[middle] < key) {
start = middle+1;
} else {
pos = middle;
break;
}
}

return pos;
}

static void dump_array(int v[], int size) {
const int blocksize = 32;
int i, blockno;

assert((size % blocksize) == 0);

for (blockno=0; blockno<size/blocksize; blockno++) {
printf("[pos] ");
for (i=0; i<blocksize; i++) {
printf("%4d ", i+blocksize*blockno);
}
putchar('\n');

printf("[elem] ");
for (i=0; i<blocksize; i++) {
printf("%4d ", v[i+blocksize*blockno]);
}
putchar('\n');
}

putchar('\n');
}

static int compare(const void *a, const void *b) {
return *(int*) a - *(int*) b;
}

int main(int argc, char **argv) {
// int array[] = {5, 55, 12, 0, 42, 14, 2, 1, 59, 14, 4, 11, 18, 19, 50, 0};
int array[ARRAY_SIZE];
int n = sizeof(array) / sizeof(int);
int elem, i;

if (argc > 1) {
elem = atoi(argv[1]);
} else {
elem = 42;
printf("No element specified, searching for %d\n", elem);
}

srandom(time(NULL));
for (i=0; i<n; i++) {
array[i] = random() % 100;
}
array[random() % n] = elem;

printf("Initial array:\n");
dump_array(array, n);

qsort(array, n, sizeof(int), compare);

printf("Sorted array:\n");
dump_array(array, n);

printf("Search for element '%d' returned: %d\n",
elem, bisect(array, n, elem));

return 0;
}
67 changes: 67 additions & 0 deletions tests/quicksort.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include <stdlib.h>
#include <stdio.h>

#define ARRAY_SIZE 1024

static void swap(void *x, void *y, size_t l) {
char *a = x, *b = y, c;
while(l--) {
c = *a;
*a++ = *b;
*b++ = c;
}
}

int count = 0;
static void sort(char *array, size_t size, int (*cmp)(void*,void*), int begin, int end) {
count++;
if (end > begin) {
void *pivot = array + begin;
int l = begin + size;
int r = end;
while(l < r) {
if (cmp(array+l,pivot) <= 0) {
l += size;
} else if ( cmp(array+r, pivot) > 0 ) {
r -= size;
} else if ( l < r ) {
swap(array+l, array+r, size);
}
}
l -= size;
swap(array+begin, array+l, size);
sort(array, size, cmp, begin, l);
sort(array, size, cmp, r, end);
}
}

void quicksort(void *array, size_t nitems, size_t size, int (*cmp)(void*,void*)) {
sort(array, size, cmp, 0, nitems*size);
}

typedef int type;

int type_cmp(void *a, void *b){ return (*(type*)a)-(*(type*)b); }

int main(void) {
int array[ARRAY_SIZE];
int len=sizeof(array)/sizeof(type);
char *sep="";
int i;

srandom(time(NULL));
for (i=0; i<len; i++) {
array[i] = random() % 100;
}

quicksort(array, len, sizeof(type), type_cmp);

printf("sorted_num_list={");
for(i=0; i<len; i++){
printf("%s%d", sep, array[i]);
sep=", ";
}
printf("};\n");
printf("count: %d\n", count);
return 0;
}
21 changes: 21 additions & 0 deletions tests/test1.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.global _start
.text

foo:
inc %eax
ret

_start:
xor %eax, %eax
jmp label1

label1:
call foo
nop
jmp exit
nop

exit:
mov $0x3c, %rax
mov $0x00, %rdi
syscall
21 changes: 21 additions & 0 deletions tests/test2.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.global _start
.text

_start:
xor %eax, %eax
xor %ecx, %ecx
mov $0x10, %eax

loop1:
cmp $0x03, %eax
jne tail
inc %ecx
inc %ecx
tail:
dec %eax
jnz loop1

exit:
mov $0x3c, %rax
mov $0x00, %rdi
syscall
26 changes: 26 additions & 0 deletions tests/test3.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
.globl _start

_test:
mov $1, %rdi
ret

_start:
jmp _do_start // only required not to loose the first instruction

_do_start:
movq $2, %rax
cmpq $1, %rax
movq $0, %rdi
jle .L2
nop
nop
nop
call _test
nop
nop
nop
.L2:
mov $0x3c, %rax
syscall
// useless, but useful to terminate cleanly our graph :-)
ret
20 changes: 20 additions & 0 deletions tests/test4.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/* Test for fallback branches */
.global _start
.text

_start:
jmp tgt // just for the sake of getting tgt as a block

tgt:
mov $0x0, %rax
test %rax,%rax
jz exit
xor %rax,%rax
xor %rax,%rax
xor %rax,%rax
exit:
mov $0x3c, %rax
mov $0x00, %rdi
syscall
// Useless ret to cleanly terminate bb after syscall
ret
22 changes: 22 additions & 0 deletions tracer/bts/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.PHONY: all clean

CFLAGS=-Wall -std=c++11 -I..
LDFLAGS=-L../common/

libtracer=../common/libtracer.a

all: bts_trace
clean:
-rm $(objs) bts_trace

objs = bts_trace.o perf.o monitor.o

bts_trace: $(objs) $(libtracer)
$(CXX) $(CFLAGS) -o $@ $(objs) $(LDFLAGS) -lprotobuf -ltracer

.PHONY: $(libtracer)
$(libtracer):
@$(MAKE) -C $(dir $(libtracer))

%.o: %.cc ../common/logging.h
$(CXX) $(CFLAGS) -c -o $@ $<
Loading

0 comments on commit 3da1854

Please sign in to comment.