Skip to content

Commit

Permalink
AFLGo initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
mboehme committed Aug 14, 2017
1 parent a4a9767 commit 9918852
Show file tree
Hide file tree
Showing 9 changed files with 1,214 additions and 50 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ CFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign \
-DBIN_PATH=\"$(BIN_PATH)\"

ifneq "$(filter Linux GNU%,$(shell uname))" ""
LDFLAGS += -ldl
LDFLAGS += -ldl -lm
endif

ifeq "$(findstring clang, $(shell $(CC) --version 2>/dev/null))" ""
Expand Down
197 changes: 192 additions & 5 deletions afl-fuzz.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@
#include <sys/ioctl.h>
#include <sys/file.h>

#include <math.h>

#if defined(__APPLE__) || defined(__FreeBSD__) || defined (__OpenBSD__)
# include <sys/sysctl.h>
#endif /* __APPLE__ || __FreeBSD__ || __OpenBSD__ */
Expand Down Expand Up @@ -98,6 +100,14 @@ EXP_ST u64 mem_limit = MEM_LIMIT; /* Memory cap for child (MB) */

static u32 stats_update_freq = 1; /* Stats update frequency (execs) */

static u8 cooling_schedule = 0; /* Cooling schedule for directed fuzzing */
enum {
/* 00 */ SAN_EXP, /* Exponential schedule */
/* 01 */ SAN_LOG, /* Logarithmical schedule */
/* 02 */ SAN_LIN, /* Linear schedule */
/* 03 */ SAN_QUAD /* Quadratic schedule */
};

EXP_ST u8 skip_deterministic, /* Skip deterministic stages? */
force_deterministic, /* Force deterministic stages? */
use_splicing, /* Recombine input files? */
Expand Down Expand Up @@ -245,6 +255,8 @@ struct queue_entry {
u8* trace_mini; /* Trace bytes, if kept */
u32 tc_ref; /* Trace bytes ref count */

double distance; /* Distance to targets */

struct queue_entry *next, /* Next element, if any */
*next_100; /* 100 elements ahead */

Expand All @@ -270,6 +282,11 @@ static u32 extras_cnt; /* Total number of tokens read */
static struct extra_data* a_extras; /* Automatically selected extras */
static u32 a_extras_cnt; /* Total number of tokens available */

static double cur_distance = -1.0; /* Distance of executed input */
static double max_distance = -1.0; /* Maximal distance for any input */
static double min_distance = -1.0; /* Minimal distance for any input */
static u32 t_x = 10; /* Time to exploitation (Default: 10 min) */

static u8* (*post_handler)(u8* buf, u32* len);

/* Interesting values, as per config.h */
Expand Down Expand Up @@ -780,6 +797,18 @@ static void add_to_queue(u8* fname, u32 len, u8 passed_det) {
q->depth = cur_depth + 1;
q->passed_det = passed_det;

q->distance = cur_distance;
if (cur_distance > 0) {

if (max_distance <= 0) {
max_distance = cur_distance;
min_distance = cur_distance;
}
if (cur_distance > max_distance) max_distance = cur_distance;
if (cur_distance < min_distance) min_distance = cur_distance;

}

if (q->depth > max_depth) max_depth = q->depth;

if (queue_top) {
Expand Down Expand Up @@ -882,13 +911,31 @@ static inline u8 has_new_bits(u8* virgin_map) {

u32 i = (MAP_SIZE >> 3);

/* Calculate distance of current input to targets */
u64* total_distance = (u64*) (trace_bits + MAP_SIZE);
u64* total_count = (u64*) (trace_bits + MAP_SIZE + 8);

if (*total_count > 0)
cur_distance = (double) (*total_distance) / (double) (*total_count);
else
cur_distance = -1.0;

#else

u32* current = (u32*)trace_bits;
u32* virgin = (u32*)virgin_map;

u32 i = (MAP_SIZE >> 2);

/* Calculate distance of current input to targets */
u32* total_distance = (u32*)(trace_bits + MAP_SIZE);
u32* total_count = (u32*)(trace_bits + MAP_SIZE + 4);

if (*total_count > 0) {
cur_distance = (double) (*total_distance) / (double) (*total_count);
else
cur_distance = -1.0;

#endif /* ^__x86_64__ */

u8 ret = 0;
Expand Down Expand Up @@ -1346,7 +1393,8 @@ EXP_ST void setup_shm(void) {
memset(virgin_tmout, 255, MAP_SIZE);
memset(virgin_crash, 255, MAP_SIZE);

shm_id = shmget(IPC_PRIVATE, MAP_SIZE, IPC_CREAT | IPC_EXCL | 0600);
/* Allocate 24 byte more for distance info */
shm_id = shmget(IPC_PRIVATE, MAP_SIZE + 16, IPC_CREAT | IPC_EXCL | 0600);

if (shm_id < 0) PFATAL("shmget() failed");

Expand Down Expand Up @@ -2270,7 +2318,7 @@ static u8 run_target(char** argv, u32 timeout) {
must prevent any earlier operations from venturing into that
territory. */

memset(trace_bits, 0, MAP_SIZE);
memset(trace_bits, 0, MAP_SIZE + 16);
MEM_BARRIER();

/* If we're running in "dumb" mode, we can't rely on the fork server
Expand Down Expand Up @@ -2582,6 +2630,27 @@ static u8 calibrate_case(char** argv, struct queue_entry* q, u8* use_mem,

cksum = hash32(trace_bits, MAP_SIZE, HASH_CONST);

/* This is relevant when test cases are added w/out save_if_interesting */

if (q->distance <= 0) {

/* This calculates cur_distance */
has_new_bits(virgin_bits);

q->distance = cur_distance;
if (cur_distance > 0) {

if (max_distance <= 0) {
max_distance = cur_distance;
min_distance = cur_distance;
}
if (cur_distance > max_distance) max_distance = cur_distance;
if (cur_distance < min_distance) min_distance = cur_distance;

}

}

if (q->exec_cksum != cksum) {

u8 hnb = has_new_bits(virgin_bits);
Expand Down Expand Up @@ -4713,10 +4782,68 @@ static u32 calculate_score(struct queue_entry* q) {

}

u64 cur_ms = get_cur_time();
u64 t = (cur_ms - start_time) / 1000;
double progress_to_tx = ((double) t) / ((double) t_x * 60.0);

double T;

//TODO Substitute functions of exp and log with faster bitwise operations on integers
switch (cooling_schedule) {
case SAN_EXP:

T = 1.0 / pow(20.0, progress_to_tx);

break;

case SAN_LOG:

// alpha = 2 and exp(19/2) - 1 = 13358.7268297
T = 1.0 / (1.0 + 2.0 * log(1.0 + progress_to_tx * 13358.7268297));

break;

case SAN_LIN:

T = 1.0 / (1.0 + 19.0 * progress_to_tx);

break;

case SAN_QUAD:

T = 1.0 / (1.0 + 19.0 * pow(progress_to_tx, 2));

break;

default:
PFATAL ("Unkown Power Schedule for Directed Fuzzing");
}

double power_factor = 1.0;
if (q->distance > 0) {

double normalized_d = q->distance;
if (max_distance != min_distance)
normalized_d = (q->distance - min_distance) / (max_distance - min_distance);

if (normalized_d >= 0) {

double p = (1.0 - normalized_d) * (1.0 - T) + 0.5 * T;
power_factor = pow(2.0, 2.0 * (double) log2(MAX_FACTOR) * (p - 0.5));

}// else WARNF ("Normalized distance negative: %f", normalized_d);

}

perf_score *= power_factor;

/* Make sure that we don't go over limit. */

if (perf_score > HAVOC_MAX_MULT * 100) perf_score = HAVOC_MAX_MULT * 100;

/* AFLGO-DEBUGGING */
// fprintf(stderr, "[Time %llu] q->distance: %4lf, max_distance: %4lf min_distance: %4lf, T: %4.3lf, power_factor: %4.3lf, adjusted perf_score: %4d\n", t, q->distance, max_distance, min_distance, T, power_factor, perf_score);

return perf_score;

}
Expand Down Expand Up @@ -7023,6 +7150,13 @@ static void usage(u8* argv0) {
" -i dir - input directory with test cases\n"
" -o dir - output directory for fuzzer findings\n\n"

"Directed fuzzing specific settings:\n\n"

" -z schedule - temperature-based power schedules\n"
" {exp, log, lin, quad} (Default: exp)\n"
" -c min - time from start when SA enters exploitation\n"
" in secs (s), mins (m), hrs (h), or days (d)\n\n"

"Execution control settings:\n\n"

" -f file - location read by the fuzzed program (stdin)\n"
Expand Down Expand Up @@ -7665,9 +7799,17 @@ static void save_cmdline(u32 argc, char** argv) {

}


#ifndef AFL_LIB

int stricmp(char const *a, char const *b) {
int d;
for (;; a++, b++) {
d = tolower(*a) - tolower(*b);
if (d != 0 || !*a)
return d;
}
}

/* Main entry point */

int main(int argc, char** argv) {
Expand All @@ -7683,14 +7825,14 @@ int main(int argc, char** argv) {
struct timeval tv;
struct timezone tz;

SAYF(cCYA "afl-fuzz " cBRI VERSION cRST " by <[email protected]>\n");
SAYF(cCYA "aflgo (yeah!) " cBRI VERSION cRST "\n");

doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;

gettimeofday(&tv, &tz);
srandom(tv.tv_sec ^ tv.tv_usec ^ getpid());

while ((opt = getopt(argc, argv, "+i:o:f:m:t:T:dnCB:S:M:x:Q")) > 0)
while ((opt = getopt(argc, argv, "+i:o:f:m:t:T:dnCB:S:M:x:Qz:c:")) > 0)

switch (opt) {

Expand Down Expand Up @@ -7858,6 +8000,43 @@ int main(int argc, char** argv) {

break;

case 'z': /* Cooling schedule for Directed Fuzzing */

if (!stricmp(optarg, "exp"))
cooling_schedule = SAN_EXP;
else if (!stricmp(optarg, "log"))
cooling_schedule = SAN_LOG;
else if (!stricmp(optarg, "lin"))
cooling_schedule = SAN_LIN;
else if (!stricmp(optarg, "quad"))
cooling_schedule = SAN_QUAD;
else
PFATAL ("Unknown value for option -z");

break;

case 'c': { /* cut-off time for cooling schedule */

u8 suffix = 'm';

if (sscanf(optarg, "%u%c", &t_x, &suffix) < 1 ||
optarg[0] == '-') FATAL("Bad syntax used for -c");

switch (suffix) {

case 's': t_x /= 60; break;
case 'm': break;
case 'h': t_x *= 60; break;
case 'd': t_x *= 60 * 24; break;

default: FATAL("Unsupported suffix or bad syntax for -c");

}

}

break;

default:

usage(argv[0]);
Expand All @@ -7866,6 +8045,14 @@ int main(int argc, char** argv) {

if (optind == argc || !in_dir || !out_dir) usage(argv[0]);

OKF("Running with " cBRI "%s" cRST " schedule and time-to-exploitation set to " cBRI "%d minutes" cRST,
cooling_schedule == SAN_EXP ? "EXP" :
cooling_schedule == SAN_LOG ? "LOG" :
cooling_schedule == SAN_LIN ? "LIN" :
cooling_schedule == SAN_QUAD ? "QUAD" : "???",
t_x
);

setup_signal_handlers();
check_asan_opts();

Expand Down
4 changes: 4 additions & 0 deletions config.h
Original file line number Diff line number Diff line change
Expand Up @@ -347,4 +347,8 @@

// #define IGNORE_FINDS

#define MAX_FACTOR 32

//#define AFLGO_TRACING

#endif /* ! _HAVE_CONFIG_H */
10 changes: 8 additions & 2 deletions llvm_mode/afl-clang-fast.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ static void edit_params(u32 argc, char** argv) {
cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
cc_params[cc_par_cnt++] = "-mllvm";
cc_params[cc_par_cnt++] = "-sanitizer-coverage-block-threshold=0";
WARNF("Disabling AFLGO features..\n");
#else
cc_params[cc_par_cnt++] = "-Xclang";
cc_params[cc_par_cnt++] = "-load";
Expand All @@ -139,6 +140,11 @@ static void edit_params(u32 argc, char** argv) {
while (--argc) {
u8* cur = *(++argv);

if (!strncmp(cur, "-distance", 9)
|| !strncmp(cur, "-targets", 8)
|| !strncmp(cur, "-outdir", 7))
cc_params[cc_par_cnt++] = "-mllvm";

if (!strcmp(cur, "-m32")) bit_mode = 32;
if (!strcmp(cur, "-m64")) bit_mode = 64;

Expand Down Expand Up @@ -316,9 +322,9 @@ int main(int argc, char** argv) {
if (isatty(2) && !getenv("AFL_QUIET")) {

#ifdef USE_TRACE_PC
SAYF(cCYA "afl-clang-fast [tpcg] " cBRI VERSION cRST " by <[email protected]>\n");
SAYF(cCYA "aflgo-compiler (yeah!) [tpcg] " cBRI VERSION cRST "\n");
#else
SAYF(cCYA "afl-clang-fast " cBRI VERSION cRST " by <[email protected]>\n");
SAYF(cCYA "aflgo-compiler (yeah!) " cBRI VERSION cRST "\n");
#endif /* ^USE_TRACE_PC */

}
Expand Down
Loading

0 comments on commit 9918852

Please sign in to comment.