Skip to content

Commit c03f289

Browse files
committed
Add AFL_SHA1_FILENAMES option
1 parent ac6ccd5 commit c03f289

File tree

8 files changed

+479
-62
lines changed

8 files changed

+479
-62
lines changed

docs/env_variables.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,9 @@ checks or alter some of the more exotic semantics of the tool:
550550
use a custom afl-qemu-trace or if you need to modify the afl-qemu-trace
551551
arguments.
552552
553+
- `AFL_SHA1_FILENAMES` causes AFL++ to generate files named by the SHA1 hash
554+
of their contents, rather than use the standard `id:000000,...` names.
555+
553556
- `AFL_SHUFFLE_QUEUE` randomly reorders the input queue on startup. Requested
554557
by some users for unorthodox parallelized fuzzing setups, but not advisable
555558
otherwise.

include/afl-fuzz.h

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,8 @@ typedef struct afl_env_vars {
452452
afl_keep_timeouts, afl_no_crash_readme, afl_ignore_timeouts,
453453
afl_no_startup_calibration, afl_no_warn_instability,
454454
afl_post_process_keep_original, afl_crashing_seeds_as_new_crash,
455-
afl_final_sync, afl_ignore_seed_problems, afl_disable_redundant;
455+
afl_final_sync, afl_ignore_seed_problems, afl_disable_redundant,
456+
afl_sha1_filenames;
456457

457458
u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path,
458459
*afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload,
@@ -1404,6 +1405,32 @@ void queue_testcase_retake_mem(afl_state_t *afl, struct queue_entry *q, u8 *in,
14041405

14051406
void queue_testcase_store_mem(afl_state_t *afl, struct queue_entry *q, u8 *mem);
14061407

1408+
/* Compute the SHA1 hash of `data`, which is of `len` bytes, and return the
1409+
* result as a `\0`-terminated hex string, which the caller much `ck_free`. */
1410+
char *sha1_hex(const u8 *data, size_t len);
1411+
1412+
/* Apply `sha1_hex` to the first `len` bytes of data of the file at `fname`. */
1413+
char *sha1_hex_for_file(const char *fname, u32 len);
1414+
1415+
/* Create file `fn`, but allow it to already exist if `AFL_SHA1_FILENAMES` is
1416+
* enabled. */
1417+
static inline int permissive_create(afl_state_t *afl, const char *fn) {
1418+
1419+
int fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
1420+
if (unlikely(fd < 0)) {
1421+
1422+
if (!(afl->afl_env.afl_sha1_filenames && errno == EEXIST)) {
1423+
1424+
PFATAL("Unable to create '%s'", fn);
1425+
1426+
}
1427+
1428+
}
1429+
1430+
return fd;
1431+
1432+
}
1433+
14071434
#if TESTCASE_CACHE == 1
14081435
#error define of TESTCASE_CACHE must be zero or larger than 1
14091436
#endif

include/envs.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,15 +108,15 @@ static char *afl_environment_variables[] = {
108108
"AFL_QEMU_PERSISTENT_RETADDR_OFFSET", "AFL_QEMU_PERSISTENT_EXITS",
109109
"AFL_QEMU_INST_RANGES", "AFL_QEMU_EXCLUDE_RANGES", "AFL_QEMU_SNAPSHOT",
110110
"AFL_QEMU_TRACK_UNSTABLE", "AFL_QUIET", "AFL_RANDOM_ALLOC_CANARY",
111-
"AFL_REAL_PATH", "AFL_SHUFFLE_QUEUE", "AFL_SKIP_BIN_CHECK",
112-
"AFL_SKIP_CPUFREQ", "AFL_SKIP_CRASHES", "AFL_SKIP_OSSFUZZ", "AFL_STATSD",
113-
"AFL_STATSD_HOST", "AFL_STATSD_PORT", "AFL_STATSD_TAGS_FLAVOR",
114-
"AFL_SYNC_TIME", "AFL_TESTCACHE_SIZE", "AFL_TESTCACHE_ENTRIES",
115-
"AFL_TMIN_EXACT", "AFL_TMPDIR", "AFL_TOKEN_FILE", "AFL_TRACE_PC",
116-
"AFL_USE_ASAN", "AFL_USE_MSAN", "AFL_USE_TRACE_PC", "AFL_USE_UBSAN",
117-
"AFL_USE_TSAN", "AFL_USE_CFISAN", "AFL_USE_LSAN", "AFL_WINE_PATH",
118-
"AFL_NO_SNAPSHOT", "AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN", "AFL_USE_QASAN",
119-
"AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", NULL
111+
"AFL_REAL_PATH", "AFL_SHA1_FILENAMES", "AFL_SHUFFLE_QUEUE",
112+
"AFL_SKIP_BIN_CHECK", "AFL_SKIP_CPUFREQ", "AFL_SKIP_CRASHES",
113+
"AFL_SKIP_OSSFUZZ", "AFL_STATSD", "AFL_STATSD_HOST", "AFL_STATSD_PORT",
114+
"AFL_STATSD_TAGS_FLAVOR", "AFL_SYNC_TIME", "AFL_TESTCACHE_SIZE",
115+
"AFL_TESTCACHE_ENTRIES", "AFL_TMIN_EXACT", "AFL_TMPDIR", "AFL_TOKEN_FILE",
116+
"AFL_TRACE_PC", "AFL_USE_ASAN", "AFL_USE_MSAN", "AFL_USE_TRACE_PC",
117+
"AFL_USE_UBSAN", "AFL_USE_TSAN", "AFL_USE_CFISAN", "AFL_USE_LSAN",
118+
"AFL_WINE_PATH", "AFL_NO_SNAPSHOT", "AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN",
119+
"AFL_USE_QASAN", "AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", NULL
120120

121121
};
122122

src/afl-fuzz-bitmap.c

Lines changed: 67 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -527,12 +527,24 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
527527

528528
#ifndef SIMPLE_FILES
529529

530-
queue_fn = alloc_printf(
531-
"%s/queue/id:%06u,%s%s%s", afl->out_dir, afl->queued_items,
532-
describe_op(afl, new_bits + is_timeout,
533-
NAME_MAX - strlen("id:000000,")),
534-
afl->file_extension ? "." : "",
535-
afl->file_extension ? (const char *)afl->file_extension : "");
530+
if (!afl->afl_env.afl_sha1_filenames) {
531+
532+
queue_fn = alloc_printf(
533+
"%s/queue/id:%06u,%s%s%s", afl->out_dir, afl->queued_items,
534+
describe_op(afl, new_bits + is_timeout,
535+
NAME_MAX - strlen("id:000000,")),
536+
afl->file_extension ? "." : "",
537+
afl->file_extension ? (const char *)afl->file_extension : "");
538+
539+
} else {
540+
541+
const char *hex = sha1_hex(mem, len);
542+
queue_fn = alloc_printf(
543+
"%s/queue/%s%s%s", afl->out_dir, hex, afl->file_extension ? "." : "",
544+
afl->file_extension ? (const char *)afl->file_extension : "");
545+
ck_free((char *)hex);
546+
547+
}
536548

537549
#else
538550

@@ -542,10 +554,14 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
542554
afl->file_extension ? (const char *)afl->file_extension : "");
543555

544556
#endif /* ^!SIMPLE_FILES */
545-
fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
546-
if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", queue_fn); }
547-
ck_write(fd, mem, len, queue_fn);
548-
close(fd);
557+
fd = permissive_create(afl, queue_fn);
558+
if (likely(fd >= 0)) {
559+
560+
ck_write(fd, mem, len, queue_fn);
561+
close(fd);
562+
563+
}
564+
549565
add_to_queue(afl, queue_fn, len, 0);
550566

551567
if (unlikely(afl->fuzz_mode) &&
@@ -743,11 +759,23 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
743759

744760
#ifndef SIMPLE_FILES
745761

746-
snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s%s%s", afl->out_dir,
747-
afl->saved_hangs,
748-
describe_op(afl, 0, NAME_MAX - strlen("id:000000,")),
749-
afl->file_extension ? "." : "",
750-
afl->file_extension ? (const char *)afl->file_extension : "");
762+
if (!afl->afl_env.afl_sha1_filenames) {
763+
764+
snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s%s%s", afl->out_dir,
765+
afl->saved_hangs,
766+
describe_op(afl, 0, NAME_MAX - strlen("id:000000,")),
767+
afl->file_extension ? "." : "",
768+
afl->file_extension ? (const char *)afl->file_extension : "");
769+
770+
} else {
771+
772+
const char *hex = sha1_hex(mem, len);
773+
snprintf(fn, PATH_MAX, "%s/hangs/%s%s%s", afl->out_dir, hex,
774+
afl->file_extension ? "." : "",
775+
afl->file_extension ? (const char *)afl->file_extension : "");
776+
ck_free((char *)hex);
777+
778+
}
751779

752780
#else
753781

@@ -799,11 +827,23 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
799827

800828
#ifndef SIMPLE_FILES
801829

802-
snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s",
803-
afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal,
804-
describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,")),
805-
afl->file_extension ? "." : "",
806-
afl->file_extension ? (const char *)afl->file_extension : "");
830+
if (!afl->afl_env.afl_sha1_filenames) {
831+
832+
snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s",
833+
afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal,
834+
describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,")),
835+
afl->file_extension ? "." : "",
836+
afl->file_extension ? (const char *)afl->file_extension : "");
837+
838+
} else {
839+
840+
const char *hex = sha1_hex(mem, len);
841+
snprintf(fn, PATH_MAX, "%s/crashes/%s%s%s", afl->out_dir, hex,
842+
afl->file_extension ? "." : "",
843+
afl->file_extension ? (const char *)afl->file_extension : "");
844+
ck_free((char *)hex);
845+
846+
}
807847

808848
#else
809849

@@ -873,10 +913,13 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
873913
/* If we're here, we apparently want to save the crash or hang
874914
test case, too. */
875915

876-
fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
877-
if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", fn); }
878-
ck_write(fd, mem, len, fn);
879-
close(fd);
916+
fd = permissive_create(afl, fn);
917+
if (fd >= 0) {
918+
919+
ck_write(fd, mem, len, fn);
920+
close(fd);
921+
922+
}
880923

881924
#ifdef __linux__
882925
if (afl->fsrv.nyx_mode && fault == FSRV_RUN_CRASH) {

src/afl-fuzz-init.c

Lines changed: 53 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,14 +1190,27 @@ void perform_dry_run(afl_state_t *afl) {
11901190

11911191
#ifndef SIMPLE_FILES
11921192

1193-
snprintf(
1194-
crash_fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s%s",
1195-
afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal,
1196-
describe_op(
1197-
afl, 0,
1198-
NAME_MAX - strlen("id:000000,sig:00,") - strlen(use_name)),
1199-
use_name, afl->file_extension ? "." : "",
1200-
afl->file_extension ? (const char *)afl->file_extension : "");
1193+
if (!afl->afl_env.afl_sha1_filenames) {
1194+
1195+
snprintf(
1196+
crash_fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s%s",
1197+
afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal,
1198+
describe_op(
1199+
afl, 0,
1200+
NAME_MAX - strlen("id:000000,sig:00,") - strlen(use_name)),
1201+
use_name, afl->file_extension ? "." : "",
1202+
afl->file_extension ? (const char *)afl->file_extension : "");
1203+
1204+
} else {
1205+
1206+
const char *hex = sha1_hex(use_mem, read_len);
1207+
snprintf(
1208+
crash_fn, PATH_MAX, "%s/crashes/%s%s%s", afl->out_dir, hex,
1209+
afl->file_extension ? "." : "",
1210+
afl->file_extension ? (const char *)afl->file_extension : "");
1211+
ck_free((char *)hex);
1212+
1213+
}
12011214

12021215
#else
12031216

@@ -1518,10 +1531,23 @@ void pivot_inputs(afl_state_t *afl) {
15181531

15191532
}
15201533

1521-
nfn = alloc_printf(
1522-
"%s/queue/id:%06u,time:0,execs:%llu,orig:%s%s%s", afl->out_dir, id,
1523-
afl->fsrv.total_execs, use_name, afl->file_extension ? "." : "",
1524-
afl->file_extension ? (const char *)afl->file_extension : "");
1534+
if (!afl->afl_env.afl_sha1_filenames) {
1535+
1536+
nfn = alloc_printf(
1537+
"%s/queue/id:%06u,time:0,execs:%llu,orig:%s%s%s", afl->out_dir, id,
1538+
afl->fsrv.total_execs, use_name, afl->file_extension ? "." : "",
1539+
afl->file_extension ? (const char *)afl->file_extension : "");
1540+
1541+
} else {
1542+
1543+
const char *hex = sha1_hex_for_file(q->fname, q->len);
1544+
nfn = alloc_printf(
1545+
"%s/queue/%s%s%s", afl->out_dir, hex,
1546+
afl->file_extension ? "." : "",
1547+
afl->file_extension ? (const char *)afl->file_extension : "");
1548+
ck_free((char *)hex);
1549+
1550+
}
15251551

15261552
u8 *pos = strrchr(nfn, '/');
15271553
no_spaces(pos + 30);
@@ -1738,30 +1764,31 @@ double get_runnable_processes(void) {
17381764

17391765
void nuke_resume_dir(afl_state_t *afl) {
17401766

1741-
u8 *fn;
1767+
u8 *const case_prefix = afl->afl_env.afl_sha1_filenames ? "" : CASE_PREFIX;
1768+
u8 *fn;
17421769

17431770
fn = alloc_printf("%s/_resume/.state/deterministic_done", afl->out_dir);
1744-
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1771+
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
17451772
ck_free(fn);
17461773

17471774
fn = alloc_printf("%s/_resume/.state/auto_extras", afl->out_dir);
17481775
if (delete_files(fn, "auto_")) { goto dir_cleanup_failed; }
17491776
ck_free(fn);
17501777

17511778
fn = alloc_printf("%s/_resume/.state/redundant_edges", afl->out_dir);
1752-
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1779+
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
17531780
ck_free(fn);
17541781

17551782
fn = alloc_printf("%s/_resume/.state/variable_behavior", afl->out_dir);
1756-
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1783+
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
17571784
ck_free(fn);
17581785

17591786
fn = alloc_printf("%s/_resume/.state", afl->out_dir);
17601787
if (rmdir(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
17611788
ck_free(fn);
17621789

17631790
fn = alloc_printf("%s/_resume", afl->out_dir);
1764-
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1791+
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
17651792
ck_free(fn);
17661793

17671794
return;
@@ -1778,8 +1805,9 @@ void nuke_resume_dir(afl_state_t *afl) {
17781805

17791806
static void handle_existing_out_dir(afl_state_t *afl) {
17801807

1781-
FILE *f;
1782-
u8 *fn = alloc_printf("%s/fuzzer_stats", afl->out_dir);
1808+
u8 *const case_prefix = afl->afl_env.afl_sha1_filenames ? "" : CASE_PREFIX;
1809+
FILE *f;
1810+
u8 *fn = alloc_printf("%s/fuzzer_stats", afl->out_dir);
17831811

17841812
/* See if the output directory is locked. If yes, bail out. If not,
17851813
create a lock that will persist for the lifetime of the process
@@ -1901,19 +1929,19 @@ static void handle_existing_out_dir(afl_state_t *afl) {
19011929
/* Next, we need to clean up <afl->out_dir>/queue/.state/ subdirectories: */
19021930

19031931
fn = alloc_printf("%s/queue/.state/deterministic_done", afl->out_dir);
1904-
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1932+
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
19051933
ck_free(fn);
19061934

19071935
fn = alloc_printf("%s/queue/.state/auto_extras", afl->out_dir);
19081936
if (delete_files(fn, "auto_")) { goto dir_cleanup_failed; }
19091937
ck_free(fn);
19101938

19111939
fn = alloc_printf("%s/queue/.state/redundant_edges", afl->out_dir);
1912-
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1940+
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
19131941
ck_free(fn);
19141942

19151943
fn = alloc_printf("%s/queue/.state/variable_behavior", afl->out_dir);
1916-
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1944+
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
19171945
ck_free(fn);
19181946

19191947
/* Then, get rid of the .state subdirectory itself (should be empty by now)
@@ -1924,7 +1952,7 @@ static void handle_existing_out_dir(afl_state_t *afl) {
19241952
ck_free(fn);
19251953

19261954
fn = alloc_printf("%s/queue", afl->out_dir);
1927-
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1955+
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
19281956
ck_free(fn);
19291957

19301958
/* All right, let's do <afl->out_dir>/crashes/id:* and
@@ -1971,7 +1999,7 @@ static void handle_existing_out_dir(afl_state_t *afl) {
19711999
#ifdef AFL_PERSISTENT_RECORD
19722000
delete_files(fn, RECORD_PREFIX);
19732001
#endif
1974-
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
2002+
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
19752003
ck_free(fn);
19762004

19772005
fn = alloc_printf("%s/hangs", afl->out_dir);
@@ -2006,7 +2034,7 @@ static void handle_existing_out_dir(afl_state_t *afl) {
20062034
#ifdef AFL_PERSISTENT_RECORD
20072035
delete_files(fn, RECORD_PREFIX);
20082036
#endif
2009-
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
2037+
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
20102038
ck_free(fn);
20112039

20122040
/* And now, for some finishing touches. */

src/afl-fuzz-queue.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -371,9 +371,8 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
371371
s32 fd;
372372

373373
if (unlikely(afl->afl_env.afl_disable_redundant)) { q->disabled = 1; }
374-
fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
375-
if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
376-
close(fd);
374+
fd = permissive_create(afl, fn);
375+
if (fd >= 0) { close(fd); }
377376

378377
} else {
379378

src/afl-fuzz-state.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
626626

627627
}
628628

629+
} else if (!strncmp(env, "AFL_SHA1_FILENAMES",
630+
631+
afl_environment_variable_len)) {
632+
633+
afl->afl_env.afl_sha1_filenames =
634+
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
635+
629636
}
630637

631638
} else {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy