Skip to content

Commit

Permalink
0.47b
Browse files Browse the repository at this point in the history
  • Loading branch information
thomas-huet committed Dec 2, 2014
0 parents commit dea4f90
Show file tree
Hide file tree
Showing 69 changed files with 9,676 additions and 0 deletions.
99 changes: 99 additions & 0 deletions Makefile
@@ -0,0 +1,99 @@
#
# american fuzzy lop - make wrapper
# ---------------------------------
#
# Written and maintained by Michal Zalewski <lcamtuf@google.com>
#
# Copyright 2013, 2014 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
# http://www.apache.org/licenses/LICENSE-2.0
#

PROGNAME = afl
VERSION = 0.47b

BIN_PATH = /usr/local/bin
HELPER_PATH = /usr/local/lib/afl

PROGS = afl-gcc afl-as afl-fuzz afl-showmap

CFLAGS += -O3 -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign \
-DAFL_PATH=\"$(HELPER_PATH)\" -DVERSION=\"$(VERSION)\"

GCC48PLUS := $(shell expr `$(CC) -dumpversion | cut -f-2 -d.` \>= 4.8)

ifeq "$(GCC48PLUS)" "1"
CFLAGS += -DUSE_ASAN=1
endif

ifneq "$(HOSTNAME)" "raccoon"
CFLAGS += -Wno-format
endif

COMM_HDR = alloc-inl.h config.h debug.h types.h

all: test_gcc test_x86 $(PROGS) test_build test_prev all_done

test_gcc:
@echo "[*] Checking for an installation of GCC..."
@$(CC) -v >.test 2>&1; grep -iq '^gcc.version' .test || ( echo; echo "Oops, looks like you don't have GCC installed (or you need to specify \$CC)."; echo; rm -f .test; exit 1 )
@rm -f .test

test_x86: | test_gcc
@echo "[*] Checking for the ability to compile x86 code..."
@echo 'main() { __asm__("xorb %al, %al"); }' | $(CC) -w -x c - -o .test || ( echo; echo "Oops, looks like your compiler can't generate x86 code."; echo; echo "(If you are looking for ARM, see experimental/arm_support/README.)"; echo; exit 1 )
@rm -f .test

afl-gcc: afl-gcc.c $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $(LDFLAGS) $@.c -o $@
ln -s afl-gcc afl-g++ 2>/dev/null || true

afl-as: afl-as.c afl-as.h $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $(LDFLAGS) $@.c -o $@
ln -s afl-as as 2>/dev/null || true

afl-fuzz: afl-fuzz.c $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $(LDFLAGS) $@.c -o $@

afl-showmap: afl-showmap.c $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $(LDFLAGS) $@.c -o $@

test_build: afl-gcc afl-as afl-showmap
@echo "[*] Testing GCC wrapper and instrumentation output..."
AFL_QUIET=1 AFL_PATH=. ./afl-gcc $(CFLAGS) test-instr.c -o test-instr
echo 0 | AFL_SINK_OUTPUT=1 AFL_QUIET=1 ./afl-showmap ./test-instr 2>.test-instr0
echo 1 | AFL_SINK_OUTPUT=1 AFL_QUIET=1 ./afl-showmap ./test-instr 2>.test-instr1
@rm -f test-instr
@diff -qs .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please ping <lcamtuf@google.com> to troubleshoot the issue."; echo; exit 1; fi
@echo "[+] All right, the instrumentation seems to be working!"

test_prev: test_build
@test -f "$(HELPER_PATH)/as"; TR="$$?"; if [ "$$TR" = "0" ]; then echo "[!] NOTE: You seem to have another copy of afl installed in $(HELPER_PATH)."; echo " You must use 'make install' or set AFL_PATH to use the current build instead."; else echo "[+] No previously-installed build detected, no need to replace anything."; fi

all_done: test_prev
@echo "[+] All done! Be sure to review README - it's pretty short and useful."

clean:
rm -f $(PROGS) as afl-g++ *.o *~ a.out core core.[1-9][0-9]* *.stackdump test .test
rm -rf out_dir

install: all
install afl-gcc afl-g++ afl-fuzz afl-showmap $${DESTDIR}$(BIN_PATH)
mkdir -p -m 755 $${DESTDIR}$(HELPER_PATH) 2>/dev/null
install afl-as as $${DESTDIR}$(HELPER_PATH)

publish: clean
test "`basename $$PWD`" = "afl" || exit 1
cd ..; rm -rf $(PROGNAME)-$(VERSION); cp -pr $(PROGNAME) $(PROGNAME)-$(VERSION); \
tar cfvz ~/www/afl/releases/$(PROGNAME)-$(VERSION).tgz $(PROGNAME)-$(VERSION)
chmod 644 ~/www/afl/releases/$(PROGNAME)-$(VERSION).tgz
( cd ~/www/afl/releases/; ln -s -f $(PROGNAME)-$(VERSION).tgz $(PROGNAME)-latest.tgz )
cat docs/README >~/www/afl/README.txt
cat docs/status_screen.txt >~/www/afl/status_screen.txt



1 change: 1 addition & 0 deletions README
250 changes: 250 additions & 0 deletions afl-as.c
@@ -0,0 +1,250 @@
/*
american fuzzy lop - wrapper for GNU as
---------------------------------------
Written and maintained by Michal Zalewski <lcamtuf@google.com>
Copyright 2013, 2014 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
http://www.apache.org/licenses/LICENSE-2.0
The sole purpose of this wrapper is to preprocess assembly files generated
by GCC and inject the instrumentation bits included from afl-as.h. It is
automatically invoked by the toolchain when compiling programs using
afl-gcc.
If AFL_QUIET is set, non-essential messages will not be shown. This is
useful when dealing with wonky build systems.
*/

#define AFL_MAIN

#include "config.h"
#include "types.h"
#include "debug.h"
#include "alloc-inl.h"

#include "afl-as.h"

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <sys/fcntl.h>
#include <sys/wait.h>
#include <sys/time.h>

static u8** as_params; /* Parameters passed to the real 'as' */

static u8* input_file; /* Originally specified input file */
static u8* modified_file; /* Instrumented file for the real 'as' */

static u32 rand_seed; /* Random seed used for instrumentation */

static u8 be_quiet, /* Quiet mode (no stderr output) */
use_64bit; /* Output 64-bit instrumentation */


/* Examine and modify parameters to pass to 'as'. Note that the file name
is always the last parameter passed by GCC, so we exploit this property
to keep the code simple. */

static void edit_params(int argc, char** argv) {

u8* tmp_dir = getenv("TMPDIR");
u32 i;

if (!tmp_dir) tmp_dir = "/tmp";

as_params = ck_alloc((argc + 1) * sizeof(u8*));

memcpy(as_params, argv, argc * sizeof(u8*));

as_params[0] = "as";
as_params[argc] = 0;

for (i = 1; i < argc; i++)
if (!strcmp(as_params[i], "--64")) use_64bit = 1;

input_file = as_params[argc - 1];

if (input_file[0] == '-') {

if (input_file[1]) FATAL("Incorrect use (not called through afl-gcc?)");
else input_file = NULL;

}

modified_file = alloc_printf("%s/.afl-%u-%u.s", tmp_dir, getpid(),
(u32)time(NULL));

as_params[argc - 1] = modified_file;

}


/* Process input file, generate modified_file. Insert instrumentation in all
the appropriate places. */

static void add_instrumentation(void) {

static u8 line[MAX_AS_LINE];

FILE* inf;
FILE* outf;
s32 outfd;
u32 ins_lines = 0;
u8 now_instr = 0, force_inhibit = 0;

if (input_file) {

inf = fopen(input_file, "r");
if (!inf) PFATAL("Unable to read '%s'", input_file);

} else inf = stdin;

outfd = open(modified_file, O_WRONLY | O_EXCL | O_CREAT, 0600);

if (outfd < 0) PFATAL("Unable to write to '%s'", modified_file);

outf = fdopen(outfd, "w");

if (!outf) PFATAL("fdopen() failed");

while (fgets(line, MAX_AS_LINE, inf)) {

fputs(line, outf);

/* We only want to instrument the .text section. So, let's keep track
of that in processed files. */

if (line[0] == '\t' && line[1] == '.') {

if (!strncmp(line + 2, "text\n", 5) ||
!strncmp(line + 2, "section\t.text", 13)) {
now_instr = 1;
continue;
}

if (!strncmp(line + 2, "section\t", 8) ||
!strncmp(line + 2, "bss\n", 4) ||
!strncmp(line + 2, "data\n", 5)) {
now_instr = 0;
continue;
}

}

if (strstr(line, ".code")) {

if (strstr(line, ".code32")) force_inhibit = use_64bit;
if (strstr(line, ".code64")) force_inhibit = !use_64bit;

}

/* If we're in the right mood for instrumenting, check for function
names or conditional labels. */

if (!force_inhibit && now_instr && (
(strstr(line, ":\n") && (line[0] == '.' ? isdigit(line[2]) : 1)) ||
(line[0] == '\t' && line[1] == 'j' && line[2] != 'm'))) {

/* Every function name and conditional label is given a random ID.
This ID, XORed with the ID of the previously executed one, is used
to selected a byte in the execution bitmap that is updated by the
runtime instrumentation.
All of this forms an almost-unique identifier of a particular state
transition in program's control flow.
If COVERAGE_ONLY is set, the instrumentation will use the current
location only, and skip the XOR part. */

fprintf(outf, use_64bit ? trampoline_fmt_64 : trampoline_fmt_32,
R(MAP_SIZE));

ins_lines++;

}

}

if (ins_lines)
fputs(use_64bit ? main_payload_64 : main_payload_32, outf);

if (input_file) fclose(inf);
fclose(outf);

if (!be_quiet) {

if (!ins_lines) WARNF("No instrumentation targets found.");
else OKF("Instrumented %u locations (%s-bit mode, seed 0x%08x).",
ins_lines, use_64bit ? "64" : "32", rand_seed);

}

}


/* Main entry point */

int main(int argc, char** argv) {

s32 pid;
int status;

struct timeval tv;
struct timezone tz;

if (!getenv("AFL_QUIET") && !getenv("as_nl")) {

SAYF(cCYA "afl-as " cBRI VERSION cRST " (" __DATE__ " " __TIME__
") by <lcamtuf@google.com>\n");

} else be_quiet = 1;

if (argc < 2) {

SAYF("\n"
"This is a helper application for afl-fuzz. It is a wrapper around GNU 'as',\n"
"executed by the toolchain whenever using afl-gcc. You probably don't want to\n"
"run this program directly.\n\n");

exit(1);

}

gettimeofday(&tv, &tz);

rand_seed = tv.tv_sec ^ tv.tv_usec ^ getpid();

srandom(rand_seed);

edit_params(argc, argv);

add_instrumentation();

if (!(pid = fork())) {

execvp(as_params[0], (char**)as_params);
FATAL("Oops, failed to execute '%s' - check your PATH", as_params[0]);

}

if (pid < 0) PFATAL("fork() failed");

if (waitpid(pid, &status, 0) <= 0) PFATAL("waitpid() failed");

unlink(modified_file);

exit(WEXITSTATUS(status));

}

0 comments on commit dea4f90

Please sign in to comment.