forked from aflgo/aflgo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
1,214 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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__ */ | ||
|
@@ -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? */ | ||
|
@@ -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 */ | ||
|
||
|
@@ -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 */ | ||
|
@@ -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) { | ||
|
@@ -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; | ||
|
@@ -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"); | ||
|
||
|
@@ -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 | ||
|
@@ -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); | ||
|
@@ -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; | ||
|
||
} | ||
|
@@ -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" | ||
|
@@ -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) { | ||
|
@@ -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) { | ||
|
||
|
@@ -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]); | ||
|
@@ -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(); | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -347,4 +347,8 @@ | |
|
||
// #define IGNORE_FINDS | ||
|
||
#define MAX_FACTOR 32 | ||
|
||
//#define AFLGO_TRACING | ||
|
||
#endif /* ! _HAVE_CONFIG_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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"; | ||
|
@@ -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; | ||
|
||
|
@@ -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 */ | ||
|
||
} | ||
|
Oops, something went wrong.