This commit is contained in:
vanhauser-thc
2025-04-21 10:59:59 +02:00
parent 0a06e36788
commit 05f4762894
2 changed files with 122 additions and 71 deletions

View File

@ -289,7 +289,7 @@ ifneq "$(findstring OpenBSD, $(SYS))" ""
override LDFLAGS += -lpthread -lm override LDFLAGS += -lpthread -lm
endif endif
COMM_HDR = include/alloc-inl.h include/config.h include/debug.h include/types.h COMM_HDR = include/alloc-inl.h include/config.h include/debug.h include/types.h include/afl-fuzz.h include/hash.h include/sharedmem.h include/forkserver.h include/common.h include/list.h
ifeq "$(shell echo '$(HASH)include <Python.h>@int main() {return 0; }' | tr @ '\n' | $(CC) $(CFLAGS) -x c - -o .test $(PYTHON_INCLUDE) $(LDFLAGS) $(PYTHON_LIB) 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" ifeq "$(shell echo '$(HASH)include <Python.h>@int main() {return 0; }' | tr @ '\n' | $(CC) $(CFLAGS) -x c - -o .test $(PYTHON_INCLUDE) $(LDFLAGS) $(PYTHON_LIB) 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
PYTHON_OK=1 PYTHON_OK=1
@ -472,19 +472,19 @@ endif
ready: ready:
@echo "[+] Everything seems to be working, ready to compile. ($(shell $(CC) --version 2>&1|head -n 1))" @echo "[+] Everything seems to be working, ready to compile. ($(shell $(CC) --version 2>&1|head -n 1))"
src/afl-performance.o : $(COMM_HDR) src/afl-performance.c include/hash.h src/afl-performance.o: $(COMM_HDR) src/afl-performance.c
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(CFLAGS_OPT) $(SPECIAL_PERFORMANCE) -Iinclude -c src/afl-performance.c -o src/afl-performance.o $(CC) $(CFLAGS) $(CFLAGS_FLTO) $(CFLAGS_OPT) $(SPECIAL_PERFORMANCE) -Iinclude -c src/afl-performance.c -o src/afl-performance.o
src/afl-common.o : $(COMM_HDR) src/afl-common.c include/common.h src/afl-common.o: $(COMM_HDR) src/afl-common.c include/envs.h
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-common.c -o src/afl-common.o $(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-common.c -o src/afl-common.o
src/afl-forkserver.o : $(COMM_HDR) src/afl-forkserver.c include/forkserver.h src/afl-forkserver.o: $(COMM_HDR) src/afl-forkserver.c
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-forkserver.c -o src/afl-forkserver.o $(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-forkserver.c -o src/afl-forkserver.o
src/afl-sharedmem.o : $(COMM_HDR) src/afl-sharedmem.c include/sharedmem.h src/afl-sharedmem.o: $(COMM_HDR) src/afl-sharedmem.c include/android-ashmem.h include/cmplog.h
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-sharedmem.c -o src/afl-sharedmem.o $(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-sharedmem.c -o src/afl-sharedmem.o
afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o | test_x86 afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o include/cmplog.h include/envs.h | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS) -lm $(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS) -lm
ifdef IS_IOS ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; } @ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }

View File

@ -63,25 +63,26 @@
#include <Python.h> #include <Python.h>
#endif #endif
extern void destroy_custom_mutators(afl_state_t *); extern void destroy_custom_mutators(afl_state_t *);
void list_init(list_t *list) { void list_init(list_t *list) {
if (list) { if (list) {
list->element_prealloc_count = 0; list->element_prealloc_count = 0;
memset(list->element_prealloc_buf, 0, sizeof(list->element_prealloc_buf)); memset(list->element_prealloc_buf, 0, sizeof(list->element_prealloc_buf));
} }
} }
void setup_custom_mutators(afl_state_t *); void setup_custom_mutators(afl_state_t *);
struct custom_mutator *load_custom_mutator(afl_state_t *, const char *); struct custom_mutator *load_custom_mutator(afl_state_t *, const char *);
#ifdef USE_PYTHON #ifdef USE_PYTHON
struct custom_mutator *load_custom_mutator_py(afl_state_t *, char *); struct custom_mutator *load_custom_mutator_py(afl_state_t *, char *);
#endif #endif
static afl_state_t *afl; /* State for custom mutators */ static afl_state_t *afl; /* State for custom mutators */
static u8 *mask_bitmap; /* Mask for trace bits (-B) */ static u8 *mask_bitmap; /* Mask for trace bits (-B) */
static u8 *in_file, /* Minimizer input test case */ static u8 *in_file, /* Minimizer input test case */
*out_file, *output_file; /* Minimizer output file */ *out_file, *output_file; /* Minimizer output file */
@ -96,9 +97,6 @@ static u32 in_len, /* Input data length */
static u64 orig_cksum; /* Original checksum */ static u64 orig_cksum; /* Original checksum */
static u8 crash_mode, /* Crash-centric mode? */ static u8 crash_mode, /* Crash-centric mode? */
hang_mode, /* Minimize as long as it hangs */ hang_mode, /* Minimize as long as it hangs */
exit_crash, /* Treat non-zero exit as crash? */ exit_crash, /* Treat non-zero exit as crash? */
@ -163,35 +161,48 @@ static sharedmem_t *deinit_shmem(afl_forkserver_t *fsrv,
/* dummy functions */ /* dummy functions */
u32 write_to_testcase(afl_state_t *afl, void **mem, u32 a, u32 b) { u32 write_to_testcase(afl_state_t *afl, void **mem, u32 a, u32 b) {
(void)afl; (void)afl;
(void)mem; (void)mem;
return a + b; return a + b;
} }
void show_stats(afl_state_t *afl) { void show_stats(afl_state_t *afl) {
(void)afl; (void)afl;
} }
void update_bitmap_score(afl_state_t *afl, struct queue_entry *q, bool add_to_queue) { void update_bitmap_score(afl_state_t *afl, struct queue_entry *q,
bool add_to_queue) {
(void)afl; (void)afl;
(void)q; (void)q;
(void)add_to_queue; (void)add_to_queue;
} }
fsrv_run_result_t fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 i) { fsrv_run_result_t fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv,
u32 i) {
(void)afl; (void)afl;
(void)fsrv; (void)fsrv;
(void)i; (void)i;
return 0; return 0;
} }
#ifndef USE_PYTHON #ifndef USE_PYTHON
struct custom_mutator *load_custom_mutator_py(afl_state_t *afl, char *module) { struct custom_mutator *load_custom_mutator_py(afl_state_t *afl, char *module) {
(void)afl; (void)afl;
(void)module; (void)module;
FATAL("Python support not available in this build"); FATAL("Python support not available in this build");
return NULL; return NULL;
} }
#endif #endif
/* Apply mask to classified bitmap (if set). */ /* Apply mask to classified bitmap (if set). */
@ -212,7 +223,6 @@ static void apply_mask(u32 *mem, u32 *mask) {
} }
void classify_counts(afl_forkserver_t *fsrv) { void classify_counts(afl_forkserver_t *fsrv) {
u8 *mem = fsrv->trace_bits; u8 *mem = fsrv->trace_bits;
@ -270,9 +280,12 @@ static void at_exit_handler(void) {
if (remove_out_file) unlink(out_file); if (remove_out_file) unlink(out_file);
if (afl) { if (afl) {
destroy_custom_mutators(afl); destroy_custom_mutators(afl);
ck_free(afl); ck_free(afl);
} }
} }
/* Read initial file. */ /* Read initial file. */
@ -324,7 +337,8 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) {
} }
/* Helper function to handle custom mutators for testcase writing */ /* Helper function to handle custom mutators for testcase writing */
static void pre_afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *mem, u32 len) { static void pre_afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *mem,
u32 len) {
static u8 buf[MAX_FILE]; static u8 buf[MAX_FILE];
u32 sent = 0; u32 sent = 0;
@ -343,10 +357,14 @@ static void pre_afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *mem, u32
el->afl_custom_post_process(el->data, new_mem, new_size, &new_buf); el->afl_custom_post_process(el->data, new_mem, new_size, &new_buf);
if (!new_buf || new_size <= 0) { if (!new_buf || new_size <= 0) {
return; return;
} else { } else {
new_mem = new_buf; new_mem = new_buf;
len = new_size; len = new_size;
} }
} }
@ -354,15 +372,19 @@ static void pre_afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *mem, u32
}); });
if (new_mem != mem && new_mem != NULL) { if (new_mem != mem && new_mem != NULL) {
mem = buf; mem = buf;
memcpy(mem, new_mem, new_size); memcpy(mem, new_mem, new_size);
} }
LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
if (el->afl_custom_fuzz_send) { if (el->afl_custom_fuzz_send) {
el->afl_custom_fuzz_send(el->data, mem, len); el->afl_custom_fuzz_send(el->data, mem, len);
sent = 1; sent = 1;
} }
}); });
@ -378,12 +400,11 @@ static void pre_afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *mem, u32
static u8 tmin_run_target(afl_forkserver_t *fsrv, u8 *mem, u32 len, static u8 tmin_run_target(afl_forkserver_t *fsrv, u8 *mem, u32 len,
u8 first_run) { u8 first_run) {
pre_afl_fsrv_write_to_testcase(fsrv, mem, len); pre_afl_fsrv_write_to_testcase(fsrv, mem, len);
fsrv_run_result_t ret = fsrv_run_result_t ret =
afl_fsrv_run_target(fsrv, fsrv->exec_tmout, &stop_soon); afl_fsrv_run_target(fsrv, fsrv->exec_tmout, &stop_soon);
if (ret == FSRV_RUN_ERROR) { FATAL("Couldn't run child"); } if (ret == FSRV_RUN_ERROR) { FATAL("Couldn't run child"); }
if (stop_soon) { if (stop_soon) {
@ -469,105 +490,132 @@ static u8 tmin_run_target(afl_forkserver_t *fsrv, u8 *mem, u32 len,
/* Actually minimize! */ /* Actually minimize! */
static void minimize(afl_forkserver_t *fsrv) { static void minimize(afl_forkserver_t *fsrv) {
static u32 alpha_map[256]; static u32 alpha_map[256];
u8 *tmp_buf = ck_alloc_nozero(in_len); u8 *tmp_buf = ck_alloc_nozero(in_len);
u32 orig_len = in_len, stage_o_len; u32 orig_len = in_len, stage_o_len;
u32 del_len, set_len, del_pos, set_pos, i, alpha_size, cur_pass = 0; u32 del_len, set_len, del_pos, set_pos, i, alpha_size, cur_pass = 0;
u32 syms_removed, alpha_del0 = 0, alpha_del1, alpha_del2, alpha_d_total = 0; u32 syms_removed, alpha_del0 = 0, alpha_del1, alpha_del2, alpha_d_total = 0;
u8 changed_any, prev_del; u8 changed_any, prev_del;
#ifdef USE_PYTHON #ifdef USE_PYTHON
// Try to load python module // Try to load python module
char *py_module = getenv("AFL_PYTHON_MODULE"); char *py_module = getenv("AFL_PYTHON_MODULE");
if (py_module) { if (py_module) {
// We cannot use Python custom mutators in tmin // We cannot use Python custom mutators in tmin
if (debug) WARNF("Python custom mutator support not available in afl-tmin"); if (debug) WARNF("Python custom mutator support not available in afl-tmin");
} }
#endif #endif
// Custom mutator trimming // Custom mutator trimming
if (afl && afl->custom_mutators_count) { if (afl && afl->custom_mutators_count) {
LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
if (el->afl_custom_init_trim && el->afl_custom_trim &&
if (el->afl_custom_init_trim && el->afl_custom_trim &&
el->afl_custom_post_trim) { el->afl_custom_post_trim) {
ACTF("Performing custom trim with %s...", el->name); ACTF("Performing custom trim with %s...", el->name);
// Initialize the trimmer // Initialize the trimmer
s32 initial_steps = el->afl_custom_init_trim(el->data, in_data, in_len); s32 initial_steps = el->afl_custom_init_trim(el->data, in_data, in_len);
if (initial_steps <= 0) { if (initial_steps <= 0) {
WARNF("Custom trimmer %s returned %d, skipping", el->name, initial_steps);
WARNF("Custom trimmer %s returned %d, skipping", el->name,
initial_steps);
continue; continue;
} }
ACTF("Custom trimmer initialized, %d steps planned", initial_steps); ACTF("Custom trimmer initialized, %d steps planned", initial_steps);
u32 trim_rounds = 0; u32 trim_rounds = 0;
u32 trimmed_successfully = 0; u32 trimmed_successfully = 0;
// Trim loop // Trim loop
s32 cur_step = 0; s32 cur_step = 0;
while (cur_step < initial_steps) { while (cur_step < initial_steps) {
u8* trimmed_buf = NULL;
u8 *trimmed_buf = NULL;
size_t trimmed_size; size_t trimmed_size;
u8 *retbuf = NULL; u8 *retbuf = NULL;
trimmed_size = el->afl_custom_trim(el->data, &retbuf); trimmed_size = el->afl_custom_trim(el->data, &retbuf);
// If trimmed_size equals or exceeds original size, skip // If trimmed_size equals or exceeds original size, skip
if (trimmed_size >= in_len) { if (trimmed_size >= in_len) {
SAYF("[Custom trim] Round %u: no improvements over %u bytes.\n",
SAYF("[Custom trim] Round %u: no improvements over %u bytes.\n",
trim_rounds, in_len); trim_rounds, in_len);
el->afl_custom_post_trim(el->data, 0); el->afl_custom_post_trim(el->data, 0);
cur_step++; cur_step++;
trim_rounds++; trim_rounds++;
continue; continue;
} }
trimmed_buf = retbuf; trimmed_buf = retbuf;
// Test if the trimmed case still works // Test if the trimmed case still works
if (!tmin_run_target(fsrv, trimmed_buf, trimmed_size, 0)) { if (!tmin_run_target(fsrv, trimmed_buf, trimmed_size, 0)) {
SAYF("[Custom trim] But the testcase no longer reproduces - skipping this reduction.\n");
SAYF(
"[Custom trim] But the testcase no longer reproduces - "
"skipping this reduction.\n");
el->afl_custom_post_trim(el->data, 0); el->afl_custom_post_trim(el->data, 0);
if (trimmed_buf != in_data) { if (trimmed_buf != in_data) { ck_free(trimmed_buf); }
ck_free(trimmed_buf);
}
} else { } else {
// Accept the reduction // Accept the reduction
u8 *old_in_data = in_data; u8 *old_in_data = in_data;
in_data = trimmed_buf; in_data = trimmed_buf;
in_len = trimmed_size; in_len = trimmed_size;
trimmed_successfully = 1; trimmed_successfully = 1;
el->afl_custom_post_trim(el->data, 1); el->afl_custom_post_trim(el->data, 1);
SAYF("[Custom trim] Successful reduction to %u bytes\n", in_len); SAYF("[Custom trim] Successful reduction to %u bytes\n", in_len);
if (old_in_data != in_data && old_in_data != trimmed_buf) { if (old_in_data != in_data && old_in_data != trimmed_buf) {
ck_free(old_in_data); ck_free(old_in_data);
} }
} }
cur_step++; cur_step++;
trim_rounds++; trim_rounds++;
} }
ACTF("Custom trimming with %s complete after %u rounds, reduced: %s", ACTF("Custom trimming with %s complete after %u rounds, reduced: %s",
el->name, trim_rounds, trimmed_successfully ? "yes" : "no"); el->name, trim_rounds, trimmed_successfully ? "yes" : "no");
if (trimmed_successfully) { if (trimmed_successfully) {
if (tmp_buf) { ck_free(tmp_buf); } if (tmp_buf) { ck_free(tmp_buf); }
return; // Skip standard minimization if successful return; // Skip standard minimization if successful
} }
} }
}); });
} }
// Skip built-in minimization if in_len is too small // Skip built-in minimization if in_len is too small
if (in_len <= 1) { if (in_len <= 1) {
if (tmp_buf) { ck_free(tmp_buf); } if (tmp_buf) { ck_free(tmp_buf); }
return; return;
} }
/*********************** /***********************
@ -1046,7 +1094,7 @@ int main(int argc, char **argv_orig, char **envp) {
s32 opt; s32 opt;
u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0, u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0,
del_limit_given = 0; del_limit_given = 0;
char **use_argv; char **use_argv;
char **argv = argv_cpy_dup(argc, argv_orig); char **argv = argv_cpy_dup(argc, argv_orig);
@ -1062,7 +1110,7 @@ int main(int argc, char **argv_orig, char **envp) {
SAYF(cCYA "afl-tmin" VERSION cRST " by Michal Zalewski\n"); SAYF(cCYA "afl-tmin" VERSION cRST " by Michal Zalewski\n");
while ((opt = getopt(argc, argv, "+i:o:f:m:t:l:B:xeAOQUWXYHh")) > 0) { while ((opt = getopt(argc, argv, "+i:o:f:m:t:l:B:xeAOQUWXYHh")) > 0) {
switch (opt) { switch (opt) {
@ -1448,25 +1496,28 @@ int main(int argc, char **argv_orig, char **envp) {
read_initial_file(); read_initial_file();
// Initialize AFL state for custom mutators // Initialize AFL state for custom mutators
afl = calloc(1, sizeof(afl_state_t)); afl = calloc(1, sizeof(afl_state_t));
if (afl) { if (afl) {
list_init(&afl->custom_mutator_list);
afl->custom_mutators_count = 0; list_init(&afl->custom_mutator_list);
afl->custom_mutators_count = 0;
afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY);
if (afl->fsrv.dev_urandom_fd < 0) { PFATAL("Unable to open /dev/urandom"); } afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY);
if (afl->fsrv.dev_urandom_fd < 0) { PFATAL("Unable to open /dev/urandom"); }
afl->afl_env.afl_custom_mutator_library = getenv("AFL_CUSTOM_MUTATOR_LIBRARY");
afl->afl_env.afl_python_module = getenv("AFL_PYTHON_MODULE"); afl->afl_env.afl_custom_mutator_library =
getenv("AFL_CUSTOM_MUTATOR_LIBRARY");
afl->shm = shm; afl->afl_env.afl_python_module = getenv("AFL_PYTHON_MODULE");
afl->out_dir = ".";
afl->shm = shm;
memcpy(&afl->fsrv, fsrv, sizeof(afl_forkserver_t)); afl->out_dir = ".";
setup_custom_mutators(afl); memcpy(&afl->fsrv, fsrv, sizeof(afl_forkserver_t));
}
setup_custom_mutators(afl);
}
#ifdef __linux__ #ifdef __linux__
if (!fsrv->nyx_mode) { (void)check_binary_signatures(fsrv->target_path); } if (!fsrv->nyx_mode) { (void)check_binary_signatures(fsrv->target_path); }