From 6ed0a2b4aa0c22f95ba723cfda5b1fb79a224bc8 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 10 Jun 2024 18:22:06 +0200 Subject: fast resume setup detection --- src/afl-fuzz-stats.c | 8 +++- src/afl-fuzz.c | 100 +++++++++++++++++++++++++++++++++++++++----------- src/afl-performance.c | 2 + 3 files changed, 88 insertions(+), 22 deletions(-) diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 3a71e158..a20c46d0 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -76,7 +76,13 @@ char *get_fuzzing_state(afl_state_t *afl) { void write_setup_file(afl_state_t *afl, u32 argc, char **argv) { - u8 fn[PATH_MAX]; + u8 fn[PATH_MAX], fn2[PATH_MAX]; + + snprintf(fn2, PATH_MAX, "%s/target_hash", afl->out_dir); + FILE *f2 = create_ffile(fn2); + fprintf(f2, "%p\n", (void *)get_binary_hash(afl->fsrv.target_path)); + fclose(f2); + snprintf(fn, PATH_MAX, "%s/fuzzer_setup", afl->out_dir); FILE *f = create_ffile(fn); u32 i; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index a7ddef6e..bb05c9c6 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2101,45 +2101,105 @@ int main(int argc, char **argv_orig, char **envp) { } - write_setup_file(afl, argc, argv); - setup_cmdline_file(afl, argv + optind); + check_binary(afl, argv[optind]); - read_testcases(afl, NULL); - // read_foreign_testcases(afl, 1); for the moment dont do this - OKF("Loaded a total of %u seeds.", afl->queued_items); + u64 prev_target_hash = 0; + s32 fast_resume = 0, fr_fd = -1; + + if (afl->in_place_resume) { - pivot_inputs(afl); + u8 fn[PATH_MAX], buf[32]; + snprintf(fn, PATH_MAX, "%s/target_hash", afl->out_dir); + fr_fd = open(fn, O_RDONLY); + if (fr_fd >= 0) { - if (!afl->timeout_given) { find_timeout(afl); } // only for resumes! + if (read(fr_fd, buf, 32) >= 16) { - if (afl->afl_env.afl_tmpdir && !afl->in_place_resume) { + sscanf(buf, "%p", (void**)&prev_target_hash); - char tmpfile[PATH_MAX]; + } - if (afl->file_extension) { + close(fr_fd); - snprintf(tmpfile, PATH_MAX, "%s/.cur_input.%s", afl->tmp_dir, - afl->file_extension); + } + + } + + + write_setup_file(afl, argc, argv); + + if (afl->in_place_resume) { + + u64 target_hash = get_binary_hash(afl->fsrv.target_path); + + if (!target_hash || prev_target_hash != target_hash) { + + ACTF("Target binary is different, cannot perform FAST RESUME!"); } else { - snprintf(tmpfile, PATH_MAX, "%s/.cur_input", afl->tmp_dir); + u8 fn[PATH_MAX]; + snprintf(fn, PATH_MAX, "%s/fastresume.bin", afl->out_dir); + if ((fr_fd = open(fn, O_RDONLY)) >= 0) { + + OKF("Performing FAST RESUME"); + // fast_resume = 1; + + } else { + + ACTF("fastresume.bin not found, cannot perform FAST RESUME!"); + + } } - /* there is still a race condition here, but well ... */ - if (access(tmpfile, F_OK) != -1) { + } - FATAL( - "AFL_TMPDIR already has an existing temporary input file: %s - if " - "this is not from another instance, then just remove the file.", - tmpfile); + if (fast_resume) { + + // XXX + + } else { + + read_testcases(afl, NULL); + + pivot_inputs(afl); + + if (!afl->timeout_given) { find_timeout(afl); } // only for resumes! + + if (afl->afl_env.afl_tmpdir && !afl->in_place_resume) { + + char tmpfile[PATH_MAX]; + + if (afl->file_extension) { + + snprintf(tmpfile, PATH_MAX, "%s/.cur_input.%s", afl->tmp_dir, + afl->file_extension); + + } else { + + snprintf(tmpfile, PATH_MAX, "%s/.cur_input", afl->tmp_dir); + + } + + /* there is still a race condition here, but well ... */ + if (access(tmpfile, F_OK) != -1) { + + FATAL( + "AFL_TMPDIR already has an existing temporary input file: %s - if " + "this is not from another instance, then just remove the file.", + tmpfile); + + } } } + // read_foreign_testcases(afl, 1); for the moment dont do this + OKF("Loaded a total of %u seeds.", afl->queued_items); + /* If we don't have a file name chosen yet, use a safe default. */ if (!afl->fsrv.out_file) { @@ -2196,8 +2256,6 @@ int main(int argc, char **argv_orig, char **envp) { } - check_binary(afl, argv[optind]); - #ifdef AFL_PERSISTENT_RECORD if (unlikely(afl->fsrv.persistent_record)) { diff --git a/src/afl-performance.c b/src/afl-performance.c index e8ece6b5..b824fd35 100644 --- a/src/afl-performance.c +++ b/src/afl-performance.c @@ -99,11 +99,13 @@ inline u64 hash64(u8 *key, u32 len, u64 seed) { u64 get_binary_hash(u8 *fn) { + if (!fn) { return 0; } int fd = open(fn, O_RDONLY); if (fd < 0) { PFATAL("Unable to open '%s'", fn); } struct stat st; if (fstat(fd, &st) < 0) { PFATAL("Unable to fstat '%s'", fn); } u32 f_len = st.st_size; + if (!f_len) { return 0; } u8 *f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0); if (f_data == MAP_FAILED) { PFATAL("Unable to mmap file '%s'", fn); } close(fd); -- cgit 1.4.1 From dd762726dc7055f4b1c48da2ee1b22ff6fdde35e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 12 Jun 2024 09:10:35 +0200 Subject: fastresume implementation --- include/afl-fuzz.h | 13 ++- src/afl-fuzz-init.c | 2 +- src/afl-fuzz-queue.c | 7 +- src/afl-fuzz.c | 224 +++++++++++++++++++++++++++++++++++++++++---------- 4 files changed, 189 insertions(+), 57 deletions(-) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index e3e4e246..3f3d6da0 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -236,7 +236,6 @@ struct queue_entry { custom, /* Marker for custom mutators */ stats_mutated; /* stats: # of mutations performed */ - u8 *trace_mini; /* Trace bytes, if kept */ u32 tc_ref; /* Trace bytes ref count */ #ifdef INTROSPECTION @@ -246,13 +245,11 @@ struct queue_entry { double perf_score, /* performance score */ weight; - u8 *testcase_buf; /* The testcase buffer, if loaded. */ - - u8 *cmplog_colorinput; /* the result buf of colorization */ - struct tainted *taint; /* Taint information from CmpLog */ - - struct queue_entry *mother; /* queue entry this based on */ - + struct queue_entry *mother; /* queue entry this based on */ + u8 *trace_mini; /* Trace bytes, if kept */ + u8 *testcase_buf; /* The testcase buffer, if loaded. */ + u8 *cmplog_colorinput; /* the result buf of colorization */ + struct tainted *taint; /* Taint information from CmpLog */ struct skipdet_entry *skipdet_e; }; diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 7310e49f..98de26dd 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1019,7 +1019,7 @@ void perform_dry_run(afl_state_t *afl) { } - if (!q->was_fuzzed) { + if (unlikely(!q->was_fuzzed)) { q->was_fuzzed = 1; afl->reinit_table = 1; diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index f4cb930d..a28172f9 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -401,7 +401,7 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) { } else { - if (unlink(fn)) { PFATAL("Unable to remove '%s'", fn); } + if (unlink(fn)) { /*PFATAL("Unable to remove '%s'", fn);*/ } } @@ -699,12 +699,11 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { void destroy_queue(afl_state_t *afl) { - u32 i; + u32 i; + struct queue_entry *q; for (i = 0; i < afl->queued_items; i++) { - struct queue_entry *q; - q = afl->queue_buf[i]; ck_free(q->fname); ck_free(q->trace_mini); diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index bb05c9c6..d8be5721 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -181,7 +181,7 @@ static void usage(u8 *argv0, int more_help) { "it.\n" " if using QEMU/FRIDA or the fuzzing target is " "compiled\n" - " for CmpLog then use '-c 0'. To disable Cmplog use '-c " + " for CmpLog then use '-c 0'. To disable CMPLOG use '-c " "-'.\n" " -l cmplog_opts - CmpLog configuration values (e.g. \"2ATR\"):\n" " 1=small files, 2=larger files (default), 3=all " @@ -2116,7 +2116,7 @@ int main(int argc, char **argv_orig, char **envp) { if (read(fr_fd, buf, 32) >= 16) { - sscanf(buf, "%p", (void**)&prev_target_hash); + sscanf(buf, "%p", (void **)&prev_target_hash); } @@ -2126,7 +2126,6 @@ int main(int argc, char **argv_orig, char **envp) { } - write_setup_file(afl, argc, argv); if (afl->in_place_resume) { @@ -2143,8 +2142,23 @@ int main(int argc, char **argv_orig, char **envp) { snprintf(fn, PATH_MAX, "%s/fastresume.bin", afl->out_dir); if ((fr_fd = open(fn, O_RDONLY)) >= 0) { - OKF("Performing FAST RESUME"); - // fast_resume = 1; + u8 ver_string[8]; + u64 *ver = (u64 *)ver_string; + u64 expect_ver = + afl->shm.cmplog_mode + (sizeof(struct queue_entry) << 1); + + if (read(fr_fd, ver_string, sizeof(ver_string)) != sizeof(ver_string)) + WARNF("Emtpy fastresume.bin, ignoring, cannot perform FAST RESUME"); + else if (expect_ver != *ver) + WARNF( + "Different AFL++ version or feature usage, cannot perform FAST " + "RESUME"); + else { + + OKF("Will perform FAST RESUME"); + fast_resume = 1; + + } } else { @@ -2156,42 +2170,34 @@ int main(int argc, char **argv_orig, char **envp) { } - if (fast_resume) { + read_testcases(afl, NULL); - // XXX + pivot_inputs(afl); - } else { - - read_testcases(afl, NULL); - - pivot_inputs(afl); + if (!afl->timeout_given) { find_timeout(afl); } // only for resumes! - if (!afl->timeout_given) { find_timeout(afl); } // only for resumes! + if (afl->afl_env.afl_tmpdir && !afl->in_place_resume) { - if (afl->afl_env.afl_tmpdir && !afl->in_place_resume) { + char tmpfile[PATH_MAX]; - char tmpfile[PATH_MAX]; + if (afl->file_extension) { - if (afl->file_extension) { + snprintf(tmpfile, PATH_MAX, "%s/.cur_input.%s", afl->tmp_dir, + afl->file_extension); - snprintf(tmpfile, PATH_MAX, "%s/.cur_input.%s", afl->tmp_dir, - afl->file_extension); - - } else { - - snprintf(tmpfile, PATH_MAX, "%s/.cur_input", afl->tmp_dir); + } else { - } + snprintf(tmpfile, PATH_MAX, "%s/.cur_input", afl->tmp_dir); - /* there is still a race condition here, but well ... */ - if (access(tmpfile, F_OK) != -1) { + } - FATAL( - "AFL_TMPDIR already has an existing temporary input file: %s - if " - "this is not from another instance, then just remove the file.", - tmpfile); + /* there is still a race condition here, but well ... */ + if (access(tmpfile, F_OK) != -1) { - } + FATAL( + "AFL_TMPDIR already has an existing temporary input file: %s - if " + "this is not from another instance, then just remove the file.", + tmpfile); } @@ -2474,7 +2480,7 @@ int main(int argc, char **argv_orig, char **envp) { } - OKF("Cmplog forkserver successfully started"); + OKF("CMPLOG forkserver successfully started"); } @@ -2512,29 +2518,102 @@ int main(int argc, char **argv_orig, char **envp) { dedup_extras(afl); if (afl->extras_cnt) { OKF("Loaded a total of %u extras.", afl->extras_cnt); } - // after we have the correct bitmap size we can read the bitmap -B option - // and set the virgin maps - if (afl->in_bitmap) { + if (unlikely(fast_resume)) { - read_bitmap(afl->in_bitmap, afl->virgin_bits, afl->fsrv.map_size); + u64 resume_start = get_cur_time_us(); + // if we get here then we should abort on errors + ck_read(fr_fd, afl->virgin_bits, afl->fsrv.map_size, "virgin_bits"); + ck_read(fr_fd, afl->virgin_tmout, afl->fsrv.map_size, "virgin_tmout"); + ck_read(fr_fd, afl->virgin_crash, afl->fsrv.map_size, "virgin_crash"); + ck_read(fr_fd, afl->var_bytes, afl->fsrv.map_size, "var_bytes"); - } else { + u8 res[1] = {0}; + u8 *o_start = (u8 *)&(afl->queue_buf[0]->colorized); + u8 *o_end = (u8 *)&(afl->queue_buf[0]->mother); + u32 r = 8 + afl->fsrv.map_size * 4; + u32 q_len = o_end - o_start; + u32 m_len = (afl->fsrv.map_size >> 3); + struct queue_entry *q; - memset(afl->virgin_bits, 255, map_size); + for (u32 i = 0; i < afl->queued_items; i++) { - } + q = afl->queue_buf[i]; + ck_read(fr_fd, (u8 *)&(q->colorized), q_len, "queue data"); + ck_read(fr_fd, res, 1, "check map"); + if (res[0]) { - memset(afl->virgin_tmout, 255, map_size); - memset(afl->virgin_crash, 255, map_size); + q->trace_mini = ck_alloc(m_len); + ck_read(fr_fd, q->trace_mini, m_len, "trace_mini"); + r += q_len + m_len + 1; - if (likely(!afl->afl_env.afl_no_startup_calibration)) { + } else { + + r += q_len + 1; + + } + + afl->total_bitmap_size += q->bitmap_size; + ++afl->total_bitmap_entries; + update_bitmap_score(afl, q); + + if (q->was_fuzzed) { --afl->pending_not_fuzzed; } + + if (q->disabled) { + + if (!q->was_fuzzed) { --afl->pending_not_fuzzed; } + --afl->active_items; + + } - perform_dry_run(afl); + if (q->var_behavior) { ++afl->queued_variable; } + if (q->favored) { + + ++afl->queued_favored; + if (!q->was_fuzzed) { ++afl->pending_favored; } + + } + + } + + u8 buf[4]; + if (read(fr_fd, buf, 3) > 0) { + + FATAL("invalid trailing data in fastresume.bin"); + + } + + OKF("Successfully loaded fastresume.bin (%u bytes)!", r); + close(fr_fd); + afl->reinit_table = 1; + update_calibration_time(afl, &resume_start); } else { - ACTF("skipping initial seed calibration due option override!"); - usleep(1000); + // after we have the correct bitmap size we can read the bitmap -B option + // and set the virgin maps + if (afl->in_bitmap) { + + read_bitmap(afl->in_bitmap, afl->virgin_bits, afl->fsrv.map_size); + + } else { + + memset(afl->virgin_bits, 255, map_size); + + } + + memset(afl->virgin_tmout, 255, map_size); + memset(afl->virgin_crash, 255, map_size); + + if (likely(!afl->afl_env.afl_no_startup_calibration)) { + + perform_dry_run(afl); + + } else { + + ACTF("Skipping initial seed calibration due option override!"); + usleep(1000); + + } } @@ -3125,6 +3204,63 @@ stop_fuzzing: fclose(afl->fsrv.det_plot_file); #endif + /* create fastresume.bin */ + u8 fr[PATH_MAX]; + snprintf(fr, PATH_MAX, "%s/fastresume.bin", afl->out_dir); + if ((fr_fd = open(fr, O_WRONLY | O_TRUNC | O_CREAT, DEFAULT_PERMISSION)) >= + 0) { + + u8 ver_string[8]; + u32 w = 0; + u64 *ver = (u64 *)ver_string; + *ver = afl->shm.cmplog_mode + (sizeof(struct queue_entry) << 1); + + w += write(fr_fd, ver_string, sizeof(ver_string)); + + w += write(fr_fd, afl->virgin_bits, afl->fsrv.map_size); + w += write(fr_fd, afl->virgin_tmout, afl->fsrv.map_size); + w += write(fr_fd, afl->virgin_crash, afl->fsrv.map_size); + w += write(fr_fd, afl->var_bytes, afl->fsrv.map_size); + + u8 on[1] = {1}, off[1] = {0}; + u8 *o_start = (u8 *)&(afl->queue_buf[0]->colorized); + u8 *o_end = (u8 *)&(afl->queue_buf[0]->mother); + u32 q_len = o_end - o_start; + u32 m_len = (afl->fsrv.map_size >> 3); + struct queue_entry *q; + + afl->pending_not_fuzzed = afl->queued_items; + afl->active_items = afl->queued_items; + + for (u32 i = 0; i < afl->queued_items; i++) { + + q = afl->queue_buf[i]; + ck_write(fr_fd, (u8 *)&(q->colorized), q_len, "queue data"); + if (!q->trace_mini) { + + ck_write(fr_fd, off, 1, "no_mini"); + w += q_len + 1; + + } else { + + ck_write(fr_fd, on, 1, "yes_mini"); + ck_write(fr_fd, q->trace_mini, m_len, "trace_mini"); + w += q_len + m_len + 1; + + } + + } + + close(fr_fd); + afl->var_byte_count = count_bytes(afl, afl->var_bytes); + OKF("Written fastresume.bin with %u bytes!", w); + + } else { + + WARNF("Could not create fastresume.bin"); + + } + destroy_queue(afl); destroy_extras(afl); destroy_custom_mutators(afl); -- cgit 1.4.1 From b5e0fff6b9ee1260fc3753af0e441606cfe853ff Mon Sep 17 00:00:00 2001 From: Kuan-Wei Chiu Date: Fri, 14 Jun 2024 09:44:36 +0800 Subject: Fix signed integer overflow in radamsa When UBSan was enabled and 'make test' was executed, the following runtime error was observed: libradamsa.c:26055:29: runtime error: left shift of 16777215 by 8 places cannot be represented in type 'int' This issue was caused by a left shift operation on a signed integer. The fix involved changing the integer literal to an unsigned integer by adding a 'U' suffix, ensuring the left shift operation produces the correct value without overflow. Fixes: 8178f4df ("remove radamsa, add radamsa custom mutator") --- custom_mutators/radamsa/libradamsa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_mutators/radamsa/libradamsa.c b/custom_mutators/radamsa/libradamsa.c index e6838752..1dcf91d8 100644 --- a/custom_mutators/radamsa/libradamsa.c +++ b/custom_mutators/radamsa/libradamsa.c @@ -3707,7 +3707,7 @@ typedef intptr_t wdiff; 1024 * 1024 * 8 /* static malloc'd heap size if used as a library */ #define FBITS 24 /* bits in fixnum, on the way to 24 and beyond */ #define FMAX \ - ((1 << FBITS) - 1) /* maximum fixnum (and most negative fixnum) \ + ((1U << FBITS) - 1) /* maximum fixnum (and most negative fixnum) \ */ #define MAXOBJ 0xffff /* max words in tuple including header */ #define MAXPAYL \ -- cgit 1.4.1 From de176a10bc225e5fa2e7dafdd784f568cc1ca5e7 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 17 Jun 2024 09:31:36 +0200 Subject: nit --- src/afl-fuzz.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index a7ddef6e..cc58b4d1 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -960,7 +960,11 @@ int main(int argc, char **argv_orig, char **envp) { } - if (afl->fsrv.mem_limit < 5) { FATAL("Dangerously low value of -m"); } + if (afl->fsrv.mem_limit && afl->fsrv.mem_limit < 5) { + + FATAL("Dangerously low value of -m"); + + } if (sizeof(rlim_t) == 4 && afl->fsrv.mem_limit > 2000) { -- cgit 1.4.1 From a6e42d98d9d3e936dc74729f17ab1208d477c944 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 18 Jun 2024 15:09:11 +0200 Subject: llvm 19 fixes --- instrumentation/SanitizerCoverageLTO.so.cc | 29 ++++++++++++----- instrumentation/SanitizerCoveragePCGUARD.so.cc | 44 ++++++++++++++++++-------- 2 files changed, 52 insertions(+), 21 deletions(-) diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index a09f28a9..63ea71c1 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -214,8 +214,12 @@ class ModuleSanitizerCoverageLTO void SetNoSanitizeMetadata(Instruction *I) { +#if LLVM_VERSION_MAJOR >= 19 + I->setNoSanitizeMetadata(); +#else I->setMetadata(I->getModule()->getMDKindID("nosanitize"), MDNode::get(*C, None)); +#endif } @@ -225,7 +229,7 @@ class ModuleSanitizerCoverageLTO FunctionCallee SanCovTracePCIndir; FunctionCallee SanCovTracePC /*, SanCovTracePCGuard*/; Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy, - *Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy; + *Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy, *PtrTy; Module *CurModule; std::string CurModuleUniqueId; Triple TargetTriple; @@ -416,6 +420,7 @@ bool ModuleSanitizerCoverageLTO::instrumentModule( Int16Ty = IRB.getInt16Ty(); Int8Ty = IRB.getInt8Ty(); Int1Ty = IRB.getInt1Ty(); + PtrTy = PointerType::getUnqual(*C); /* AFL++ START */ char *ptr; @@ -1350,7 +1355,7 @@ void ModuleSanitizerCoverageLTO::instrumentFunction( Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) { if (F.empty()) return; - if (F.getName().find(".module_ctor") != std::string::npos) + if (F.getName().contains(".module_ctor")) return; // Should not instrument sanitizer init functions. #if LLVM_VERSION_MAJOR >= 18 if (F.getName().starts_with("__sanitizer_")) @@ -1372,6 +1377,10 @@ void ModuleSanitizerCoverageLTO::instrumentFunction( if (F.hasPersonalityFn() && isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) return; + if (F.hasFnAttribute(Attribute::NoSanitizeCoverage)) return; +#if LLVM_VERSION_MAJOR >= 19 + if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) return; +#endif // if (Allowlist && !Allowlist->inSection("coverage", "fun", F.getName())) // return; // if (Blocklist && Blocklist->inSection("coverage", "fun", F.getName())) @@ -2023,16 +2032,20 @@ GlobalVariable *ModuleSanitizerCoverageLTO::CreatePCArray( if (&F.getEntryBlock() == AllBlocks[i]) { - PCs.push_back((Constant *)IRB.CreatePointerCast(&F, IntptrPtrTy)); - PCs.push_back((Constant *)IRB.CreateIntToPtr( - ConstantInt::get(IntptrTy, 1), IntptrPtrTy)); + PCs.push_back((Constant *)IRB.CreatePointerCast(&F, PtrTy)); + PCs.push_back( + (Constant *)IRB.CreateIntToPtr(ConstantInt::get(IntptrTy, 1), PtrTy)); } else { PCs.push_back((Constant *)IRB.CreatePointerCast( - BlockAddress::get(AllBlocks[i]), IntptrPtrTy)); - PCs.push_back((Constant *)IRB.CreateIntToPtr( - ConstantInt::get(IntptrTy, 0), IntptrPtrTy)); + BlockAddress::get(AllBlocks[i]), PtrTy)); +#if LLVM_VERSION_MAJOR >= 16 + PCs.push_back(Constant::getNullValue(PtrTy)); +#else + PCs.push_back( + (Constant *)IRB.CreateIntToPtr(ConstantInt::get(IntptrTy, 0), PtrTy)); +#endif } diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index 01881f28..49fe904b 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -161,7 +161,9 @@ class ModuleSanitizerCoverageAFL void SetNoSanitizeMetadata(Instruction *I) { -#if LLVM_VERSION_MAJOR >= 16 +#if LLVM_VERSION_MAJOR >= 19 + I->setNoSanitizeMetadata(); +#elif LLVM_VERSION_MAJOR >= 16 I->setMetadata(LLVMContext::MD_nosanitize, MDNode::get(*C, std::nullopt)); #else I->setMetadata(I->getModule()->getMDKindID("nosanitize"), @@ -179,7 +181,7 @@ class ModuleSanitizerCoverageAFL FunctionCallee SanCovTraceSwitchFunction; GlobalVariable *SanCovLowestStack; Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy, - *Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy; + *Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy, *PtrTy; Module *CurModule; std::string CurModuleUniqueId; Triple TargetTriple; @@ -272,13 +274,19 @@ std::pair ModuleSanitizerCoverageAFL::CreateSecStartEnd( if (!TargetTriple.isOSBinFormatCOFF()) return std::make_pair(SecStart, SecEnd); - // Account for the fact that on windows-msvc __start_* symbols actually - // point to a uint64_t before the start of the array. + // Account for the fact that on windows-msvc __start_* symbols actually + // point to a uint64_t before the start of the array. +#if LLVM_VERSION_MAJOR >= 19 + auto GEP = + IRB.CreatePtrAdd(SecStart, ConstantInt::get(IntptrTy, sizeof(uint64_t))); + return std::make_pair(GEP, SecEnd); +#else auto SecStartI8Ptr = IRB.CreatePointerCast(SecStart, Int8PtrTy); auto GEP = IRB.CreateGEP(Int8Ty, SecStartI8Ptr, ConstantInt::get(IntptrTy, sizeof(uint64_t))); return std::make_pair(IRB.CreatePointerCast(GEP, PointerType::getUnqual(Ty)), SecEnd); +#endif } @@ -370,6 +378,7 @@ bool ModuleSanitizerCoverageAFL::instrumentModule( Int16Ty = IRB.getInt16Ty(); Int8Ty = IRB.getInt8Ty(); Int1Ty = IRB.getInt1Ty(); + PtrTy = PointerType::getUnqual(*C); LLVMContext &Ctx = M.getContext(); AFLMapPtr = @@ -572,7 +581,8 @@ void ModuleSanitizerCoverageAFL::instrumentFunction( if (F.empty()) return; if (!isInInstrumentList(&F, FMNAME)) return; - if (F.getName().find(".module_ctor") != std::string::npos) + // if (F.getName().find(".module_ctor") != std::string::npos) + if (F.getName().contains(".module_ctor")) return; // Should not instrument sanitizer init functions. #if LLVM_VERSION_MAJOR >= 18 if (F.getName().starts_with("__sanitizer_")) @@ -595,6 +605,9 @@ void ModuleSanitizerCoverageAFL::instrumentFunction( isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) return; if (F.hasFnAttribute(Attribute::NoSanitizeCoverage)) return; +#if LLVM_VERSION_MAJOR >= 19 + if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) return; +#endif if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge) SplitAllCriticalEdges( F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests()); @@ -692,16 +705,16 @@ GlobalVariable *ModuleSanitizerCoverageAFL::CreatePCArray( if (&F.getEntryBlock() == AllBlocks[i]) { - PCs.push_back((Constant *)IRB.CreatePointerCast(&F, IntptrPtrTy)); - PCs.push_back((Constant *)IRB.CreateIntToPtr( - ConstantInt::get(IntptrTy, 1), IntptrPtrTy)); + PCs.push_back((Constant *)IRB.CreatePointerCast(&F, PtrTy)); + PCs.push_back( + (Constant *)IRB.CreateIntToPtr(ConstantInt::get(IntptrTy, 1), PtrTy)); } else { PCs.push_back((Constant *)IRB.CreatePointerCast( - BlockAddress::get(AllBlocks[i]), IntptrPtrTy)); + BlockAddress::get(AllBlocks[i]), PtrTy)); #if LLVM_VERSION_MAJOR >= 16 - PCs.push_back(Constant::getNullValue(IntptrPtrTy)); + PCs.push_back(Constant::getNullValue(PtrTy)); #else PCs.push_back((Constant *)IRB.CreateIntToPtr( ConstantInt::get(IntptrTy, 0), IntptrPtrTy)); @@ -711,10 +724,10 @@ GlobalVariable *ModuleSanitizerCoverageAFL::CreatePCArray( } - auto *PCArray = CreateFunctionLocalArrayInSection(N * 2, F, IntptrPtrTy, - SanCovPCsSectionName); + auto *PCArray = + CreateFunctionLocalArrayInSection(N * 2, F, PtrTy, SanCovPCsSectionName); PCArray->setInitializer( - ConstantArray::get(ArrayType::get(IntptrPtrTy, N * 2), PCs)); + ConstantArray::get(ArrayType::get(PtrTy, N * 2), PCs)); PCArray->setConstant(true); return PCArray; @@ -822,7 +835,12 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage( StringRef FuncName = Callee->getName(); if (FuncName.compare(StringRef("__afl_coverage_interesting"))) continue; +#if LLVM_VERSION_MAJOR >= 20 + // test canary + InstrumentationIRBuilder IRB(callInst); +#else IRBuilder<> IRB(callInst); +#endif if (!FunctionGuardArray) { -- cgit 1.4.1 From 304e84502d9bd8a5ac33328ceb63235f42b887ad Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 18 Jun 2024 15:24:38 +0200 Subject: fast resume option --- docs/env_variables.md | 2 ++ include/afl-fuzz.h | 2 +- include/envs.h | 2 +- src/afl-fuzz-state.c | 7 +++++++ src/afl-fuzz.c | 12 ++++++++++-- 5 files changed, 21 insertions(+), 4 deletions(-) diff --git a/docs/env_variables.md b/docs/env_variables.md index 22e0ce0f..6db31df0 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -514,6 +514,8 @@ checks or alter some of the more exotic semantics of the tool: - `AFL_NO_SNAPSHOT` will advise afl-fuzz not to use the snapshot feature if the snapshot lkm is loaded. + - `AFL_NO_FASTRESUME` will not try to read or write a fast resume file. + - Setting `AFL_NO_UI` inhibits the UI altogether and just periodically prints some basic stats. This behavior is also automatically triggered when the output from afl-fuzz is redirected to a file or to a pipe. diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 3f3d6da0..6d03a74c 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -454,7 +454,7 @@ typedef struct afl_env_vars { afl_no_startup_calibration, afl_no_warn_instability, afl_post_process_keep_original, afl_crashing_seeds_as_new_crash, afl_final_sync, afl_ignore_seed_problems, afl_disable_redundant, - afl_sha1_filenames, afl_no_sync; + afl_sha1_filenames, afl_no_sync, afl_no_fastresume; u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path, *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload, diff --git a/include/envs.h b/include/envs.h index 45b080cb..928f4185 100644 --- a/include/envs.h +++ b/include/envs.h @@ -115,7 +115,7 @@ static char *afl_environment_variables[] = { "AFL_TRACE_PC", "AFL_USE_ASAN", "AFL_USE_MSAN", "AFL_USE_TRACE_PC", "AFL_USE_UBSAN", "AFL_USE_TSAN", "AFL_USE_CFISAN", "AFL_USE_LSAN", "AFL_WINE_PATH", "AFL_NO_SNAPSHOT", "AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN", - "AFL_USE_QASAN", "AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", NULL + "AFL_USE_QASAN", "AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", "AFL_NO_FASTRESUME", NULL }; diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index fbe6d32a..dd684a19 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -286,6 +286,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_no_sync = get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_NO_FASTRESUME", + + afl_environment_variable_len)) { + + afl->afl_env.afl_no_fastresume = + get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_CUSTOM_MUTATOR_ONLY", afl_environment_variable_len)) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index d8be5721..8fd3a407 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -335,6 +335,7 @@ static void usage(u8 *argv0, int more_help) { "AFL_STATSD_PORT: change default statsd port (default: 8125)\n" "AFL_STATSD_TAGS_FLAVOR: set statsd tags format (default: disable tags)\n" " suported formats: dogstatsd, librato, signalfx, influxdb\n" + "AFL_NO_FASTRESUME: do not read or write a fast resume file\n" "AFL_NO_SYNC: disables all syncing\n" "AFL_SYNC_TIME: sync time between fuzzing instances (in minutes)\n" "AFL_FINAL_SYNC: sync a final time when exiting (will delay the exit!)\n" @@ -2107,7 +2108,7 @@ int main(int argc, char **argv_orig, char **envp) { u64 prev_target_hash = 0; s32 fast_resume = 0, fr_fd = -1; - if (afl->in_place_resume) { + if (afl->in_place_resume && !afl->afl_env.afl_no_fastresume) { u8 fn[PATH_MAX], buf[32]; snprintf(fn, PATH_MAX, "%s/target_hash", afl->out_dir); @@ -2128,7 +2129,7 @@ int main(int argc, char **argv_orig, char **envp) { write_setup_file(afl, argc, argv); - if (afl->in_place_resume) { + if (afl->in_place_resume && !afl->afl_env.afl_no_fastresume) { u64 target_hash = get_binary_hash(afl->fsrv.target_path); @@ -2166,6 +2167,10 @@ int main(int argc, char **argv_orig, char **envp) { } + // If the fast resume file is not valid we will be unable to start, so + // we remove the file but keep the file descriptor open. + unlink(fn); + } } @@ -3204,9 +3209,11 @@ stop_fuzzing: fclose(afl->fsrv.det_plot_file); #endif + if (!afl->afl_env.afl_no_fastresume) { /* create fastresume.bin */ u8 fr[PATH_MAX]; snprintf(fr, PATH_MAX, "%s/fastresume.bin", afl->out_dir); + ACTF("Writing %s ...", fr); if ((fr_fd = open(fr, O_WRONLY | O_TRUNC | O_CREAT, DEFAULT_PERMISSION)) >= 0) { @@ -3260,6 +3267,7 @@ stop_fuzzing: WARNF("Could not create fastresume.bin"); } + } destroy_queue(afl); destroy_extras(afl); -- cgit 1.4.1 From b8568034f0c120ab8500c03ed4982d641eaa88fb Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 18 Jun 2024 15:42:34 +0200 Subject: code format and changelog --- docs/Changelog.md | 5 +++ include/envs.h | 3 +- src/afl-fuzz-queue.c | 4 ++- src/afl-fuzz.c | 90 +++++++++++++++++++++++++++------------------------- 4 files changed, 56 insertions(+), 46 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 1590b2df..f146534f 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -4,6 +4,11 @@ release of the tool. See README.md for the general instruction manual. ### Version ++4.22a (dev) + - afl-fuzz: + - fastresume feature added. if you abort fuzzing and resume fuzzing + with `-i -` or `AFL_AUTORESUME=1` and the target binary has not changed + then a dump will be loaded and the calibration phase skipped. + to disable this feature set `AFL_NO_FASTRESUME=1` - frida_mode: - AFL_FRIDA_PERSISTENT_ADDR can now be be any reachable address not just a function entry diff --git a/include/envs.h b/include/envs.h index 928f4185..ef522ab4 100644 --- a/include/envs.h +++ b/include/envs.h @@ -115,7 +115,8 @@ static char *afl_environment_variables[] = { "AFL_TRACE_PC", "AFL_USE_ASAN", "AFL_USE_MSAN", "AFL_USE_TRACE_PC", "AFL_USE_UBSAN", "AFL_USE_TSAN", "AFL_USE_CFISAN", "AFL_USE_LSAN", "AFL_WINE_PATH", "AFL_NO_SNAPSHOT", "AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN", - "AFL_USE_QASAN", "AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", "AFL_NO_FASTRESUME", NULL + "AFL_USE_QASAN", "AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", + "AFL_NO_FASTRESUME", NULL }; diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index a28172f9..6069f5b9 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -401,7 +401,9 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) { } else { - if (unlink(fn)) { /*PFATAL("Unable to remove '%s'", fn);*/ } + if (unlink(fn)) { /*PFATAL("Unable to remove '%s'", fn);*/ + + } } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 2bfbee15..a09a53ec 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -3214,64 +3214,66 @@ stop_fuzzing: #endif if (!afl->afl_env.afl_no_fastresume) { - /* create fastresume.bin */ - u8 fr[PATH_MAX]; - snprintf(fr, PATH_MAX, "%s/fastresume.bin", afl->out_dir); - ACTF("Writing %s ...", fr); - if ((fr_fd = open(fr, O_WRONLY | O_TRUNC | O_CREAT, DEFAULT_PERMISSION)) >= - 0) { - - u8 ver_string[8]; - u32 w = 0; - u64 *ver = (u64 *)ver_string; - *ver = afl->shm.cmplog_mode + (sizeof(struct queue_entry) << 1); - - w += write(fr_fd, ver_string, sizeof(ver_string)); - - w += write(fr_fd, afl->virgin_bits, afl->fsrv.map_size); - w += write(fr_fd, afl->virgin_tmout, afl->fsrv.map_size); - w += write(fr_fd, afl->virgin_crash, afl->fsrv.map_size); - w += write(fr_fd, afl->var_bytes, afl->fsrv.map_size); - - u8 on[1] = {1}, off[1] = {0}; - u8 *o_start = (u8 *)&(afl->queue_buf[0]->colorized); - u8 *o_end = (u8 *)&(afl->queue_buf[0]->mother); - u32 q_len = o_end - o_start; - u32 m_len = (afl->fsrv.map_size >> 3); - struct queue_entry *q; - afl->pending_not_fuzzed = afl->queued_items; - afl->active_items = afl->queued_items; + /* create fastresume.bin */ + u8 fr[PATH_MAX]; + snprintf(fr, PATH_MAX, "%s/fastresume.bin", afl->out_dir); + ACTF("Writing %s ...", fr); + if ((fr_fd = open(fr, O_WRONLY | O_TRUNC | O_CREAT, DEFAULT_PERMISSION)) >= + 0) { - for (u32 i = 0; i < afl->queued_items; i++) { + u8 ver_string[8]; + u32 w = 0; + u64 *ver = (u64 *)ver_string; + *ver = afl->shm.cmplog_mode + (sizeof(struct queue_entry) << 1); - q = afl->queue_buf[i]; - ck_write(fr_fd, (u8 *)&(q->colorized), q_len, "queue data"); - if (!q->trace_mini) { + w += write(fr_fd, ver_string, sizeof(ver_string)); - ck_write(fr_fd, off, 1, "no_mini"); - w += q_len + 1; + w += write(fr_fd, afl->virgin_bits, afl->fsrv.map_size); + w += write(fr_fd, afl->virgin_tmout, afl->fsrv.map_size); + w += write(fr_fd, afl->virgin_crash, afl->fsrv.map_size); + w += write(fr_fd, afl->var_bytes, afl->fsrv.map_size); - } else { + u8 on[1] = {1}, off[1] = {0}; + u8 *o_start = (u8 *)&(afl->queue_buf[0]->colorized); + u8 *o_end = (u8 *)&(afl->queue_buf[0]->mother); + u32 q_len = o_end - o_start; + u32 m_len = (afl->fsrv.map_size >> 3); + struct queue_entry *q; + + afl->pending_not_fuzzed = afl->queued_items; + afl->active_items = afl->queued_items; - ck_write(fr_fd, on, 1, "yes_mini"); - ck_write(fr_fd, q->trace_mini, m_len, "trace_mini"); - w += q_len + m_len + 1; + for (u32 i = 0; i < afl->queued_items; i++) { + + q = afl->queue_buf[i]; + ck_write(fr_fd, (u8 *)&(q->colorized), q_len, "queue data"); + if (!q->trace_mini) { + + ck_write(fr_fd, off, 1, "no_mini"); + w += q_len + 1; + + } else { + + ck_write(fr_fd, on, 1, "yes_mini"); + ck_write(fr_fd, q->trace_mini, m_len, "trace_mini"); + w += q_len + m_len + 1; + + } } - } + close(fr_fd); + afl->var_byte_count = count_bytes(afl, afl->var_bytes); + OKF("Written fastresume.bin with %u bytes!", w); - close(fr_fd); - afl->var_byte_count = count_bytes(afl, afl->var_bytes); - OKF("Written fastresume.bin with %u bytes!", w); + } else { - } else { + WARNF("Could not create fastresume.bin"); - WARNF("Could not create fastresume.bin"); + } } - } destroy_queue(afl); destroy_extras(afl); -- cgit 1.4.1 From 8fcca6fb410a6ece1a4cd2eb8a2cdeed4d4d9865 Mon Sep 17 00:00:00 2001 From: "Christian Holler (:decoder)" Date: Wed, 19 Jun 2024 12:36:58 +0200 Subject: Collect persistent coverage data and dump it at the end of the run With CODE_COVERAGE builds, we need to collect the coverage data of each iteration in a persistant buffer that has the same size as the regular trace buffer used for fuzzing. We dump this information at the end of the run and when combined with pointer data and module info, this can be used to calculate code coverage. --- include/forkserver.h | 4 ++++ src/afl-forkserver.c | 8 ++++++++ src/afl-fuzz-run.c | 21 +++++++++++++++++++++ src/afl-fuzz.c | 22 ++++++++++++++++++++++ 4 files changed, 55 insertions(+) diff --git a/include/forkserver.h b/include/forkserver.h index 593e34a2..3fd813a4 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -206,6 +206,10 @@ typedef struct afl_forkserver { s32 nyx_log_fd; #endif +#ifdef __AFL_CODE_COVERAGE + u8 *persistent_trace_bits; /* Persistent copy of bitmap */ +#endif + } afl_forkserver_t; typedef enum fsrv_run_result { diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 71d8570d..a998c10f 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -252,6 +252,10 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) { fsrv->uses_crash_exitcode = false; fsrv->uses_asan = false; +#ifdef __AFL_CODE_COVERAGE + fsrv->persistent_trace_bits = NULL; +#endif + fsrv->init_child_func = fsrv_exec_child; list_append(&fsrv_list, fsrv); @@ -278,6 +282,10 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) { fsrv_to->fsrv_kill_signal = from->fsrv_kill_signal; fsrv_to->debug = from->debug; +#ifdef __AFL_CODE_COVERAGE + fsrv_to->persistent_trace_bits = from->persistent_trace_bits; +#endif + // These are forkserver specific. fsrv_to->out_dir_fd = -1; fsrv_to->child_pid = -1; diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 6a0da6ab..c234fc42 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -60,6 +60,27 @@ fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) { fsrv_run_result_t res = afl_fsrv_run_target(fsrv, timeout, &afl->stop_soon); +#ifdef __AFL_CODE_COVERAGE + if (unlikely(!fsrv->persistent_trace_bits)) { + + // On the first run, we allocate the persistent map to collect coverage. + fsrv->persistent_trace_bits = (u8 *)malloc(fsrv->map_size); + memset(fsrv->persistent_trace_bits, 0, fsrv->map_size); + + } + + for (u32 i = 0; i < fsrv->map_size; ++i) { + + if (fsrv->persistent_trace_bits[i] != 255 && fsrv->trace_bits[i]) { + + fsrv->persistent_trace_bits[i]++; + + } + + } + +#endif + /* If post_run() function is defined in custom mutator, the function will be called each time after AFL++ executes the target program. */ diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index a09a53ec..0209e74f 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -3130,6 +3130,28 @@ stop_fuzzing: write_bitmap(afl); save_auto(afl); + #ifdef __AFL_CODE_COVERAGE + if (afl->fsrv.persistent_trace_bits) { + + char cfn[4096]; + snprintf(cfn, sizeof(cfn), "%s/covmap.dump", afl->out_dir); + + FILE *cov_fd; + if ((cov_fd = fopen(cfn, "w")) == NULL) { + + PFATAL("could not create '%s'", cfn); + + } + + // Write the real map size, as the map size must exactly match the pointer + // map in length. + fwrite(afl->fsrv.persistent_trace_bits, 1, afl->fsrv.real_map_size, cov_fd); + fclose(cov_fd); + + } + + #endif + if (afl->pizza_is_served) { SAYF(CURSOR_SHOW cLRD "\n\n+++ Baking aborted %s +++\n" cRST, -- cgit 1.4.1 From 2fbc0aefb1b68c5c580c9861541dd7a2080d2f2f Mon Sep 17 00:00:00 2001 From: killerra <25255685+killerra@users.noreply.github.com> Date: Thu, 20 Jun 2024 00:10:40 +0200 Subject: Auto disable memory limits for FASAN --- src/afl-fuzz.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 0209e74f..0ae12fc1 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1873,6 +1873,13 @@ int main(int argc, char **argv_orig, char **envp) { OKF("Using Frida Address Sanitizer Mode"); + if (afl->fsrv.mem_limit) { + + WARNF("in the Frida Address Sanitizer Mode we disable all memory limits"); + afl->fsrv.mem_limit = 0; + + } + fasan_check_afl_preload(afl_preload); setenv("ASAN_OPTIONS", "detect_leaks=false", 1); -- cgit 1.4.1 From 43a98b0ec2762f15221844aa642727fe3a606596 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 18 Jun 2024 15:49:03 +0200 Subject: todos --- TODO.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/TODO.md b/TODO.md index b36269b4..9681d72b 100644 --- a/TODO.md +++ b/TODO.md @@ -2,7 +2,9 @@ ## Must - - fast restart of afl-fuzz if cmdline + target hash is the same + - fast resume: + use gzopen, gzwrite, gzread and gzclose + gzsetparams(fr_fd, 9, Z_DEFAULT_STRATEGY/Z_FILTERED/Z_HUFFMAN_ONLY); - check for null ptr for xml/curl/g_ string transform functions - hardened_usercopy=0 page_alloc.shuffle=0 - add value_profile but only enable after 15 minutes without finds -- cgit 1.4.1 From aecd15724414629ed8e42da270e6235accd7839c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 18 Jun 2024 16:10:39 +0200 Subject: nit --- TODO.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/TODO.md b/TODO.md index 9681d72b..6f7505a6 100644 --- a/TODO.md +++ b/TODO.md @@ -3,8 +3,7 @@ ## Must - fast resume: - use gzopen, gzwrite, gzread and gzclose - gzsetparams(fr_fd, 9, Z_DEFAULT_STRATEGY/Z_FILTERED/Z_HUFFMAN_ONLY); + use gzopen(fn, "rb"/"wb9-/f/h", gzwrite, gzread and gzclose - check for null ptr for xml/curl/g_ string transform functions - hardened_usercopy=0 page_alloc.shuffle=0 - add value_profile but only enable after 15 minutes without finds -- cgit 1.4.1 From ed6f19d3d8f9a5fafc3efe6328fe41f91f3b3a28 Mon Sep 17 00:00:00 2001 From: Chenhao Date: Fri, 21 Jun 2024 09:52:28 +0800 Subject: Fix typo in unicorn_mode in `unicorn_mode/samples`, python example floder's name is `python_simple`, there is a typo in README file. --- unicorn_mode/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unicorn_mode/README.md b/unicorn_mode/README.md index ce87a2e9..69ccc476 100644 --- a/unicorn_mode/README.md +++ b/unicorn_mode/README.md @@ -144,7 +144,7 @@ The following examples exist at the time of writing: blocks - persistent: A C example using persistent mode for maximum speed, and resetting the target state between each iteration -- simple: A simple Python example +- python_simple: A simple Python example - speedtest/c: The C harness for an example target, used to compare C, Python, and Rust bindings and fix speed issues - speedtest/python: Fuzzing the same target in Python @@ -158,4 +158,4 @@ get shipped pre-built (plus their source). Especially take a look at the [speedtest documentation](./samples/speedtest/README.md) to see how the -languages compare. \ No newline at end of file +languages compare. -- cgit 1.4.1 From ecb5854be08fa978be3320c1f8333f6cc3261fec Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 21 Jun 2024 14:40:16 +0200 Subject: add zlib compression for fast resume --- GNUmakefile | 8 ++++ docs/Changelog.md | 1 + include/debug.h | 2 - src/afl-fuzz.c | 135 +++++++++++++++++++++++++++++++++++++++++++----------- 4 files changed, 116 insertions(+), 30 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index e79d3f83..9f862120 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -441,6 +441,14 @@ test_shm: @echo "[-] shmat seems not to be working, switching to mmap implementation" endif +ifeq "$(shell echo '$(HASH)include @int main() {return 0; }' | tr @ '\n' | $(CC) $(CFLAGS) -Werror -x c - -lz -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" + override SPECIAL_PERFORMANCE += -DHAVE_ZLIB + override LDFLAGS += -lz + $(info [+] ZLIB detected) +else + $(info [!] Warning: no ZLIB detected) +endif + .PHONY: test_python ifeq "$(PYTHON_OK)" "1" test_python: diff --git a/docs/Changelog.md b/docs/Changelog.md index f146534f..c6266e86 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -9,6 +9,7 @@ with `-i -` or `AFL_AUTORESUME=1` and the target binary has not changed then a dump will be loaded and the calibration phase skipped. to disable this feature set `AFL_NO_FASTRESUME=1` + zlib compression is used if zlib is found at compile time - frida_mode: - AFL_FRIDA_PERSISTENT_ADDR can now be be any reachable address not just a function entry diff --git a/include/debug.h b/include/debug.h index 5496135c..c66d0334 100644 --- a/include/debug.h +++ b/include/debug.h @@ -409,8 +409,6 @@ static inline const char *colorfilter(const char *x) { \ } while (1); \ \ - \ - \ } while (0) #define ck_read(fd, buf, len, fn) \ diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 0ae12fc1..b53a9a2d 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -36,6 +36,67 @@ #include #include #endif +#ifdef HAVE_ZLIB + + #define ck_gzread(fd, buf, len, fn) \ + do { \ + \ + s32 _len = (s32)(len); \ + s32 _res = gzread(fd, buf, _len); \ + if (_res != _len) RPFATAL(_res, "Short read from %s", fn); \ + \ + } while (0) + + #define ck_gzwrite(fd, buf, len, fn) \ + do { \ + \ + if (len <= 0) break; \ + s32 _written = 0, _off = 0, _len = (s32)(len); \ + \ + do { \ + \ + s32 _res = gzwrite(fd, (buf) + _off, _len); \ + if (_res != _len && (_res > 0 && _written + _res != _len)) { \ + \ + if (_res > 0) { \ + \ + _written += _res; \ + _len -= _res; \ + _off += _res; \ + \ + } else { \ + \ + RPFATAL(_res, "Short write to %s (%d of %d bytes)", fn, _res, \ + _len); \ + \ + } \ + \ + } else { \ + \ + break; \ + \ + } \ + \ + } while (1); \ + \ + \ + \ + } while (0) + + #include + #define ZLIBOPEN gzopen + #define ZLIBREAD ck_gzread + #define NZLIBREAD gzread + #define ZLIBWRITE ck_gzwrite + #define ZLIBCLOSE gzclose + #define ZLIB_EXTRA "9" +#else + #define ZLIBOPEN open + #define NZLIBREAD read + #define ZLIBREAD ck_read + #define ZLIBWRITE ck_write + #define ZLIBCLOSE close +#endif #ifdef __APPLE__ #include @@ -1875,7 +1936,9 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->fsrv.mem_limit) { - WARNF("in the Frida Address Sanitizer Mode we disable all memory limits"); + WARNF( + "in the Frida Address Sanitizer Mode we disable all memory " + "limits"); afl->fsrv.mem_limit = 0; } @@ -2117,22 +2180,27 @@ int main(int argc, char **argv_orig, char **envp) { check_binary(afl, argv[optind]); u64 prev_target_hash = 0; - s32 fast_resume = 0, fr_fd = -1; + s32 fast_resume = 0; + #ifdef HAVE_ZLIB + gzFile fr_fd = NULL; + #else + s32 fr_fd = -1; + #endif if (afl->in_place_resume && !afl->afl_env.afl_no_fastresume) { u8 fn[PATH_MAX], buf[32]; snprintf(fn, PATH_MAX, "%s/target_hash", afl->out_dir); - fr_fd = open(fn, O_RDONLY); - if (fr_fd >= 0) { + s32 fd = open(fn, O_RDONLY); + if (fd >= 0) { - if (read(fr_fd, buf, 32) >= 16) { + if (read(fd, buf, 32) >= 16) { sscanf(buf, "%p", (void **)&prev_target_hash); } - close(fr_fd); + close(fd); } @@ -2152,14 +2220,21 @@ int main(int argc, char **argv_orig, char **envp) { u8 fn[PATH_MAX]; snprintf(fn, PATH_MAX, "%s/fastresume.bin", afl->out_dir); + #ifdef HAVE_ZLIB + if ((fr_fd = ZLIBOPEN(fn, "rb")) != NULL) { + + #else if ((fr_fd = open(fn, O_RDONLY)) >= 0) { + #endif + u8 ver_string[8]; u64 *ver = (u64 *)ver_string; u64 expect_ver = afl->shm.cmplog_mode + (sizeof(struct queue_entry) << 1); - if (read(fr_fd, ver_string, sizeof(ver_string)) != sizeof(ver_string)) + if (NZLIBREAD(fr_fd, ver_string, sizeof(ver_string)) != + sizeof(ver_string)) WARNF("Emtpy fastresume.bin, ignoring, cannot perform FAST RESUME"); else if (expect_ver != *ver) WARNF( @@ -2538,10 +2613,10 @@ int main(int argc, char **argv_orig, char **envp) { u64 resume_start = get_cur_time_us(); // if we get here then we should abort on errors - ck_read(fr_fd, afl->virgin_bits, afl->fsrv.map_size, "virgin_bits"); - ck_read(fr_fd, afl->virgin_tmout, afl->fsrv.map_size, "virgin_tmout"); - ck_read(fr_fd, afl->virgin_crash, afl->fsrv.map_size, "virgin_crash"); - ck_read(fr_fd, afl->var_bytes, afl->fsrv.map_size, "var_bytes"); + ZLIBREAD(fr_fd, afl->virgin_bits, afl->fsrv.map_size, "virgin_bits"); + ZLIBREAD(fr_fd, afl->virgin_tmout, afl->fsrv.map_size, "virgin_tmout"); + ZLIBREAD(fr_fd, afl->virgin_crash, afl->fsrv.map_size, "virgin_crash"); + ZLIBREAD(fr_fd, afl->var_bytes, afl->fsrv.map_size, "var_bytes"); u8 res[1] = {0}; u8 *o_start = (u8 *)&(afl->queue_buf[0]->colorized); @@ -2554,12 +2629,12 @@ int main(int argc, char **argv_orig, char **envp) { for (u32 i = 0; i < afl->queued_items; i++) { q = afl->queue_buf[i]; - ck_read(fr_fd, (u8 *)&(q->colorized), q_len, "queue data"); - ck_read(fr_fd, res, 1, "check map"); + ZLIBREAD(fr_fd, (u8 *)&(q->colorized), q_len, "queue data"); + ZLIBREAD(fr_fd, res, 1, "check map"); if (res[0]) { q->trace_mini = ck_alloc(m_len); - ck_read(fr_fd, q->trace_mini, m_len, "trace_mini"); + ZLIBREAD(fr_fd, q->trace_mini, m_len, "trace_mini"); r += q_len + m_len + 1; } else { @@ -2592,14 +2667,14 @@ int main(int argc, char **argv_orig, char **envp) { } u8 buf[4]; - if (read(fr_fd, buf, 3) > 0) { + if (NZLIBREAD(fr_fd, buf, 3) > 0) { FATAL("invalid trailing data in fastresume.bin"); } OKF("Successfully loaded fastresume.bin (%u bytes)!", r); - close(fr_fd); + ZLIBCLOSE(fr_fd); afl->reinit_table = 1; update_calibration_time(afl, &resume_start); @@ -3248,20 +3323,24 @@ stop_fuzzing: u8 fr[PATH_MAX]; snprintf(fr, PATH_MAX, "%s/fastresume.bin", afl->out_dir); ACTF("Writing %s ...", fr); + #ifdef HAVE_ZLIB + if ((fr_fd = ZLIBOPEN(fr, "wb9")) != NULL) { + + #else if ((fr_fd = open(fr, O_WRONLY | O_TRUNC | O_CREAT, DEFAULT_PERMISSION)) >= - 0) { + #endif u8 ver_string[8]; u32 w = 0; u64 *ver = (u64 *)ver_string; *ver = afl->shm.cmplog_mode + (sizeof(struct queue_entry) << 1); - w += write(fr_fd, ver_string, sizeof(ver_string)); - - w += write(fr_fd, afl->virgin_bits, afl->fsrv.map_size); - w += write(fr_fd, afl->virgin_tmout, afl->fsrv.map_size); - w += write(fr_fd, afl->virgin_crash, afl->fsrv.map_size); - w += write(fr_fd, afl->var_bytes, afl->fsrv.map_size); + ZLIBWRITE(fr_fd, ver_string, sizeof(ver_string), "ver_string"); + ZLIBWRITE(fr_fd, afl->virgin_bits, afl->fsrv.map_size, "virgin_bits"); + ZLIBWRITE(fr_fd, afl->virgin_tmout, afl->fsrv.map_size, "virgin_tmout"); + ZLIBWRITE(fr_fd, afl->virgin_crash, afl->fsrv.map_size, "virgin_crash"); + ZLIBWRITE(fr_fd, afl->var_bytes, afl->fsrv.map_size, "var_bytes"); + w += sizeof(ver_string) + afl->fsrv.map_size * 4; u8 on[1] = {1}, off[1] = {0}; u8 *o_start = (u8 *)&(afl->queue_buf[0]->colorized); @@ -3276,23 +3355,23 @@ stop_fuzzing: for (u32 i = 0; i < afl->queued_items; i++) { q = afl->queue_buf[i]; - ck_write(fr_fd, (u8 *)&(q->colorized), q_len, "queue data"); + ZLIBWRITE(fr_fd, (u8 *)&(q->colorized), q_len, "queue data"); if (!q->trace_mini) { - ck_write(fr_fd, off, 1, "no_mini"); + ZLIBWRITE(fr_fd, off, 1, "no_mini"); w += q_len + 1; } else { - ck_write(fr_fd, on, 1, "yes_mini"); - ck_write(fr_fd, q->trace_mini, m_len, "trace_mini"); + ZLIBWRITE(fr_fd, on, 1, "yes_mini"); + ZLIBWRITE(fr_fd, q->trace_mini, m_len, "trace_mini"); w += q_len + m_len + 1; } } - close(fr_fd); + ZLIBCLOSE(fr_fd); afl->var_byte_count = count_bytes(afl, afl->var_bytes); OKF("Written fastresume.bin with %u bytes!", w); -- cgit 1.4.1 From 540d741df0541e0e41e600672245ca1e867c5ef4 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 22 Jun 2024 22:22:01 +0200 Subject: nits atnwalk --- custom_mutators/atnwalk/README.md | 2 +- custom_mutators/atnwalk/atnwalk.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/custom_mutators/atnwalk/README.md b/custom_mutators/atnwalk/README.md index 730349a3..7dbe8ee5 100644 --- a/custom_mutators/atnwalk/README.md +++ b/custom_mutators/atnwalk/README.md @@ -13,7 +13,7 @@ Just type `make` to build `atnwalk.so`. **NOTE:** The commands below just demonstrate an example how running ATNwalk looks like and require a working [testbed](https://github.com/atnwalk/testbed) ```bash -# create the required a random seed first +# create the required random seed first mkdir -p ~/campaign/example/seeds cd ~/campaign/example/seeds head -c1 /dev/urandom | ~/atnwalk/build/javascript/bin/decode -wb > seed.decoded 2> seed.encoded diff --git a/custom_mutators/atnwalk/atnwalk.c b/custom_mutators/atnwalk/atnwalk.c index c3a2cd95..45ccc181 100644 --- a/custom_mutators/atnwalk/atnwalk.c +++ b/custom_mutators/atnwalk/atnwalk.c @@ -180,7 +180,8 @@ size_t fail_fatal(int fd_socket, uint8_t **out_buf) { if (fd_socket != -1) { close(fd_socket); } *out_buf = NULL; - return 0; + fprintf(stderr, "atnwalk.socket not found in current directory!\n"); + exit(-1); } -- cgit 1.4.1 From ac5815d994fe8ff151e0f13088891acc506662ed Mon Sep 17 00:00:00 2001 From: Kuan-Wei Chiu Date: Mon, 24 Jun 2024 05:51:55 +0800 Subject: Optimize bit counting using __builtin_popcount Use the __builtin_popcount intrinsic to optimize the bit counting function if the compiler supports it. This change replaces the manual bit counting algorithm with the more efficient built-in function, which leverages hardware support on compatible processors. This modification ensures that the code remains backward-compatible by falling back to the original implementation when __builtin_popcount is not available. --- include/afl-fuzz.h | 4 ++++ src/afl-fuzz-bitmap.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 6d03a74c..45600698 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -116,6 +116,10 @@ #include #endif +#ifndef __has_builtin + #define __has_builtin(x) 0 +#endif + #undef LIST_FOREACH /* clashes with FreeBSD */ #include "list.h" #ifndef SIMPLE_FILES diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 03bc5d6c..405d2dd6 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -75,9 +75,13 @@ u32 count_bits(afl_state_t *afl, u8 *mem) { } +#if __has_builtin(__builtin_popcount) + ret += __builtin_popcount(v); +#else v -= ((v >> 1) & 0x55555555); v = (v & 0x33333333) + ((v >> 2) & 0x33333333); ret += (((v + (v >> 4)) & 0xF0F0F0F) * 0x01010101) >> 24; +#endif } -- cgit 1.4.1 From af47531745ccdc61b5966f213f6cd6cd9030cc2f Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 26 Jun 2024 01:12:04 +0200 Subject: improved seed selection algorithm --- TODO.md | 3 +- custom_mutators/gramatron/json-c | 2 +- docs/Changelog.md | 1 + src/afl-fuzz-bitmap.c | 4 +- src/afl-fuzz-queue.c | 126 +++++++++++++++++++++++++++++++++------ 5 files changed, 112 insertions(+), 24 deletions(-) diff --git a/TODO.md b/TODO.md index 6f7505a6..a1431afa 100644 --- a/TODO.md +++ b/TODO.md @@ -2,8 +2,7 @@ ## Must - - fast resume: - use gzopen(fn, "rb"/"wb9-/f/h", gzwrite, gzread and gzclose + - docs: AFL_DISABLE_REDUNDANT (large/slow/LAF) - check for null ptr for xml/curl/g_ string transform functions - hardened_usercopy=0 page_alloc.shuffle=0 - add value_profile but only enable after 15 minutes without finds diff --git a/custom_mutators/gramatron/json-c b/custom_mutators/gramatron/json-c index 11546bfd..af8dd4a3 160000 --- a/custom_mutators/gramatron/json-c +++ b/custom_mutators/gramatron/json-c @@ -1 +1 @@ -Subproject commit 11546bfd07a575c47416924cb98de3d33a4e6424 +Subproject commit af8dd4a307e7b837f9fa2959549548ace4afe08b diff --git a/docs/Changelog.md b/docs/Changelog.md index c6266e86..09ea8cb6 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -10,6 +10,7 @@ then a dump will be loaded and the calibration phase skipped. to disable this feature set `AFL_NO_FASTRESUME=1` zlib compression is used if zlib is found at compile time + - improved seed selection algorithm - frida_mode: - AFL_FRIDA_PERSISTENT_ADDR can now be be any reachable address not just a function entry diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 405d2dd6..97ccd3d3 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -463,7 +463,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { if (unlikely(fault == FSRV_RUN_TMOUT && afl->afl_env.afl_ignore_timeouts)) { - if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) { + if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) { classify_counts(&afl->fsrv); u64 cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); @@ -489,7 +489,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { /* Generating a hash on every input is super expensive. Bad idea and should only be used for special schedules */ - if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) { + if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) { classify_counts(&afl->fsrv); classified = 1; diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 6069f5b9..999929a1 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -123,7 +123,7 @@ void create_alias_table(afl_state_t *afl) { double weight = 1.0; { // inline does result in a compile error with LTO, weird - if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) { + if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) { u32 hits = afl->n_fuzz[q->n_fuzz_entry]; if (likely(hits)) { weight /= (log10(hits) + 1); } @@ -133,39 +133,127 @@ void create_alias_table(afl_state_t *afl) { if (likely(afl->schedule < RARE)) { double t = q->exec_us / avg_exec_us; + if (likely(t < 0.1)) { // nothing - } else if (likely(t <= 0.25)) + } else if (likely(t <= 0.25)) { + + weight *= 0.95; - weight *= 0.9; - else if (likely(t <= 0.5)) { + } else if (likely(t <= 0.5)) { // nothing - } else if (likely(t < 1.0)) + } else if (likely(t <= 0.75)) { + + weight *= 1.05; + + } else if (likely(t <= 1.0)) { + + weight *= 1.1; + + } else if (likely(t < 1.25)) { + + weight *= 0.2; // WTF ??? makes no sense + + } else if (likely(t <= 1.5)) { + + // nothing + + } else if (likely(t <= 2.0)) { + + weight *= 1.1; + + } else if (likely(t <= 2.5)) { + + } else if (likely(t <= 5.0)) { weight *= 1.15; - else if (unlikely(t > 2.5 && t < 5.0)) + + } else if (likely(t <= 20.0)) { + weight *= 1.1; - // else nothing + // else nothing + + } } double l = q->len / avg_len; - if (likely(l < 0.1)) - weight *= 0.75; - else if (likely(l < 0.25)) - weight *= 1.1; - else if (unlikely(l >= 10)) - weight *= 1.1; + if (likely(l < 0.1)) { + + weight *= 0.5; + + } else if (likely(l <= 0.5)) { + + // nothing + + } else if (likely(l <= 1.25)) { + + weight *= 1.05; + + } else if (likely(l <= 1.75)) { + + // nothing + + } else if (likely(l <= 2.0)) { + + weight *= 0.95; + + } else if (likely(l <= 5.0)) { + + // nothing + + } else if (likely(l <= 10.0)) { + + weight *= 1.05; + + } else { + + weight *= 1.15; + + } double bms = q->bitmap_size / avg_bitmap_size; - if (likely(bms < 0.5)) - weight *= (1.0 + ((bms - 0.5) / 2)); - else if (unlikely(bms > 1.33)) - weight *= 1.1; + if (likely(bms < 0.1)) { + + weight *= 0.01; + + } else if (likely(bms <= 0.25)) { + + weight *= 0.55; + + } else if (likely(bms <= 0.5)) { + + // nothing + + } else if (likely(bms <= 0.75)) { + + weight *= 1.2; + + } else if (likely(bms <= 1.25)) { + + weight *= 1.3; + + } else if (likely(bms <= 1.75)) { + + weight *= 1.25; + + } else if (likely(bms <= 2.0)) { + + // nothing + + } else if (likely(bms <= 2.5)) { + + weight *= 1.3; + + } else { + + weight *= 0.75; + + } if (unlikely(!q->was_fuzzed)) { weight *= 2.5; } if (unlikely(q->fs_redundant)) { weight *= 0.75; } @@ -741,7 +829,7 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { u64 fav_factor; u64 fuzz_p2; - if (likely(afl->schedule >= FAST && afl->schedule < RARE)) { + if (unlikely(afl->schedule >= FAST && afl->schedule < RARE)) { fuzz_p2 = 0; // Skip the fuzz_p2 comparison @@ -777,7 +865,7 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { u64 top_rated_fav_factor; u64 top_rated_fuzz_p2; - if (likely(afl->schedule >= FAST && afl->schedule < RARE)) { + if (unlikely(afl->schedule >= FAST && afl->schedule < RARE)) { top_rated_fuzz_p2 = 0; // Skip the fuzz_p2 comparison -- cgit 1.4.1 From 5f43d0ad42b9c9d3aca8e4c7ed3cc47f6d00b9be Mon Sep 17 00:00:00 2001 From: Jake Lamberson Date: Wed, 26 Jun 2024 09:53:04 -0400 Subject: Fix and enhance Nyx mode instructions --- nyx_mode/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nyx_mode/README.md b/nyx_mode/README.md index 7a2a8e6c..a839c157 100644 --- a/nyx_mode/README.md +++ b/nyx_mode/README.md @@ -23,7 +23,7 @@ requires an Intel processor (6th generation onwards) and a special 5.10 kernel 2. Additionally, install the following packages: ```shell - apt-get install -y libgtk-3-dev pax-utils python3-msgpack python3-jinja2 + apt-get install -y libgtk-3-dev pax-utils python3-msgpack python3-jinja2 libcapstone-dev ``` 3. As Nyx is written in Rust, install the newest rust compiler (rust packages in @@ -33,7 +33,7 @@ requires an Intel processor (6th generation onwards) and a special 5.10 kernel curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` -4. Finally build Nyx mode: +4. Finally build Nyx mode (or use `make distrib` at the repo root to build all AFL++ modes): ```shell ./build_nyx_support.sh @@ -92,7 +92,7 @@ sudo modprobe -r kvm-intel sudo modprobe -r kvm sudo modprobe kvm enable_vmware_backdoor=y sudo modprobe kvm-intel -cat /sys/module/kvm/parameters/enable_vmware_backdoor | grep -q Y && echi OK || echo KVM module problem +cat /sys/module/kvm/parameters/enable_vmware_backdoor | grep -q Y && echo OK || echo KVM module problem ``` All the hard parts are done, fuzzing with Nyx mode is easy - just supply the @@ -186,7 +186,7 @@ make CC=afl-clang-fast CXX=afl-clang-fast++ LD=afl-clang-fast #### Nyx share directories -Nyx expects that the target is provided in a certain format. More specifically, the target is passed as a so-called „share directory“ to a Nyx-frontend implementation. The share directory contains the target as well as a folder containing all dependencies and other files that are copied over to the guest. But more importantly, this share directory also contains a bootstrap script (`fuzz.sh`if you are using `KVM-Nyx`otherwise `fuzz_no_pt.sh`) that is also executed right after launching the fuzzer. Both bootstrap scripts use several tools to communicate with the "outer world": +Nyx expects that the target is provided in a certain format. More specifically, the target is passed as a so-called „share directory“ to a Nyx-frontend implementation. The share directory contains the target as well as a folder containing all dependencies and other files that are copied over to the guest. But more importantly, this share directory also contains a bootstrap script (`fuzz.sh`if you are using `KVM-Nyx`otherwise `fuzz_no_pt.sh`) that is also executed right after launching the fuzzer. Either of these scripts can be edited to more fully prepare an environment for the target, like transferring configuration files to the target's filesystem. Both bootstrap scripts use several tools to communicate with the "outer world": - `hcat` - this tool copies a given string to the host - `hget` - this program requests a file from the host's share directory -- cgit 1.4.1 From 22487735663c2ab49d76b0fdddafe0a2f96ebf83 Mon Sep 17 00:00:00 2001 From: Jake Lamberson Date: Wed, 26 Jun 2024 20:19:00 -0400 Subject: Add nyx_mode to contribution instructions --- CONTRIBUTING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0042bf28..8b4dcb6d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -34,6 +34,7 @@ file in one the following folders: * [docs/](docs/) (this is where you can find most of our docs content) * [frida_mode/](frida_mode/) * [instrumentation/](instrumentation/) +* [nyx_mode/](nyx_mode/) * [qemu_mode/](qemu_mode/) * [unicorn_mode/](unicorn_mode/) -- cgit 1.4.1 From ba7313b521df7a347cd9f96a694cd8caa63b9b41 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 27 Jun 2024 18:51:54 +0200 Subject: AFL_CUSTOM_MUTATOR_LATE_SEND added --- docs/Changelog.md | 2 ++ docs/custom_mutators.md | 5 +++++ docs/env_variables.md | 4 ++++ include/afl-fuzz.h | 5 +++-- include/envs.h | 19 ++++++++++--------- include/forkserver.h | 5 +++++ src/afl-forkserver.c | 10 ++++++++++ src/afl-fuzz-run.c | 12 +++++++++++- src/afl-fuzz-state.c | 7 +++++++ src/afl-fuzz.c | 25 +++++++++++++++++++++++++ 10 files changed, 82 insertions(+), 12 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 09ea8cb6..c16214e4 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -11,6 +11,8 @@ to disable this feature set `AFL_NO_FASTRESUME=1` zlib compression is used if zlib is found at compile time - improved seed selection algorithm + - added `AFL_CUSTOM_MUTATOR_LATE_SEND=1` to call the custom send() + function after the target has been restarted. - frida_mode: - AFL_FRIDA_PERSISTENT_ADDR can now be be any reachable address not just a function entry diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md index b7a7032f..3067ceab 100644 --- a/docs/custom_mutators.md +++ b/docs/custom_mutators.md @@ -198,6 +198,11 @@ def deinit(): # optional for Python This method can be used if you want to send data to the target yourself, e.g. via IPC. This replaces some usage of utils/afl_proxy but requires that you start the target with afl-fuzz. + + Setting `AFL_CUSTOM_MUTATOR_LATE_SEND` will call the afl_custom_fuzz_send() + function after the target has been restarted. (This is needed for e.g. TCP + services.) + Example: [custom_mutators/examples/custom_send.c](../custom_mutators/examples/custom_send.c) - `queue_new_entry` (optional): diff --git a/docs/env_variables.md b/docs/env_variables.md index 6db31df0..eebbcbda 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -368,6 +368,10 @@ checks or alter some of the more exotic semantics of the tool: XML or other highly flexible structured input. For details, see [custom_mutators.md](custom_mutators.md). + - Setting `AFL_CUSTOM_MUTATOR_LATE_SEND` will call the afl_custom_fuzz_send() + function after the target has been restarted. (This is needed for e.g. TCP + services.) + - Setting `AFL_CYCLE_SCHEDULES` will switch to a different schedule every time a cycle is finished. diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 45600698..0f0e45d3 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -449,8 +449,9 @@ extern char *power_names[POWER_SCHEDULES_NUM]; typedef struct afl_env_vars { u8 afl_skip_cpufreq, afl_exit_when_done, afl_no_affinity, afl_skip_bin_check, - afl_dumb_forksrv, afl_import_first, afl_custom_mutator_only, afl_no_ui, - afl_force_ui, afl_i_dont_care_about_missing_crashes, afl_bench_just_one, + afl_dumb_forksrv, afl_import_first, afl_custom_mutator_only, + afl_custom_mutator_late_send, afl_no_ui, afl_force_ui, + afl_i_dont_care_about_missing_crashes, afl_bench_just_one, afl_bench_until_crash, afl_debug_child, afl_autoresume, afl_cal_fast, afl_cycle_schedules, afl_expand_havoc, afl_statsd, afl_cmplog_only_new, afl_exit_on_seed_issues, afl_try_affinity, afl_ignore_problems, diff --git a/include/envs.h b/include/envs.h index ef522ab4..6a0d329b 100644 --- a/include/envs.h +++ b/include/envs.h @@ -24,15 +24,16 @@ static char *afl_environment_variables[] = { "AFL_DUMP_CYCLOMATIC_COMPLEXITY", "AFL_CMPLOG_MAX_LEN", "AFL_COMPCOV_LEVEL", "AFL_CRASH_EXITCODE", "AFL_CRASHING_SEEDS_AS_NEW_CRASH", "AFL_CUSTOM_MUTATOR_LIBRARY", "AFL_CUSTOM_MUTATOR_ONLY", - "AFL_CUSTOM_INFO_PROGRAM", "AFL_CUSTOM_INFO_PROGRAM_ARGV", - "AFL_CUSTOM_INFO_PROGRAM_INPUT", "AFL_CUSTOM_INFO_OUT", "AFL_CXX", - "AFL_CYCLE_SCHEDULES", "AFL_DEBUG", "AFL_DEBUG_CHILD", "AFL_DEBUG_GDB", - "AFL_DEBUG_UNICORN", "AFL_DISABLE_REDUNDANT", "AFL_NO_REDUNDANT", - "AFL_DISABLE_TRIM", "AFL_NO_TRIM", "AFL_DISABLE_LLVM_INSTRUMENTATION", - "AFL_DONT_OPTIMIZE", "AFL_DRIVER_STDERR_DUPLICATE_FILENAME", - "AFL_DUMB_FORKSRV", "AFL_EARLY_FORKSERVER", "AFL_ENTRYPOINT", - "AFL_EXIT_WHEN_DONE", "AFL_EXIT_ON_TIME", "AFL_EXIT_ON_SEED_ISSUES", - "AFL_FAST_CAL", "AFL_FINAL_SYNC", "AFL_FORCE_UI", "AFL_FRIDA_DEBUG_MAPS", + "AFL_CUSTOM_MUTATOR_LATE_SEND", "AFL_CUSTOM_INFO_PROGRAM", + "AFL_CUSTOM_INFO_PROGRAM_ARGV", "AFL_CUSTOM_INFO_PROGRAM_INPUT", + "AFL_CUSTOM_INFO_OUT", "AFL_CXX", "AFL_CYCLE_SCHEDULES", "AFL_DEBUG", + "AFL_DEBUG_CHILD", "AFL_DEBUG_GDB", "AFL_DEBUG_UNICORN", + "AFL_DISABLE_REDUNDANT", "AFL_NO_REDUNDANT", "AFL_DISABLE_TRIM", + "AFL_NO_TRIM", "AFL_DISABLE_LLVM_INSTRUMENTATION", "AFL_DONT_OPTIMIZE", + "AFL_DRIVER_STDERR_DUPLICATE_FILENAME", "AFL_DUMB_FORKSRV", + "AFL_EARLY_FORKSERVER", "AFL_ENTRYPOINT", "AFL_EXIT_WHEN_DONE", + "AFL_EXIT_ON_TIME", "AFL_EXIT_ON_SEED_ISSUES", "AFL_FAST_CAL", + "AFL_FINAL_SYNC", "AFL_FORCE_UI", "AFL_FRIDA_DEBUG_MAPS", "AFL_FRIDA_DRIVER_NO_HOOK", "AFL_FRIDA_EXCLUDE_RANGES", "AFL_FRIDA_INST_CACHE_SIZE", "AFL_FRIDA_INST_COVERAGE_ABSOLUTE", "AFL_FRIDA_INST_COVERAGE_FILE", "AFL_FRIDA_INST_DEBUG_FILE", diff --git a/include/forkserver.h b/include/forkserver.h index 3fd813a4..6c649528 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -210,6 +210,11 @@ typedef struct afl_forkserver { u8 *persistent_trace_bits; /* Persistent copy of bitmap */ #endif + void *custom_data_ptr; + u8 *custom_input; + u32 custom_input_len; + void (*late_send)(void *, const u8 *, size_t); + } afl_forkserver_t; typedef enum fsrv_run_result { diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index a998c10f..cec91f76 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -292,6 +292,9 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) { fsrv_to->use_fauxsrv = 0; fsrv_to->last_run_timed_out = 0; + fsrv_to->late_send = from->late_send; + fsrv_to->custom_data_ptr = from->custom_data_ptr; + fsrv_to->init_child_func = from->init_child_func; // Note: do not copy ->add_extra_func or ->persistent_record* @@ -1952,6 +1955,13 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, } + if (unlikely(fsrv->late_send)) { + + fsrv->late_send(fsrv->custom_data_ptr, fsrv->custom_input, + fsrv->custom_input_len); + + } + exec_ms = read_s32_timed(fsrv->fsrv_st_fd, &fsrv->child_status, timeout, stop_soon_p); diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index c234fc42..2f244a1d 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -194,7 +194,17 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) { if (el->afl_custom_fuzz_send) { - el->afl_custom_fuzz_send(el->data, *mem, new_size); + if (!afl->afl_env.afl_custom_mutator_late_send) { + + el->afl_custom_fuzz_send(el->data, *mem, new_size); + + } else { + + afl->fsrv.custom_input = *mem; + afl->fsrv.custom_input_len = new_size; + + } + sent = 1; } diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index dd684a19..eead3e50 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -300,6 +300,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_custom_mutator_only = get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_CUSTOM_MUTATOR_LATE_SEND", + + afl_environment_variable_len)) { + + afl->afl_env.afl_custom_mutator_late_send = + get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_CMPLOG_ONLY_NEW", afl_environment_variable_len)) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index b53a9a2d..8a84d447 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2142,6 +2142,31 @@ int main(int argc, char **argv_orig, char **envp) { } + if (afl->custom_mutators_count && afl->afl_env.afl_custom_mutator_late_send) { + + u32 count_send = 0; + LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { + + if (el->afl_custom_fuzz_send) { + + if (count_send) { + + FATAL( + "You can only have one custom send() function if you are using " + "AFL_CUSTOM_MUTATOR_LATE_SEND!"); + + } + + afl->fsrv.late_send = el->afl_custom_fuzz_send; + afl->fsrv.custom_data_ptr = el->data; + count_send = 1; + + } + + }); + + } + if (afl->limit_time_sig > 0 && afl->custom_mutators_count) { if (afl->custom_only) { -- cgit 1.4.1 From 8993ba430545b867da11e119be15126de43d061c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 27 Jun 2024 19:42:58 +0200 Subject: add ruby dict --- dictionaries/ruby.dict | 5713 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 5713 insertions(+) create mode 100644 dictionaries/ruby.dict diff --git a/dictionaries/ruby.dict b/dictionaries/ruby.dict new file mode 100644 index 00000000..601b7363 --- /dev/null +++ b/dictionaries/ruby.dict @@ -0,0 +1,5713 @@ +! +!= +!~ +% +& +* +** ++ ++@ +- +-@ +/ +< +<< +<= +<=> +== +=== +=~ +> +>= +>> +APOP +ASCIIZ +AdditiveExpr +AndExpr +Array +BigDecimal +CSV +Call +CloseKey +Complex +CreateKey +CurrentContext +D +DEBUG +DEBUG= +DelegateClass +DeleteKey +DeleteValue +Digest +E +ESCDELAY +ESCDELAY= +EnumKey +EnumValue +EqualityExpr +Fail +FilterExpr +Float +FlushKey +FunctionCall +Hash +I +Integer +JSON +JobManager +LOG_MASK +LOG_UPTO +LocationPath +MultiplicativeExpr +NodeTest +OpenKey +OrExpr +PI +PathExpr +Pathname +PermaLink? +Predicate +PrimaryExpr +Proxy +QueryInfoKey +QueryValue +Raise +Rational +RelationalExpr +RelativeLocationPath +SP +SP_Z +SetValue +String +TABSIZE +TABSIZE= +URI +UnaryExpr +UnionExpr +Z +[] +[]= +^ +_PermaLink? +__callee__ +__dir__ +__drbref +__drburi +__evaluate__ +__exit__ +__getobj__ +__id__ +__method__ +__send__ +__setobj__ +__to_xpath_helper +__validate +_ac_arg_enable +_attrs +_check_ac_args +_dump +_getproperty +_httpdate +_id2ref +_invoke +_iso8601 +_jisx0301 +_load +_nodeType +_ns +_parse +_parse_date_if_needed +_prepare_run +_print +_racc_do_parse_c +_racc_do_parse_rb +_racc_do_reduce +_racc_evalact +_racc_init_sysvars +_racc_setup +_racc_yyparse_c +_racc_yyparse_rb +_report +_reverse +_rfc2822 +_rfc3339 +_rfc822 +_run_parallel +_run_suite +_run_suites +_set_default_values +_set_last_value +_setproperty +_setup_maker_element +_strptime +_tags +_to_string +_validate +_xmlschema +` +a +abbrev +abbreviate +abi +abort +abort_on_exception +abort_on_exception= +about +abs +abs2 +absolute +absolute? +absolute_name +absolute_path +ac_arg_disable +ac_arg_enable +ac_arg_with +accept +accept_blank_line +accept_block_quote +accept_charset +accept_charset= +accept_document +accept_encoding +accept_heading +accept_indented_paragraph +accept_language +accept_list_end +accept_list_item_end +accept_list_item_start +accept_list_start +accept_loop +accept_nonblock +accept_paragraph +accept_raw +accept_rule +accept_uri_http +accept_verbatim +access_log +acct +acos +acos! +acosh +acosh! +actions +activate +activate_dependencies +activated +activated? +active? +active_count +active_job? +active_jobs +active_jobs_exist? +active_process_controllers +add +add! +add? +add_alias +add_also_in +add_attribute +add_attributes +add_authenticator +add_bindir +add_bulk_threshold_option +add_c_enclosure +add_c_variables +add_cert +add_certid +add_certificate +add_chain_to +add_checksums +add_class +add_class_or_module +add_clear_sources_option +add_comment +add_common_option +add_constant +add_converter +add_crl +add_data +add_date +add_dependency +add_dependency_with_type +add_description +add_development_dependency +add_dictionary +add_element +add_entry +add_event_to_arry +add_extend +add_extends +add_extension +add_extension_modules +add_extra_args +add_field +add_file +add_file_digest +add_file_signed +add_file_simple +add_filter +add_footnote +add_found_dependencies +add_from +add_generator +add_handler +add_have_children_element +add_html +add_import +add_include +add_includes +add_install_update_options +add_introspection +add_key_option +add_label +add_line_numbers +add_listener +add_loader +add_local_remote_options +add_location +add_log_header +add_maker +add_method +add_method_documentation +add_method_list +add_module +add_module_alias +add_multicall +add_namespace +add_need_initialize_variable +add_nonce +add_observer +add_option +add_other_element +add_owners +add_padding +add_paragraph +add_parser_run_info +add_path +add_platform +add_platform_option +add_plural_form +add_prerelease_option +add_private_type +add_protocol +add_proxy_option +add_rakelib +add_recipient +add_require +add_response_handler +add_revoked +add_row +add_ruby_type +add_rubygems_trusted_certs +add_runtime_dependency +add_schedule +add_section +add_self_to_load_path +add_setup_hook +add_signer +add_source_option +add_spec +add_special +add_special_RDOCLINK +add_special_TIDYLINK +add_specific_extra_args +add_specs +add_status +add_tag +add_target +add_teardown_hook +add_text +add_text_tests +add_to +add_to_classes_or_modules +add_to_element_method +add_to_fetcher +add_token +add_token_listener +add_tokens +add_trace_func +add_unconverted_fields +add_update_sources_option +add_value +add_version_option +add_visitor_tests +add_word_pair +addch +addr +addr_mask +addr_port +address +addstr +adler +adler32 +adler32_combine +advise +afamily +after +after_setup +after_teardown +after_worker_down +after_worker_quit +ajd +alert +alert_error +alert_warning +algorithm +alias +alias_command +alias_extension +alias_map +alias_method +aliases +alien +align +alive? +all +all= +all? +all_classes +all_classes_and_modules +all_files +all_modules +all_names +all_spec_names +all_specs +all_symbols +all_waits +allocate +allow_addr? +allow_socket? +alt_name_or_x509_entry +alternate= +amjd +ancestors +ancestors_of +anchor +angle +annotate +any? +any_content +any_to_s +ap_name +api_endpoint +api_endpoints +api_key +api_keys +api_uri +apop? +app_script_text +append +append_data +append_features +application +application= +apply_offset +appname +approximate_recommendation +aref +aref_prefix +aref_to +arg +arg_names +arglists +args +arguments +argv +arity +array +array_attributes +as_href +as_json +as_string +ascend +ascii_compatible? +ascii_only? +asciicompat_encoding +asctime +asin +asin! +asinh +asinh! +ask +ask_for_password +ask_for_password_on_unix +ask_for_password_on_windows +ask_if_ok +ask_yes_no +asn1_flag +asn1_flag= +assemble_template +assert +assert_block +assert_contains_make_command +assert_empty +assert_equal +assert_headers_equal +assert_in_delta +assert_in_epsilon +assert_includes +assert_instance_of +assert_kind_of +assert_match +assert_nil +assert_no_match +assert_not_equal +assert_not_nil +assert_not_same +assert_not_send +assert_nothing_raised +assert_nothing_thrown +assert_operator +assert_output +assert_path_exists +assert_performance +assert_performance_constant +assert_performance_exponential +assert_performance_linear +assert_performance_power +assert_predicate +assert_raise +assert_raises +assert_respond_to +assert_same +assert_send +assert_silent +assert_throws +asset +asset_dirs +asset_rel_path +assign_names +assoc +at +at_exit +atan +atan! +atan2 +atan2! +atanh +atanh! +atime +atom_validate +attempt_rule +attlistdecl +attlistdecl? +attr +attr_accessor +attr_reader +attr_writer +attribute +attribute_manager +attribute_names +attribute_of +attributes +attributes= +attributes_of +attroff +attron +attrset +atype +audit +auth_capable? +auth_cram_md5 +auth_data= +auth_login +auth_method +auth_only +auth_plain +auth_tag +auth_tag= +auth_type +authenticate +authenticated? +author +author= +authors +authors= +auto_indent_mode +autoclose= +autoclose? +autoload +autoload? +autorequire +autorun +avail_in +avail_out +avail_out= +available_specs +available_tags +axe +b +back_trace_limit +backticks +backtrace +backtrace_filter +backtrace_locations +banner +base +base64 +base64_encode +base64digest +base64digest! +base_dir +base_label +base_name +base_uri +basename +basic +basic_auth +basic_encode +basic_quote_characters +basic_quote_characters= +basic_word_break_characters +basic_word_break_characters= +beep +before +before_running_rdoc +before_setup +before_teardown +begin +begin_adding +begin_transport +beginning_of_line? +begins? +begx +begy +bench +bench_exp +bench_linear +bench_performance_constant +bench_performance_exponential +bench_performance_linear +bench_range +benchmark +benchmark_suites +between? +bin_dir +bin_file +bin_for_find +bin_key +bin_path +binary +binary= +binary? +binary_mode +bind +bind_at_call +bind_function +binding +bindir +binmode +binmode= +binmode? +binread +binwrite +bit_set? +bitmap +bitmap_for +bkgd +bkgdset +blank_line +blinding_off! +blinding_on! +blksize +block +block_given? +block_length +block_output_synchronize +block_params +block_params= +block_scanf +blockdev? +blockquote +blocks +bm +bmbm +body +body= +body_exist? +body_permitted? +body_stream +body_stream= +bool +boolean +boolean_writer +both? +bottom +bound? +box +break +break? +break_on_newline +break_outmost_groups +break_points +breakable +breakables +broadcast +broadcast_list +bsearch +buf +buffer +bufferSize +bufferType +build +build2 +build_args +build_args= +build_eigenvectors +build_extensions +build_heading +build_index +build_indicies +build_info_dir +build_info_file +build_list +build_marshal_gemspecs +build_modern +build_modern_index +build_modern_indicies +build_paragraph +build_path_query +build_rake_in +build_verbatim +builtin_curves +bulk_threshold +bump +by_col +by_col! +by_col_or_row +by_col_or_row! +by_id +by_row +by_row! +bytes +bytes_read +bytesize +byteslice +c_class_variables +c_function +c_singleton_class_variables +ca_certs +ca_file +ca_path +cache +cache_dir +cache_file +cache_path +cache_update_path +cachesize= +calc_checksum +calc_indent +calculate +calculate_checksum +call +call2 +call2_async +call_async +call_hook +call_method +call_seq +callcc +caller +caller_locations +calls_super +calltype +calltype= +can_change_color? +can_parse +can_parse_by_name +cancel +canceled? +candidate +canonical +canonical_each +canonname +capabilities +capability +capable? +capable_auth_types +capable_cram_md5_auth? +capable_login_auth? +capable_plain_auth? +capable_starttls? +capitalize +capitalize! +caption +capture2 +capture2e +capture3 +capture_io +capture_subprocess_io +captures +cascade +casecmp +casefold? +cat +catch +cbreak +cbrt +cbrt! +cd +cdata +cdata? +cdatas +cdesc +cdiv +ceil +ceiling +center +cert +cert_chain +cert_path +cert_store +certid +certificate +certificates +certificates= +certificates_matching +certs +chain +chain= +challenge +challenge= +change_attribute +change_privilege +change_workspace +changed +changed? +changed_attribute_by_name +char_pos +character +character_limit +characters +chardev? +charpos +chars +charset +chdir +check +check_arity +check_auth_args +check_auth_continue +check_auth_method +check_auth_response +check_cert +check_chain +check_closed +check_continue +check_credentials_permissions +check_data +check_files +check_fragment +check_gems +check_generator +check_headers +check_host +check_insecure_method +check_inspect_key +check_key +check_modeline +check_modify +check_names +check_nonce +check_ns +check_opaque +check_password +check_path +check_port +check_private_key +check_query +check_registry +check_response +check_root +check_ruby_version +check_scheme +check_shift_log +check_signedness +check_sizeof +check_that_user_bin_dir_is_in_path +check_to +check_trust +check_typecode +check_until +check_user +check_userinfo +checkbox +checkbox_group +checksums +childNodes +child_name +children +chmod +chmod_R +chomp +chomp! +choose_from_list +chop +chop! +chown +chown_R +chr +chroot +chunk +chunked= +chunked? +cipher +cipher= +ciphers +ciphers= +civil +class +class_attributes +class_dir +class_document +class_eval +class_exec +class_file +class_method_list +class_methods +class_name +class_path +class_variable_defined? +class_variable_get +class_variable_set +class_variables +classes +classes_and_includes_and_extends_for +classes_and_modules +classes_hash +classes_or_modules +classify +clean_gems +clean_up +cleanpath +cleanup +clear +clear_actions +clear_comment +clear_comments +clear_default_specs +clear_exclude +clear_paths +clear_prerequisites +client_ca +client_cert +client_cert_cb +client_error? +client_thread +clobber_task_description +clobber_task_name +clone +close +close! +close_enabled? +close_on_empty_response +close_on_exec= +close_on_exec? +close_read +close_screen +close_write +closed? +closed_read? +closed_write? +clrtoeol +cmd +cmds +cmp +cmp_issuer +cmsg_is? +code +code_object +codepage +codepage= +codepoints +coerce +coerce_other +cofactor +col_sep +collapse +collect +collect! +collect2 +collect_attributes +collect_attrs +collect_concat +collect_first_comment +collect_method +collect_tasks +collect_tokens +color_content +color_pair +color_pairs +color_set +colors +cols +column +column_count +column_size +column_vector +column_vectors +columns +combination +comma_breakable +command +command= +command_names +command_processor +commands +comment +comment= +comment? +comment_location +comments +commercial +commit +common_options +compact +compact! +compact_specs +compare +compare_by_identity +compare_by_identity? +compare_file +compare_language +compare_stream +compatible? +compile +compile_error +compile_file +compile_option +compile_option= +complain +complete +complete_authentication +completer_quote_characters +completer_quote_characters= +completer_word_break_characters +completer_word_break_characters= +completion_append_character +completion_append_character= +completion_case_fold +completion_case_fold= +completion_proc +completion_proc= +component +component_ary +compress +compress_indicies +compute_key +concat +conf +config +config= +config_file +config_file_name +configuration +configuration= +configure_connection_for_https +configure_options +conflict +conflicting_dependencies +conflicts +conj +conjugate +connect +connect_address +connect_from +connect_internal +connect_nonblock +connect_to +connecting +connection_close? +connection_for +connection_keep_alive? +connections +consider_local? +consider_remote? +console +const_defined? +const_defined_in? +const_get +const_load +const_missing +const_set +const_warning +constant_aliases +constants +constants_hash +construct +consume +consume_rbuff +contains +contains_requirable_file? +content +content= +content_encoding +content_is_set? +content_length +content_length= +content_range +content_setup +content_type +content_type= +content_writer +contents +context +context= +contextAttributes +continue? +continue_entry_body +continue_timeout +continue_timeout= +continued_exception +conv +conv2value +conv_arg +convert +convert_attr_reader +convert_attrs +convert_fields +convert_flow +convert_html +convert_special +convert_specials +convert_string +convert_to_uri +converter= +converters +convertible_int +convpath +cooked +cooked! +cookie +cookies +copy +copy_entry +copy_file +copy_files +copy_internal +copy_nonce +copy_static +copy_stream +copy_string +coredump? +correct? +correct_for_windows_path +cos +cos! +cosh +cosh! +count +count_objects +count_observers +covector +cover? +coverage_level +coverage_level= +coverage_report +cp +cp_r +cpu +cram_md5_challenge +cram_md5_response +cram_secret +crc +crc32 +crc32_combine +crc_table +create +createCleanedTree +create_carried_function +create_carrier +create_cert +create_cert_email +create_cert_self_signed +create_document +create_entries +create_entry +create_ext +create_ext_from_array +create_ext_from_hash +create_ext_from_string +create_extension +create_from +create_guid +create_header +create_id +create_items +create_key +create_listeners +create_logfile +create_makefile +create_new_id +create_option_parser +create_rule +create_self_signed_cert +create_ssl_params +create_temp_function +create_tmpdir +create_value +created? +credentials +credentials_path +critical +critical= +critical? +crl +crl= +crls +crls= +crmode +cross_reference +crypt +css +cstime +csv_attr_reader +csv_integer_writer +csv_writer +ctime +ctrl_cmd +ctype +ctype= +current +current= +current_element +current_group +current_job +current_line +current_scope +current_section +current_server +curry +curs_set +curve_name +curx +cury +cut_off +cutime +cvs_url +cwd +cwday +cweek +cwyear +cycle +d +d_o_s +daemon +data +data= +data_type +datadir +date +date= +dateTime +date_writer +datetime_format +datetime_format= +day +day= +day_fraction +dclone +deafen +deal +debug +debug= +debug? +debug_level +debug_level= +debug_mode +debug_msg +debug_output= +debug_thread_info +decode +decode64 +decode_all +decode_content +decode_utf7 +decode_www_form +decode_www_form_component +decoded +decrypt +deep_clone +def_array_element +def_atom_persons +def_atom_text_construct +def_children_accessor +def_class +def_class_accessor +def_classed_element +def_classed_element_without_accessor +def_classed_elements +def_convert +def_corresponded_attr_reader +def_corresponded_attr_writer +def_csv_accessor +def_csv_element +def_delegator +def_delegators +def_e2message +def_element_class_accessor +def_elements_class_accessor +def_else_enc +def_erb_method +def_exception +def_extend_command +def_get_text_element +def_head_option +def_iconv_convert +def_inspector +def_instance_delegator +def_instance_delegators +def_method +def_module +def_notifier +def_option +def_other_element +def_other_element_without_accessor +def_post_proc +def_pre_proc +def_prog_mode +def_same_enc +def_single_delegator +def_single_delegators +def_system_command +def_tail_option +def_to_euc_jp_from_iso_2022_jp +def_to_euc_jp_from_shift_jis +def_to_euc_jp_from_utf_8 +def_to_iso_2022_jp_from_euc_jp +def_to_iso_8859_1_from_utf_8 +def_to_shift_jis_from_euc_jp +def_to_shift_jis_from_utf_8 +def_to_utf_8_from_euc_jp +def_to_utf_8_from_iso_8859_1 +def_to_utf_8_from_shift_jis +def_uconv_convert_if_can +def_yes_clean_other_accessor +def_yes_other_accessor +default +default= +default_acl +default_argc_limit +default_argv +default_bindir +default_cert_path +default_dir +default_event_sources +default_exec_format +default_executable +default_external +default_external= +default_gem? +default_id_conv +default_imap_port +default_imaps_port +default_internal +default_internal= +default_key_path +default_load_limit +default_ole_types +default_options +default_parser +default_parser= +default_path +default_pop3_port +default_pop3s_port +default_port +default_proc +default_proc= +default_record_separator +default_record_separator= +default_rubygems_dirs +default_safe_level +default_sources +default_specifications_dir +default_src_encoding +default_ssl_context +default_ssl_port +default_submission_port +default_system_path +default_system_path= +default_title= +default_tls_port +default_value +defaults +defaults_str +define +define_aliases +define_finalizer +define_head +define_method +define_module_function +define_singleton_method +define_tail +define_task +defined_class +defined_in? +definition +definition_lists +deflate +degree +del_jobs_status +del_status_line +delch +delegate +delete +delete! +delete? +delete_all +delete_at +delete_attribute +delete_element +delete_field +delete_if +delete_key +delete_legacy_args +delete_namespace +delete_observer +delete_observers +delete_passwd +delete_unless_alive +delete_value +delete_worker +deleted? +deleteln +denominator +dep +depend_rules +dependencies +dependencies_ok? +dependency +dependency_order +dependent_gems +dependent_specs +deprecate +depth +deq +dequote +desc +descend +descendant_or_self +description +description= +deserialize +dest_directory +dest_latest_specs_index +dest_prerelease_specs_index +dest_specs_index +destination_encoding +destination_encoding_name +det +det_e +detach +detached +detached= +detached? +detect +detect_encoding +detect_gemdeps +detect_implicit +determinant +determinant_bareiss +determinant_e +determine_time +dev +dev_major +dev_minor +development +development_dependencies +dfdxi +dh_compute_key +diagonal +diagonal? +diagonalize +died +diff +diff= +difference +digest +digest! +digest_algorithm +digest_length +digests +dir +dir_config +dir_stack +direct_ancestors +directory +directory? +dirname +dirs +dirs= +disable +disable_close +disable_default_gem_server +disable_ssl +disable_starttls +disable_tls +disasm +disassemble +disconnect +disconnected? +disconnecting +dispatch +dispid +display +display? +display_attributes +display_c_call +display_c_call? +display_class +display_error_message +display_method +display_name +display_names +display_page +display_page_list +display_prerequisites +display_process_id +display_process_id? +display_tasks_and_comments +display_thread_id +display_thread_id? +disposition +div +divide +divmod +dlload +dlopen +dlunwrap +dlwrap +dn +dn= +do_GET +do_HEAD +do_OPTIONS +do_POST +do_aliases +do_attrs +do_boot_defclass +do_classes +do_configuration +do_constants +do_define_class +do_define_class_under +do_define_module +do_define_module_under +do_finish +do_helo +do_includes +do_methods +do_missing +do_modules +do_not_reverse_lookup +do_not_reverse_lookup= +do_nothing +do_parse +do_reply +do_rpc +do_singleton_class +do_sort +do_start +do_struct_define_without_accessor +do_validate +do_validate= +do_write +doc +doc_dir +doc_root +doc_stats +doctor +doctype +doctype? +doctype_end +document +document_children +document_children= +document_order +document_self +document_self= +document_self_or_methods +document_to_str +documentation_page +documentation_search +documentation_source +documented? +domain +done +done? +done_adding +done_documenting +done_documenting= +done_installing +done_installing_hooks +dont_rename_initialize +dot_pat +dot_pat_str +double +double_fig +doupdate +downcase +downcase! +download +download_reporter +download_to_cache +downto +dowrite +drop +drop_while +dry_run +dsa_sign_asn1 +dsa_verify_asn1 +dst? +dummy? +dummy_makefile +dump +dump_call +dump_coder +dump_default_options +dump_ivars +dump_list +dump_response +dump_stream +dup +dynamic_width +dynamic_width_stty +dynamic_width_tput +e2mm_message +each +each2 +each_active_object +each_address +each_ancestor +each_attribute +each_byte +each_capitalized +each_capitalized_name +each_certificate +each_char +each_child +each_classmodule +each_codepoint +each_cons +each_const +each_constant +each_data +each_element +each_element_with_attribute +each_element_with_text +each_entry +each_extend +each_filename +each_header +each_include +each_index +each_installed_parser +each_installed_writer +each_key +each_line +each_localized_path +each_mail +each_method +each_name +each_name_of +each_object +each_option +each_pair +each_parent +each_prime +each_recursive +each_resource +each_response_header +each_section +each_slice +each_source +each_strongly_connected_component +each_strongly_connected_component_from +each_sublocale +each_value +each_with_index +each_with_object +each_with_something +echo +echo= +echo? +edit_path +egid +egid= +ehlo +eid +eigen +eigensystem +eigenvalue_matrix +eigenvalues +eigenvector_matrix +eigenvector_matrix_inv +eigenvectors +ele +element +element= +element_initialize_arguments? +element_name +elementdecl +elementdecl? +elements +elements_to_f +elements_to_i +elements_to_r +emacs_editing_mode +emacs_editing_mode? +email +email_to_name +emailbx +emit_coder +emphasis +empty +empty? +empty_content? +empty_marshal_checksum +empty_marshal_data +enable +enable_close +enable_config +enable_ssl +enable_starttls +enable_starttls_auto +enable_tls +enabled? +enc_key +enclose +enclosed? +enclosure_dependencies +encode +encode! +encode64 +encode_fallback +encode_multipart_form_data +encode_re +encode_str +encode_token +encode_utf7 +encode_with +encode_www_form +encode_www_form_component +encoded +encoding +encoding= +encoding_updated +encrypt +end +endElement +end_accepting +end_document +end_element +end_element? +end_mapping +end_prefix_mapping +end_seen? +end_sequence +end_stream +end_transport +end_with? +ended? +endgrent +endpwent +engines +england +enhance +enhance_with_matching_rule +enq +ensure_dependencies_met +ensure_dependency +ensure_gem_subdirectories +ensure_loadable_spec +ensure_required_ruby_version_met +ensure_required_rubygems_version_met +ensure_xml_content +entities +entity +entity? +entity_class +entity_expansion_count +entity_expansion_limit +entity_expansion_limit= +entity_expansion_text_limit +entity_expansion_text_limit= +entitydecl +entitydecl? +entries +entry_details +entry_versions +enum_for +env_shebang +env_table +environment +eod +eof +eof? +eos? +eql? +equal? +equality_relational_compare +erf +erfc +errno +error +error? +error_bytes +error_char +error_message +error_string +errors +errs +escape +escape8bit +escapeElement +escapeHTML +escape_element +escape_form +escape_html +escape_path +escape_re +escape_userpass +esmtp +esmtp? +euid +euid= +eval +eval_history +eval_history= +eval_input +evaluate +even? +event +event? +event_arg +event_interface +event_type +events +examine +exception +exception_class +exception_details +exchange +exclude +exclude_end? +exclusive +exec +exec_format +exec_if +executable +executable= +executable? +executable_real? +executables +executables= +execute +exist? +exists? +exit +exit! +exit_code +exit_value +exited? +exitstatus +exp +exp! +expand +expand_class +expand_environ +expand_hexstring +expand_name +expand_pair +expand_path +expand_ref_in +expand_tabs +expand_value +expanded_name +expect +expected +expire +expired? +expires +expires= +exponent +export +expr +expunge +ext +extend +extend_object +extend_table +extended +extends +extension +extension? +extension_build_error +extensions +extensions= +extern +external +external_aliases +external_encoding +external_id +extname +extra_args +extra_args= +extra_chain_cert +extra_rdoc_files +extra_rdoc_files= +extract +extract_call_seq +extract_comment +extract_files +extract_reference +facility +fail +failed +false +family +family_addrinfo +fast_generate +fastmode= +fatal +fatal? +fault +faultCode +faultString +fcntl +fdatasync +fdiv +feed +feed_info +feed_subtype +feed_type +feed_version +fetch +fetch_file +fetch_http +fetch_https +fetch_internal +fetch_path +fetch_server +fetch_size +fetch_spec +fetcher +fetcher= +fiddle? +field +field? +field_row? +field_size_limit +fields +file +file= +file? +file_create +file_dir +file_field +file_input? +file_list_string +file_name +file_output +file_path +file_stat +filename +filename_quote_characters +filename_quote_characters= +fileno +files +files= +files_hash +files_so_far +fill +fill_breakable +fill_rbuff +filter +filter= +filter_backtrace +filter_methods +final +finalize +find +find_alias_comment +find_all +find_all_by_name +find_all_satisfiers +find_all_template +find_ancestor_local_symbol +find_attr_comment +find_attribute +find_attribute_named +find_body +find_by_name +find_by_path +find_c_enclosure +find_class +find_class_comment +find_class_method_named +find_class_named +find_class_named_from +find_class_or_module +find_command +find_command_possibilities +find_const_comment +find_constant_named +find_data +find_enclosing_module_named +find_encoding +find_executable +find_external_alias +find_external_alias_named +find_file_named +find_files +find_files_for_gem +find_first_recursive +find_gem +find_gems_with_sources +find_header +find_home +find_in_cache +find_in_unresolved +find_in_unresolved_tree +find_inactive_by_path +find_include_file +find_index +find_instance_method_named +find_ivars +find_library +find_local_symbol +find_location +find_method +find_method_named +find_methods +find_modifiers +find_module_named +find_name +find_override_comment +find_pager_jruby +find_paths +find_proxy +find_rakefile_location +find_reverse_dependencies +find_runnable +find_spec +find_spec_by_name_and_version +find_store +find_symbol +find_symbol_module +find_system_command +find_text_page +find_type +find_unique +find_unresolved_default_spec +finger +finish +finish_page_dir +finish_resolve +finished +finished? +finite? +fips_mode= +first +first? +first_lineno +fit_error +fit_exponential +fit_linear +fit_power +fix +fix_basic_object_inheritance +fix_syck_default_key_in_requirements +fixed_encoding? +flags= +flash +flat_map +flatten +flatten! +flock +floor +flow +flunk +flush +flush_buffer +flush_left +flush_next_in +flush_next_out +flush_sessions +fnmatch +fnmatch? +following +following_node_of +footnotes +for +for_cache +for_current_gems +for_fd +for_files +for_matching_files +for_spec? +force +force_documentation +force_documentation= +force_encoding +force_output +force_quotes? +force_update +foreach +fork +form +form_data= +format +format= +format_date +format_datetime +format_executable +format_line_num +format_message +format_severity +format_text +format_time +format_trace_flags +formatted_program_filename +formatter +found +frac +fragment +fragment= +free +free= +freeze +frexp +friday? +friendly_path +from +from_hash +from_list +from_module +from_name +from_path +from_prime_division +from_specs +from_yaml +front +frozen? +fsync +ftype +fu_blksize +fu_default_blksize +fu_stream_blksize +fu_windows? +full_comment +full_gem_path +full_name +full_name= +full_old_name +full_spec +fully_documented? +fully_expanded_name +function +gamma +garbage_collect +gather_dependencies +gather_files +gcd +gcdlcm +gem +gem_dir +gem_file_list +gem_home +gem_original_require +gem_paths +gem_repository? +gem_spec +gemdirs +gems_dir +gems_to_install +gen_multicall +gen_relative_url +gen_sub_directories +gen_url +generate +generate_bin +generate_bin_script +generate_bin_symlink +generate_class +generate_class_files +generate_default_dirs +generate_event +generate_file_files +generate_index +generate_key +generate_key! +generate_line +generate_name +generate_page +generate_prime +generate_rdoc +generate_ri +generate_servlet_not_found +generate_servlet_root +generate_table_of_contents +generate_tag +generate_windows_script +generation_hook +generator +generator_descriptions +generator_for +generator_options +generic? +genspace +get +get2 +get_all_gem_names +get_all_gem_names_and_versions +get_attribute +get_attribute_ns +get_attributes +get_bool +get_byte +get_candidate_gems +get_class_or_module +get_class_specification +get_constant +get_constant_with_optional_parens +get_credentials +get_default_handler +get_definition +get_description +get_elements +get_fields +get_file_and_line_from_caller +get_first +get_gems_to_cleanup +get_group +get_hosts_path +get_included +get_initial_token +get_instance +get_key_string +get_line +get_listeners +get_metadata +get_methods +get_namespace +get_no_proxy_from_env +get_one_gem_name +get_one_optional_argument +get_option +get_passwd +get_path +get_platform_from_requirements +get_primary_gems +get_print +get_procs +get_proxy_from_env +get_renewer +get_resolv_info +get_response +get_screen_size +get_service_hook +get_sorted_module_list +get_svninfo +get_symbol_or_name +get_tagged_response +get_text +get_thread +get_tk +get_tk_until +get_tkread +get_valid_ip +get_value +get_version_from_requirements +getacl +getaddress +getaddress_orig +getaddresses +getaddrinfo +getbinaryfile +getbkgd +getbyte +getc +getch +getdir +getegid +geteuid +getgid +getgm +getgrent +getgrgid +getgrnam +gethostbyaddr +gethostbyname +gethostname +getlocal +getlogin +getmouse +getname +getnameinfo +getnames +getok +getopts +getpeereid +getpeername +getpgid +getpgrp +getpriority +getpty +getpwent +getpwnam +getpwuid +getquota +getquotaroot +getresource +getresources +getrlimit +gets +getservbyname +getservbyport +getservername +getsid +getsockname +getsockopt +getstr +getter +gettextfile +getuid +getutc +getwd +gid +gid= +github +glob +global_variables +gm +gmt? +gmt_offset +gmtime +gmtoff +grant_privilege +great_job +greeting +gregorian +gregorian? +gregorian_leap? +grep +group +group= +group_by +group_entries +group_queue +group_sub +groups +groups= +grpowned? +gsub +gsub! +guard_inspect_key +guess +guess_type +guess_type_if_need +guid +gunzip +gzip +gzip_to +h +handle +handle_arguments +handle_attr +handle_class_module +handle_constants +handle_directive +handle_ifdefs_in +handle_interrupt +handle_method +handle_options +handle_pipe +handle_rdoc_link +handle_singleton +handle_special_CROSSREF +handle_special_HARD_BREAK +handle_special_HYPERLINK +handle_special_RDOCLINK +handle_special_SUPPRESSED_CROSSREF +handle_special_TIDYLINK +handle_tab_width +handler +handler= +handlers +handles? +hard_break +hasChildNodes +hasOnlyOneChild +has_attributes? +has_chain? +has_colors? +has_elements? +has_expires? +has_key? +has_name? +has_next? +has_rdoc +has_rdoc= +has_rdoc? +has_text? +has_unit_tests? +has_value? +hash +hash? +hash_old +have_author? +have_children_elements +have_const +have_content? +have_framework +have_func +have_header +have_library +have_macro +have_option? +have_rakefile +have_rdoc_4_plus? +have_required_elements? +have_required_values? +have_run? +have_struct_member +have_type +have_var +have_xml_content? +head +head2 +header +header? +header_convert +header_converters +header_row? +headers +headers= +height= +helo +help +helpcontext +helpfile +helpstring +here? +hermitian? +hessenberg_to_real_schur +hex +hexdigest +hexdigest! +hexencode +hidden +hierarchical? +history_file +history_file= +hkey +hmac_md5 +home +home= +home_dir +home_workspace +homepage +hook +host +host= +hostname +hostname= +hour +hour= +href +href= +html +html_escape +html_list_name +html_name +html_tags +hton +http_date +http_default_port +http_error +http_header +http_header_extra +http_last_response +http_resp +http_url +http_version +http_write +httpd +httpdate +https? +https_default_port +hyperlink_all +hypot +i +i_suck_and_my_tests_are_order_dependent! +icon +icon= +iconv +id +id2name +ident +identical? +identity +idle +idle_done +idlok +if_current_indent_equal +if_modified_since +iflush +ignore +ignore_dependencies +ignore_eof +ignore_eof? +ignore_sigint +ignore_sigint? +ignore_unknown_element +ignore_unknown_element= +ignore_whitespace_nodes +ignored? +imag +image +image_button +image_height +image_size +image_size= +image_width +imaginary +img +implemented_ole_types +implicit +implicit_end +import +import_function +import_symbol +import_value +in6_addr +in_addr +in_background +in_files +in_namespace +in_path? +in_service? +in_transaction +in_transaction_wr +in_tt? +inactivate +inc +inch +include +include? +include_file +include_path +included +included_modules +includes +incompatible_argument_styles +incomplete_input? +increment_io +indent +indent_text +indentation +index +index_classes +index_in_parent +index_methods +index_pages +indices +indir +infinite? +infinite_length +infinity? +inflate +info +info? +inherit_convert_attr_reader +inherited +inherited_array_reader +inherited_base +inherited_hash_reader +inherited_reader +init +init_color +init_comments +init_converters +init_headers +init_pair +init_parsers +init_screen +init_separators +init_tags +init_with +init_with_ary +init_with_hash +initgroups +initial_start_RDF +initial_start_entry +initial_start_feed +initial_start_rss +initialize +initialize_copy +initialize_have_children_elements +initialize_http_header +initialize_methods_etc +initialize_pattern +initialize_query +initialize_regexp +initialize_tracer +initialize_variables +inject +inject_into_list +inline +inline_html? +inline_other? +inline_other_base64? +inline_other_text? +inline_other_xml? +inline_text? +inline_xhtml? +inner_product +ino +inplace_mode +inplace_mode= +input +input= +input? +ins +insch +insecure_method? +insert +insert_after +insert_before +insert_output +insert_text +insertln +inspect +inspect? +inspect_mode +inspect_mode= +inspect_sockaddr +inspect_value +install +install_accessor_base +install_acl +install_alias_method +install_class_name +install_date_element +install_default_gems +install_default_specs +install_dublin_core +install_element +install_executables +install_extend_commands +install_file +install_from_gemdeps +install_gem +install_gem_user +install_get_attribute +install_get_text_element +install_have_attribute_element +install_have_child_element +install_have_children_element +install_id_conv +install_image_favicon +install_image_item +install_indicies +install_into +install_lib +install_list +install_model +install_must_call_validator +install_ns +install_rdoc +install_siginfo_handler +install_specs +install_system_commands +install_taxo_topic +install_taxo_topics +install_text_element +install_update_defaults_str +installation_satisfies_dependency? +installed? +installed_docs +installed_gems +installed_specs +instance +instance_attributes +instance_delegate +instance_eval +instance_exec +instance_method +instance_method_list +instance_methods +instance_of? +instance_variable_defined? +instance_variable_get +instance_variable_set +instance_variables +instruction +instruction? +instructions +int +int_from_prime_division +integer +integer? +integer_writer +interactive +intern +internal_encoding +interrupt +intersection +inv +invalidate_memoized_attributes +inverse +invert +invert! +investigation +invkind +invoke +invoke_kind +invoke_service +invoke_service_command +invoke_task +invoke_thread +invoke_with_build_args +io +io? +ioctl +ioflush +ip +ip6_arpa +ip6_int +ip? +ip_address +ip_address_list +ip_pktinfo +ip_port +ip_unpack +ipv4? +ipv4_compat +ipv4_compat? +ipv4_loopback? +ipv4_mapped +ipv4_mapped? +ipv4_multicast? +ipv4_private? +ipv6? +ipv6_linklocal? +ipv6_loopback? +ipv6_mc_global? +ipv6_mc_linklocal? +ipv6_mc_nodelocal? +ipv6_mc_orglocal? +ipv6_mc_sitelocal? +ipv6_multicast? +ipv6_pktinfo +ipv6_pktinfo_addr +ipv6_pktinfo_ifindex +ipv6_sitelocal? +ipv6_to_ipv4 +ipv6_unique_local? +ipv6_unspecified? +ipv6_v4compat? +ipv6_v4mapped? +ipv6only! +irb +irb_abort +irb_at_exit +irb_context +irb_exit +irb_level +irb_load +irb_name +irb_path +irb_require +isEqual +is_a? +is_alias_for +is_version_1_2? +isatty +isdst +iseuc +isjis +iso8601 +issetugid +issjis +issuer +issuer= +issuer_certificate +issuer_certificate= +issuer_of +isutf8 +it +italy +item +items +iterator? +iv= +j +jacobian +jd +jisx0301 +jj +jobs +jobs_exist? +jobs_status +join +join_nowait +jruby? +json_creatable +json_creatable? +json_create +json_index +julian +julian? +julian_leap? +kconv +keep_alive +keep_alive? +keep_alive_timeout +keep_clean +keep_if +key +key= +key? +key_len= +key_path +keyname +keypad +keypad= +keys +keys_with_inspector +kill +kill_job +kind_of? +known_class? +known_classes +l +label +labels +lambda +lambda? +lang +last +lastBuildDate= +last_comment +last_description +last_error +last_error= +last_line +last_match +last_modified +last_request +last_response +last_response_code +last_update +last_update= +last_value +lastresp +latest_rubygems_version +latest_spec_for +latest_specs +latest_version? +latest_version_for +launch +launch_worker +lazy +lchmod +lchown +lcm +ld +ldexp +leap? +length +let +level +level= +level_notifier +level_notifier= +levenshtein_distance +lex +lgamma +lib_dirs_glob +lib_files +lib_path +library_name +libs +libyaml_version +license +license= +licenses +licenses= +limit +line +line_buffer +line_index +line_numbers +line_trace_all +line_trace_specify +line_width +lineno +lineno= +lines +linger +link +link_files +link_to +list +list_end_for +list_files_in_directory +list_index +list_item_from +list_item_start +list_known_classes +list_methods_matching +list_type +list_width +listen +listener +listener= +listeners +literalize +ljust +ln +ln_s +ln_sf +load +load_all +load_and_instantiate +load_api_keys +load_cache +load_call +load_cert +load_certificate +load_class +load_class_data +load_data +load_default_cert +load_default_key +load_default_options +load_defaults +load_documents +load_env_plugins +load_file +load_gemdeps +load_imports +load_key +load_method +load_methods_matching +load_mime_types +load_modules +load_options +load_page +load_path_insert_index +load_plugin_files +load_plugins +load_private_key +load_public_key +load_rakefile +load_rdoc +load_response +load_spec +load_specs +load_stream +load_variable_map +load_yaml +loaded_from +loaded_from= +loaded_specs +loader +loadpath +local +local? +local_address +local_host +local_name +local_name= +local_port +local_variables +locale +locale= +locale_charmap +localtime +location +location_of_caller +locations +lock +locked? +log +log! +log10 +log10! +log2 +log2! +log= +logger +logger= +logging +login +logo +logo= +logout +long +long_name +look_for_directives_in +lookup +lookup_in_scope +lookup_method +lookup_prerequisite +lookup_ring +lookup_ring_any +lookup_server +loop +lower +lower_triangular? +ls +lstat +lstrip +lstrip! +lsub +ludecomp +lup +lup_decomposition +lusolve +magnitude +mail +mailfrom +mails +main +main= +main_irb +main_loop +main_page +main_thread +main_type +major +major_version +make +make_affine! +make_command +make_compiler +make_destination_dirs +make_entry +make_expires +make_feed +make_link +make_message +make_my_diffs_pretty! +make_passwd +make_regexp +make_sources +make_start_tag +make_switch +make_symlink +make_temp_directories +make_thread_list +make_time +make_tuple +make_variable_map +make_xml_stylesheets +makedirs +maker +maker_target +makers +malloc +malloc_allocated_size +malloc_allocations +manage_owners +map +map! +map2 +map= +map_gems_to_specs +mark_version +markup +markup_code +marshal_dump +marshal_load +marshal_version +mask +mask! +mask= +mask_protected_sequences +match +match? +match_platform! +match_platform? +match_to +match_to_consume +matched +matched? +matched_size +matches? +matches_for_glob +matches_spec? +matching_specs +matching_word_pairs +math? +math_mode +math_mode= +max +max= +maxConnections +max_age +max_by +max_flag_count +max_flag_count= +max_size +maxgroups +maxgroups= +maxwidth +maxx +maxy +maybe_xml? +mday +mdtm +measure +media_subtype +member +member? +members +memberwise +merge +merge! +merge0 +merge_key +merge_options +merge_path +merged? +message +message_loop +meta +meta_vars +metadata +meth +method +methodCall +methodCall_document +methodName +methodResponse +methodResponse_document +method_added +method_defined? +method_document +method_file +method_id +method_list +method_missing +method_name +method_removed +method_type +method_undefined +methods +methods_by_type +methods_hash +methods_matching +mime_split +mime_type +min +min= +min_by +minimum +minmax +minmax_by +minor +minor_version +minute +minute= +missing_dependencies +mjd +mkcol +mkdir +mkdir_p +mkmf +mkpath +mktime +mktmpdir +mname +mode +models +modifiable +modifieer +modsort +module +module? +module_eval +module_exec +module_function +module_names +modules +modules_hash +modulo +mon +mon= +mon_check_owner +mon_enter +mon_enter_for_cond +mon_exit +mon_exit_for_cond +mon_initialize +mon_synchronize +mon_try_enter +monday? +month +month= +month_days +mount +mount_proc +mountpoint? +mouseinterval +mousemask +move +mri? +msg +msg2str +mtime +mtime= +mu_lock +mu_locked? +mu_pp +mu_pp_for_diff +mu_synchronize +mu_try_lock +mu_unlock +mul +mult +multicall +multicall2 +multicall2_async +multicall_async +multicall_fault +multipart? +multipart_form +multitask +must_C_version +must_be +must_be_close_to +must_be_empty +must_be_instance_of +must_be_kind_of +must_be_nil +must_be_same_as +must_be_silent +must_be_within_delta +must_be_within_epsilon +must_call_validators +must_equal +must_include +must_match +must_output +must_raise +must_respond_to +must_send +must_throw +mv +n_bytes +n_jobs +n_mails +name +name= +name_for_path +name_list +name_path +name_prefix +name_regexp +name_tuple +named_captures +names +namespace +namespace= +namespace_context +namespace_context= +namespace_of +namespace_uri +namespaces +namespaces= +namesplit +nan? +nary +native +nc +ndata +need_base64_encode? +need_initialize_variables +need_keeper? +need_parent? +need_source_encoding_update? +need_tar +need_tar_bz2 +need_tar_gz +need_zip +needed? +needs +nest +nesting +net_http +new +new2 +new3 +new_alias_name +new_comment +new_cond +new_default_spec +new_from_hash +new_from_uri +new_internet_message_io +new_name +new_ntoh +new_offset +new_ostruct_member +new_scope +new_seed +new_session +new_spec +new_start +new_test +new_toplevel +new_with +new_with_uri +new_with_value_if_need +newline +newobj +next +next! +next_current +next_day +next_element +next_month +next_sibling= +next_sibling_node +next_to +next_token +next_update +next_update= +next_values +next_wait +next_words_on_error +next_year +nil? +nkf +nl +nlink +nlsolve +nlst +nmake_found? +no_proxy? +nocbreak +nocrmode +nodeMustBe +nodeName +nodeType +nodeValue +node_type +nodelay= +nodoc +noecho +non_aliases +non_nil_attributes +non_options +none? +nonl +nonzero? +noop +noraw +norm +normal? +normalize +normalize! +normalize_comment +normalize_path +normalize_rss +normalize_searching_criteria +normalize_space +normalize_uri +normalize_yaml_input +normalized +normalized_file_list +not +not_after +not_after= +not_before +not_before= +not_found +not_need_to_call_setup_maker_variables +not_set_name +not_set_required_variables +notation +notationdecl +notationdecl? +notations +note +note_for +notes +notifiers +notify +notify? +notify_event +notify_observers +notwice +noutrefresh +now +nowrite +nowrite_flag +npn_protocol +npn_protocols +npn_select_cb +nread +ns_declarations +nsec +ntop +null +null? +num_files +num_waiting +number +numerator +obj +object +object_address_group +object_class +object_group +object_id +object_maker +oct +odd? +of +off +off_event +off_tags +offset +offset_vtbl +oflush +oid +oid= +ok? +ok_to_remove? +old_enc= +old_name +ole_activex_initialize +ole_classes +ole_free +ole_func_methods +ole_get_methods +ole_initialize +ole_method +ole_method_help +ole_methods +ole_obj_help +ole_put_methods +ole_query_interface +ole_reference_count +ole_respond_to? +ole_show_help +ole_type +ole_type_detail +ole_typelib +ole_types +ole_uninitialize +omit_headings_below +on +on_attr_charref +on_attr_charref_hex +on_attr_entityref +on_attr_value +on_attribute +on_cdata +on_chardata +on_charref +on_charref_hex +on_connect +on_curve? +on_default +on_entityref +on_error +on_etag +on_event +on_event_with_outargs +on_head +on_parallel_worker? +on_stag +on_stag_end +on_stag_end_empty +on_tags +on_tail +on_windows? +on_xmldecl_encoding +on_xmldecl_end +on_xmldecl_standalone +on_xmldecl_version +one? +ongoing_visibility= +only_signed +only_trusted +op_dir +opaque +opaque= +open +open! +open? +open_and_lock_file +open_logfile +open_message_stream +open_server +open_timeout +open_uri_or_path +open_uri_original_open +opendir +opened? +option_list +option_parser +optional? +options +options= +options_of +optname +ord +order +order! +ordering +ordering= +ordinal +orig_initialize +orig_name +orig_name= +original_dir +orthogonal? +os +os_code +other_elements +others_possible? +out +out_of_date? +out_of_line? +outdated +output +output= +output? +output_encoding +output_encoding= +output_flag_file +output_name +output_query_results +output_versions +outputdir +outs +owned? +owner +p +pack +pack_sockaddr_in +pack_sockaddr_un +package_dir +package_dir_path +package_files +package_name +packdw +packqw +padding= +page +page-ChangeLog +page-NEWS +page_dir +page_file +page_name +paging? +pair +pair_content +pair_number +para +paragraph +paragraph_limit +paragraphs +parallelize_me! +param +param_list +param_seq +parameters +params +params= +params_ok? +paranoid +parent +parent= +parent? +parent_file_name +parent_name +parse +parse! +parseMethodCall +parseMethodResponse +parse_alias +parse_arg +parse_args +parse_attr +parse_attr_accessor +parse_bind_options +parse_call_parameters +parse_class +parse_comment +parse_comment_tomdoc +parse_config +parse_config_lines +parse_constant +parse_content_type +parse_ctype +parse_dn +parse_dot_doc_file +parse_entries +parse_extend +parse_file +parse_files +parse_files_matching +parse_form_data +parse_header +parse_headers +parse_helper +parse_include +parse_int +parse_line +parse_make_command_line +parse_meta_attr +parse_meta_method +parse_method +parse_method_dummy +parse_method_or_yield_parameters +parse_method_parameters +parse_mode +parse_module +parse_name +parse_openssl +parse_pasv_ipv4_host +parse_pasv_ipv6_host +parse_pasv_port +parse_pi_content +parse_printf_format +parse_query +parse_qvalues +parse_range_header +parse_require +parse_rescue +parse_rfc2253 +parse_set_cookie +parse_set_cookies +parse_sig +parse_signature +parse_source +parse_statements +parse_stream +parse_struct_signature +parse_subtree +parse_symbol_arg +parse_symbol_in_arg +parse_task_string +parse_time +parse_top_level_statements +parse_types +parse_url +parse_visibility +parse_yield +parseable? +parser +parsers +partition +parts +pass +passed? +passive +passwd +password +password= +password_field +patch +path +path= +path_info +path_ok? +path_query +path_separator +path_warning +pathmap +pathmap_explode +pathmap_partial +pathmap_replace +paths +paths= +pattern +pbkdf2_hmac +pbkdf2_hmac_sha1 +peek +peek_read +peek_tk +peek_token +peek_values +peep +peer_cert +peer_cert_chain +peeraddr +peg_parse +pem_files_in +pending +pending_interrupt? +percent_doc +permanent_link= +permanent_link? +permutation +permutation? +permute +permute! +pfamily +phase +pi +pick_best! +pid +pipe +pipe? +pipeline +pipeline_r +pipeline_rw +pipeline_start +pipeline_w +pivots +pkcs5_keyivgen +plain +plain_html +platform +platform= +platforms +platforms= +plural_forms +point +point_conversion_form +point_conversion_form= +pointer +pointer= +polar +pop +pop_inspect_key +pop_token +pop_workspace +popd +popdir +popen +popen2 +popen2e +popen3 +popup_menu +port +port= +pos +pos= +position +positive_integer_writer +post +post2 +post_build +post_build_hooks +post_connection_check +post_form +post_install +post_install_hooks +post_install_message +post_match +post_process +post_processors +post_reset +post_reset_hooks +post_uninstall +post_uninstall_hooks +power +power! +pp +pp_hash +pp_object +ppid +ppx +pre_input_hook +pre_input_hook= +pre_install +pre_install_checks +pre_install_hooks +pre_match +pre_reset +pre_reset_hooks +pre_uninstall +pre_uninstall_hooks +preceding +preceding_node_of +precs +pred +predicate +predicate_to_string +preference +prefetch +prefix +prefix_of +prefixes +prepend +prepend_features +prepended +preprocess +prerelease +prerelease? +prerequisite_tasks +prerequisites +pretty +pretty_generate +pretty_inspect +pretty_name +pretty_new_name +pretty_old_name +pretty_print +pretty_print_cycle +pretty_print_inspect +pretty_print_instance_variables +prev_day +prev_month +prev_words_on_error +prev_year +previous= +previous_element +previous_period_end +previous_sibling= +previous_sibling_node +pride +primary +primary_server +prime? +prime_division +prime_fasttest? +primes +primes_so_far +primitive_convert +primitive_errinfo +print +print_alias +print_attribute +print_class +print_constant +print_dependencies +print_file +print_method +print_module +print_profile +print_rakefile_directory +print_usage +printf +printn +priority +priority= +private +private? +private_class_method +private_constant +private_decrypt +private_encrypt +private_instance_methods +private_key +private_key= +private_key? +private_method_defined? +private_methods +problem +proc +procdest +process +process_args +process_based_port +process_controller +process_directive +process_line +process_options +processingInstruction +processing_instruction +product +progid +progids +progname +program_name +progress +progress_reporter +proj_id +project +prompt +prompt_c +prompt_i +prompt_mode +prompt_mode= +prompt_n +prompt_s +prompting? +proper_subset? +proper_superset? +propfind +proppatch +protectable +protected +protected_instance_methods +protected_method_defined? +protected_methods +proto +protocol +provide +proxy +proxy2 +proxy2_async +proxy? +proxy_address +proxy_async +proxy_auth_get +proxy_basic_auth +proxy_class? +proxy_from_env +proxy_from_env? +proxy_pass +proxy_port +proxy_user +proxyaddr +proxyport +prune +psych_to_yaml +psych_yaml_as +ptr +ptr= +pubDate +pubDate= +pubid +public +public? +public_class_method +public_constant +public_decrypt +public_encrypt +public_instance_method +public_instance_methods +public_key +public_key= +public_key? +public_method +public_method_defined? +public_methods +public_send +puke +pull +pull_event +purpose= +push +push_inspect_key +push_workspace +pushd +pushdir +put +put_status +put_string +putback +putbinaryfile +putc +puts +puttextfile +pwd +qdval +qop +query +query= +query_string +quick +quick_gem +quick_spec +quiet +quiet= +quiet? +quit +quit_called +quit_workers +quo +quote +quote_char +quote_string +quoted +r +racc_accept +racc_e_pop +racc_next_state +racc_print_stacks +racc_print_states +racc_read_token +racc_reduce +racc_shift +racc_token2str +radio_button +radio_group +raise +raise_for_undefined_entity? +raise_if_conflicts +raised_exception +rake_check_options +rake_extension +rake_merge_option +rake_original_const_missing +rake_original_time_compare +rake_output_message +rake_require +rake_system +rakefile +rakefile_location +rand +random_bytes +random_iv +random_key +random_number +random_string +range +range= +range_length +rank +rank_e +rassoc +rationalize +raw +raw! +raw_cookie +raw_cookie2 +raw_data +raw_encoding +raw_header +raw_path +rb_files_in +rb_scan_args +rc +rc? +rcptto +rcptto_list +rdev +rdev_major +rdev_minor +rdoc +rdoc_dir +rdoc_files +rdoc_include +rdoc_installed? +rdoc_options +rdoc_options= +rdoc_target +rdoc_task_description +rdoc_task_name +rdoc_version +re_exchange +re_exchangeable? +re_sign +read +read_all +read_bin +read_binary +read_body +read_body_0 +read_cache +read_checksums +read_directive +read_documentation_modifiers +read_file +read_from_cmdline +read_i +read_multipart +read_nonblock +read_s +read_s_expand +read_smime +read_status_line +read_timeout +read_timeout= +read_type_class +read_with_substitution +readable? +readable_after_eof? +readable_real? +readagain_bytes +readbyte +readchar +readline +readlines +readlink +readpartial +ready +ready? +real +real? +real_file +real_load +realdirpath +realloc +really_verbose +realm +realpath +realtime +reason +reason_phrase +receive +receive_responses +received_nodoc +receiver +recipients +record_entity_expansion +record_location +record_response +record_separator +record_task_metadata +recover +rect +rectangular +recurse +recurse_proc +recv +recv_io +recv_nonblock +recv_response +recvfrom +recvfrom_nonblock +recvmsg +recvmsg_nonblock +redirect? +redirect_to_directory_uri +redirector +redisplay +reduce +reduce_to_hessenberg +reenable +ref +reference +references +refine +refresh +refresh_line +refute +refute_empty +refute_equal +refute_in_delta +refute_in_epsilon +refute_includes +refute_instance_of +refute_kind_of +refute_match +refute_nil +refute_operator +refute_path_exists +refute_predicate +refute_respond_to +refute_same +regexp +regist +regist_server +register +register_command +register_default_spec +register_empty +register_spec_type +register_uri +registered +registry +registry= +regular? +rehash +reject +reject! +relative? +relative_name +relative_path_from +release +reload +remainder +remote? +remote_address +remote_ip +remove +removeChild +removeWhitespacesAndComments +remove_all +remove_by_name +remove_cache_file +remove_callback +remove_callback_internal +remove_cdecl_callback +remove_class_variable +remove_coding_comment +remove_comment +remove_commented_out_lines +remove_const +remove_dir +remove_entry +remove_entry_secure +remove_executables +remove_file +remove_from_documentation? +remove_handler +remove_installed! +remove_instance_variable +remove_invisible +remove_method +remove_nodoc +remove_nodoc_children +remove_old_bin_files +remove_old_lib_files +remove_option +remove_owners +remove_private +remove_private_comment +remove_private_comments +remove_response_handler +remove_server +remove_siginfo_handler +remove_spec +remove_specs_unsatisfied_by +remove_stdcall_callback +remove_token_listener +remove_unparseable +remove_unresolved_default_spec +rename +render +render_template +renegotiation_cb +renew +reopen +reorganize +repair_command +repeated_combination +repeated_permutation +replace +replace! +replace_child +replace_with +replacement +replacement= +replicate +reply +reply_service +report +report_attributes +report_class_module +report_constants +report_methods +represent_map +represent_object +represent_scalar +represent_seq +req +request +request_body_permitted? +request_get +request_head +request_http_version +request_line +request_method +request_post +request_time +request_uri +requester +requests +require +require_path +require_path= +require_path_info? +require_paths +require_relative +required_attribute? +required_attributes +required_element? +required_prefix +required_ruby_version +required_ruby_version= +required_rubygems_version +required_rubygems_version= +required_uri +required_variable_names +required_variables_are_set? +requirement +requirements +requirements= +requirements_list +requires +rerdoc_task_description +rerdoc_task_name +res +reset +reset_nil_attributes_to_default +reset_prog_mode +resize +resizeterm +resolve +resolve_add +resolve_aliases +resolve_args +resolve_args_without_dependencies +resolve_class +resolve_current +resolve_for +resource +resource= +resources +respace +respond_to? +respond_to_missing? +response +response_body_permitted? +response_class +response_handlers +responses +rest +rest? +rest_size +restore +restsize +result +resume +retrbinary +retrlines +retry +return_format +return_headers? +return_type +return_type_detail +return_value +return_vtype +retval? +reverse +reverse! +reverse_each +revive +revive_hash +revoked +revoked= +rewind +rfc1123_date +rfc2822 +rfc3339 +rfc822 +ri_dir +ri_installed? +ri_paths +rid +rindex +rjust +rm +rm_f +rm_r +rm_rf +rmailbx +rmdir +rmtree +rname +root +root? +root_node +root_search +roots +rotate +rotate! +round +route_from +route_to +row +row_count +row_sep +row_size +row_vector +row_vectors +rows +rpartition +rsqrt +rss +rss_version +rstrip +rstrip! +rubinius? +ruby +ruby= +ruby? +ruby_code +ruby_engine +ruby_opts +ruby_opts_string +ruby_version +rubybin +rubyforge_project +rubygems_api_key +rubygems_api_key= +rubygems_api_request +rubygems_version +rule +run +run_code +run_config +run_once +run_test +run_tests +run_with_threads +runtime_dependencies +rw +safe_level +safe_ln +safe_unlink +same_attributes? +same_feed_type? +sample +sanitize +sanitize_path +sanitize_string +satisfied_by? +satisfies_requirement? +saturday? +save +save_cache +save_class +save_data +save_data_with_atomic_file_rename_strategy +save_data_with_fast_strategy +save_exception_mode +save_history +save_history= +save_limit +save_method +save_page +save_rounding_mode +say +scalar +scalar= +scan +scan_full +scan_make_command_lines +scan_until +scanf +scanner +scheme +scheme= +scheme_list +scope +scope= +scope_name +script_name +scrl +scroll +scrolling_list +scrollok +search +search_const +search_convpath +search_file +search_for_dependency +search_full +search_internal +search_record +search_servlet +search_string +searcher= +sec +sec= +sec_fraction +second +second= +second_fraction +section +section_contents +sections +secure +secure= +security_policy +see +seed +seed= +seek +seen +select +select! +select_tasks_to_show +select_trace_output +self +send +send_command +send_data +send_entity +send_gem +send_io +send_list_data +send_literal +send_mail +send_message +send_number_data +send_quoted_string +send_request +send_request_with_body +send_request_with_body_data +send_request_with_body_stream +send_string_data +send_symbol_data +send_time_data +sendcmd +sender +sendmail +sendmsg +sendmsg_nonblock +sent_size +separator +seplist +seq +seq= +sequence +serial +serial= +serve +server +server_cert +server_error? +server_name +servername_cb +service +session +session= +session_add +session_cache_mode +session_cache_mode= +session_cache_size +session_cache_size= +session_cache_stats +session_get_cb +session_id +session_id_context +session_new_cb +session_remove +session_remove_cb +session_reused? +set +set_arg_names +set_attributes +set_attrs +set_auth +set_backtrace +set_banner +set_callback +set_callback_internal +set_cdecl_callback +set_close_on_exec +set_component +set_content_type +set_ctypes +set_current_section +set_debug_output +set_default +set_default_handler +set_default_paths +set_default_values +set_dictionary +set_dn +set_element +set_encoding +set_eoutvar +set_error +set_extensions +set_filter +set_form +set_form_data +set_fragment +set_generator +set_get_line_procs +set_headers +set_host +set_last_thread +set_last_value +set_log +set_next_element +set_non_blocking +set_opaque +set_option +set_options +set_params +set_parent +set_parser +set_passwd +set_password +set_path +set_port +set_program_name +set_query +set_range +set_redirect +set_registry +set_scheme +set_scope +set_screen_size +set_service_hook +set_size +set_socket +set_stdcall_callback +set_summary_indent +set_summary_width +set_term_to_element +set_to +set_to_infinity! +set_trace +set_trace_func +set_typecode +set_user +set_userinfo +set_valid_ip +set_visibility_for +set_writer +set_xhtml_uri_as_default_uri +setacl +setbyte +setegid +seteuid +setgid +setgid? +setgrent +setpgid +setpgrp +setpos +setpriority +setproperty +setpwent +setquota +setregid +setresgid +setresuid +setreuid +setrgid +setrlimit +setruid +setscrreg +setsid +setsockopt +setter +setuid +setuid? +setup +setup_certificate +setup_elements +setup_generator +setup_image +setup_items +setup_maker +setup_maker_attributes +setup_maker_element +setup_maker_element_writer +setup_maker_elements +setup_next_element +setup_next_element_in_unknown_element +setup_options +setup_other_elements +setup_output_dir +setup_pager +setup_params +setup_scanner +setup_signer +setup_ssl_context +setup_textinput +setup_values +sev_threshold +sev_threshold= +sexp +sexp_raw +sfork +sh +sharing_detection +shebang +shell +shellescape +shelljoin +shellsplit +shellwords +shift +shift_log_age +shift_log_period +short +short_name +show_all +show_documentation +show_hash +show_help +show_lookup_failure +show_owners +show_rdoc_for_pattern +show_version +shuffle +shuffle! +shutdown +sid_available? +sigma +sign +sign_in +signal +signal_handle +signal_status +signaled? +signame +signature +signature_algorithm +signed_time +signed_value +signers +signing_key +signo +sin +sin! +single? +single_delegate +singleline_format +singleline_pp +singleton +singleton_class +singleton_classes +singleton_method_added +singleton_method_removed +singleton_method_undefined +singleton_methods +singular? +sinh +sinh! +site +site_dir +size +size= +size? +size_opt_params +size_params +sizeof +skip +skip_blanks? +skip_during +skip_for_variable +skip_lines +skip_method +skip_optional_do_after_expression +skip_tkspace +skip_tkspace_comment +skip_until +sleep +slice +slice! +slice_before +sn +snippet +soak_up_spaces +sock +sockaddr_in +sockaddr_un +socket? +socketpair +socktype +solve +sort +sort! +sort_by +sort_by! +sort_if_need +sort_internal +sort_obj +sort_options +sort_sections +sorted +sorted_requests +source +source_encoding +source_encoding_name +source_exception +source_file +source_for +source_location +source_ole_types +sources +sources= +spawn +spec +spec_authors +spec_dir +spec_dirs +spec_file +spec_for_dependency +spec_homepage +spec_license +spec_loaded_from +spec_name +spec_path +spec_platforms +spec_predecessors +spec_summary +spec_type +special +special_prefixes +special_prefixes= +specific? +specific_extra_args +specific_extra_args_hash +specification_version +specs +specs_in +split +split_all +split_header_value +split_into_flow +split_name +split_path +split_userinfo +sprintf +sqrt +sqrt! +square? +squeeze +squeeze! +srand +src +src_type +ssl? +ssl_ca_cert +ssl_params +ssl_socket +ssl_timeout +ssl_verify_mode +ssl_version +ssl_version= +sspi_auth +sspi_auth? +stand_alone? +standalone +standard_exception_handling +standard_rake_options +standend +standout +start +startElement +start_accepting +start_collecting_tokens +start_color +start_doc +start_document +start_element +start_element? +start_else_element +start_export +start_get_text_element +start_have_something_element +start_immediately +start_import +start_job +start_keeper +start_mapping +start_prefix_mapping +start_profile +start_sequence +start_server +start_service +start_stream +start_tls_session +start_watchdog +start_with? +started +started? +starting +starts_with +starttls +starttls? +starttls_always? +starttls_auto? +stat +state +static_path +stats +status +status= +status_line +status_message +status_string +status_type_char +stdinput +stdlog +stdout +stdout= +stdout_mutex +stdoutput +stdscr +step +sticky? +stime +stop +stop? +stop_doc +stop_profile +stop_service +stopped? +stopping +stopsig +storbinary +store +store= +store_for +store_internal +stores +storlines +stream= +stream_check +stream_end? +streaming? +stress +stress= +strftime +strict_decode64 +strict_encode64 +string +string= +string_length +string_value +strings +strip +strip! +strip_hashes +strip_newlines +strip_quotes +strip_stars +strong +strongly_connected_components +strptime +struct +style +su +sub +sub! +sub_ext +sub_type +subdomain_of? +subject +subject= +subject_certificate +subject_certificate= +subject_request +subject_request= +submit +subpad +subscribe +subsec +subset? +substring +substring_after +substring_before +subtract +subwin +succ +succ! +succeed +success? +suffix_pattern +suffixes +suggest_gems_from_name +sum +summarize +summary +summary= +summary_indent +summary_width +sunday? +super_each +superclass +superclass= +superclass_method +superset? +supply_default_content_type +supported? +suppressed? +suspend +suspend_context +suspend_input_method +suspend_name +suspend_workspace +swapcase +swapcase! +switch +switch_name +sym +symlink +symlink? +symlink_files +symmetric? +sync +sync= +sync_ex_count +sync_ex_locker +sync_exclusive? +sync_extend +sync_initialize +sync_inspect +sync_lock +sync_locked? +sync_mode +sync_point? +sync_sh_locker +sync_shared? +sync_synchronize +sync_try_lock +sync_try_lock_sub +sync_unlock +sync_upgrade_waiting +sync_waiting +synchronize +syncmode= +synthesize_file_task +sysaccept +syscall +sysclose +sysconfdir +sysopen +sysread +sysread_nonblock +sysseek +syssign +system +system_dir +system_path +system_path= +systmpdir +sysverify +syswrite +syswrite_nonblock +t +tab_width +table +table_of_contents +tag +tag_class +tag_directives +tag_end +tag_filter +tag_name +tag_name_with_prefix +tag_start +tagging +tagurize +taint +tainted? +take +take_while +tan +tan! +tanh +tanh! +tap +tar_bz2_file +tar_command +tar_dir_header +tar_file_header +tar_gz_file +target +task +task_defined? +tasks +tasks_in_scope +taxo_link +taxo_link= +tcp +tcp_server_loop +tcp_server_sockets +tcp_socket +teardown +tee +tell +telnetmode +telnetmode= +temp_dir +template +template_dir +template_dir_for +template_for +template_result +temporary_section +terminal +terminal_columns +terminal_width +terminate +terminate_interaction +terminate_job +terminated? +termsig +territory +test +test_accept_blank_line +test_accept_block_quote +test_accept_document +test_accept_heading +test_accept_heading_1 +test_accept_heading_2 +test_accept_heading_3 +test_accept_heading_4 +test_accept_heading_b +test_accept_heading_indent +test_accept_heading_suppressed_crossref +test_accept_list_end_bullet +test_accept_list_end_label +test_accept_list_end_lalpha +test_accept_list_end_note +test_accept_list_end_number +test_accept_list_end_ualpha +test_accept_list_item_end_bullet +test_accept_list_item_end_label +test_accept_list_item_end_lalpha +test_accept_list_item_end_note +test_accept_list_item_end_number +test_accept_list_item_end_ualpha +test_accept_list_item_start_bullet +test_accept_list_item_start_label +test_accept_list_item_start_lalpha +test_accept_list_item_start_note +test_accept_list_item_start_note_2 +test_accept_list_item_start_note_multi_description +test_accept_list_item_start_note_multi_label +test_accept_list_item_start_number +test_accept_list_item_start_ualpha +test_accept_list_start_bullet +test_accept_list_start_label +test_accept_list_start_lalpha +test_accept_list_start_note +test_accept_list_start_number +test_accept_list_start_ualpha +test_accept_paragraph +test_accept_paragraph_b +test_accept_paragraph_br +test_accept_paragraph_break +test_accept_paragraph_i +test_accept_paragraph_indent +test_accept_paragraph_plus +test_accept_paragraph_star +test_accept_paragraph_underscore +test_accept_paragraph_wrap +test_accept_raw +test_accept_rule +test_accept_rule_indent +test_accept_verbatim +test_accept_verbatim_big_indent +test_accept_verbatim_indent +test_attributes +test_end_accepting +test_file +test_file= +test_files +test_files= +test_list_nested +test_list_verbatim +test_order +test_start_accepting +text +text= +text? +text_field +text_type_writer +text_zero_one +textarea +textinput +texts +tgz_file +thread +thread_internal +thread_list +thread_list_all +thread_variable? +thread_variable_get +thread_variable_set +thread_variables +threads +throw +thursday? +time +time2wtime +time= +time_delta_string +time_format +timeout +timeout= +timeouts= +times +timestamp +title +title= +tls? +tlsconnect +tmp_dh_callback +tmpdir +to +to= +to_a +to_ary +to_atom +to_basic +to_bn +to_c +to_class_name +to_csv +to_d +to_date +to_datetime +to_der +to_digits +to_element_methods +to_enum +to_f +to_feed +to_feed_for_categories +to_h +to_hash +to_html +to_i +to_id +to_int +to_io +to_json +to_mailtext +to_name +to_obj +to_oct +to_p +to_path +to_pem +to_proc +to_ptr +to_r +to_range +to_rfc822text +to_rss +to_ruby +to_ruby_for_cache +to_run +to_s +to_set +to_sockaddr +to_spec +to_specs +to_str +to_string +to_sym +to_text +to_time +to_toc +to_uri +to_value +to_write_io +to_xml +to_yaml +to_yaml_properties +today +toeuc +tojis +token +token_listener +token_pos +token_stream +token_to_str +tokenize +tokens +tokens_to_s +tolocale +tomdoc? +top +top_level +top_level_tasks +top_level_test +toplevel_load +tosjis +total +total_bytes +total_in +total_out +total_time +touch +toutf16 +toutf32 +toutf8 +tr +tr! +tr_s +tr_s! +trace +trace_func +trace_on +trace_rule +trace_var +trackback_validate +transact +transaction +transfer +transform +translate +transport_request +transpose +trap +traverse +tree +tridiagonalize +true +truncate +truncate_output? +trust +trust= +trust_cert +trust_dir +trusted_certificates +try_activate +try_const +try_convert +try_lock +try_mon_enter +try_type +tsort +tsort_each +tsort_each_child +tsort_each_node +tt? +tt_sections +ttl +tty +tty? +tty_output= +tty_output? +tuesday? +tuples_for +tv_nsec +tv_sec +tv_usec +type +type2name +type= +type_params +typealias +typecode +typecode= +typekind +typelibs +types +u +udp +udp_server_loop +udp_server_loop_on +udp_server_recv +udp_server_sockets +ui +ui= +uid +uid= +uid_copy +uid_fetch +uid_search +uid_sort +uid_store +uid_thread +uidl +ultra_safe +umask +umount +unadvise +unalias_command +unbind +unbind_at_call +unconverted_fields? +undef_method +undef_system_command +undefine_finalizer +undoc_params +unescape +unescapeElement +unescapeHTML +unescape_element +unescape_form +unescape_html +unescape_value +unget +unget_tk +ungetbyte +ungetc +ungetch +ungetmouse +uninstall +uninstall_dep +uninstall_gem +uninstall_old_gemcutter +union +uniq +uniq! +unique_classes +unique_classes_and_modules +unique_id +unique_modules +unit +unitary? +unix +unix? +unix_path +unix_rights +unix_server_loop +unix_server_socket +unix_socket_abstract_name? +unknown +unlink +unlock +unmask_protected_sequences +unmatched_alias_lists +unmount +unnormalize +unnormalized +unpack +unpack_sockaddr_in +unpack_sockaddr_un +unpackdw +unpackqw +unparsed_uri +unregist +unregister_command +unresolved_deps +unscan +unshift +unsigned_value +unsubscribe +untaint +untrace_var +untrust +untrusted? +unused +unyank_gem +upcase +upcase! +update +update_aliases +update_cache? +update_checksum +update_content +update_display +update_extends +update_gem +update_gems +update_includes +update_index +update_output_dir +update_rubygems +update_sources +update_specs_index +update_status +updated +updated= +upgrade_to_class +upload +upload_files +upper +upper_bound +upper_bound= +upper_triangular? +upto +uptodate? +uri +uri_convert_attr_reader +uri_escaper +uri_option +uri_registered? +url_encode +urlsafe_base64 +urlsafe_decode64 +urlsafe_encode64 +usage +use_default_colors +use_loader +use_loader= +use_loader? +use_markup +use_paths +use_prefix +use_readline +use_readline= +use_readline? +use_registry +use_ssl= +use_ssl? +use_stdout +use_tracer +use_tracer= +use_tracer? +use_ui +usec +user +user= +user_agent +user_dir +user_home +userdb +userinfo +userinfo= +utc +utc? +utc_offset +util_build_gem +util_clear_gems +util_dir_entry +util_entry +util_gem +util_gzip +util_inst_bindir +util_installer +util_make_exec +util_make_gems +util_remove_gem +util_set_arch +util_setup_fake_fetcher +util_setup_gem +util_setup_spec_fetcher +util_spec +util_zip +utime +uuid +v +v_inv +v_nil +valid? +valid_civil? +valid_commercial? +valid_date? +valid_encoding? +valid_jd? +valid_ordinal? +valid_v6? +validate +validate_attribute +validate_data +validate_duplicate_links +validate_for_stream +validate_one_tag_name +validate_permissions +validate_sy_updatePeriod +validation_for_fit +value +value= +value? +values +values_at +variable_is_set? +variable_kind +variables +variables= +varkind +vartype +vc_windows? +ver +verb +verbose +verbose= +verbose? +verbose_capture_io +verbose_flag +verbosity +verify +verify_api_key +verify_callback +verify_callback= +verify_certificate_identity +verify_chain +verify_data +verify_depth +verify_files +verify_gem +verify_gem_file +verify_gem_home +verify_mode +verify_result +verify_root +verify_signatures +verify_signer +version +version= +version_1_2 +version_1_2? +versions +vi_editing_mode +vi_editing_mode? +viewer +virtual_host +visibility +visible? +visit +visit_Array +visit_BigDecimal +visit_Class +visit_Complex +visit_Date +visit_DateTime +visit_Exception +visit_FalseClass +visit_Float +visit_Hash +visit_Integer +visit_Module +visit_NilClass +visit_Object +visit_Psych_Nodes_Alias +visit_Psych_Nodes_Document +visit_Psych_Nodes_Mapping +visit_Psych_Nodes_Scalar +visit_Psych_Nodes_Sequence +visit_Psych_Nodes_Stream +visit_Psych_Omap +visit_Psych_Set +visit_Range +visit_Rational +visit_Regexp +visit_String +visit_Struct +visit_Symbol +visit_Time +visit_TrueClass +visit_array_subclass +voidcmd +w3cdtf +wait +wait2 +wait? +wait_all_jobs_execution +wait_for_child_process_to_exit +wait_for_continue +wait_readable +wait_to_finish_all_process_controllers +wait_until +wait_while +wait_writable +waitall +waitfor +waiting +waiting_job? +waiting_jobs +waiting_jobs_exist? +waitpid +waitpid2 +wakeup +warn +warn? +warning +wday +weakref_alive? +webcvs +wednesday? +weight +welcome +when_invoked +when_writing +which_to_update +whitespace +why_not_ok? +width +width= +win32_last_error +win32_last_error= +win_platform= +win_platform? +windows? +windows_stub_script +winsize +winsize= +with +with_config +with_defaults +with_index +with_object +with_response +with_verbose +wont_be +wont_be_close_to +wont_be_empty +wont_be_instance_of +wont_be_kind_of +wont_be_nil +wont_be_same_as +wont_be_within_delta +wont_be_within_epsilon +wont_equal +wont_include +wont_match +wont_respond_to +word_pair_map +wordy +workspace +workspace_home +workspaces +world_readable? +world_writable? +wrap +wrap_arg +wrap_args +wrap_result +wrappers +writable? +writable_real? +write +writeTo +write_bin +write_build_info_file +write_cache_file +write_cdata +write_comment +write_document +write_element +write_file +write_header +write_headers? +write_i +write_instruction +write_nonblock +write_options +write_s +write_service +write_smime +write_spec +write_style_sheet +write_text +write_with_substitution +writeencoding +writethis +written +wrong_type +wtime2time +xhtml +xhtml= +xlist +xml +xml= +xmlDecl +xml_content= +xml_decl +xml_getter +xml_setter +xml_stylesheet_pi +xml_stylesheets +xml_type? +xmldecl +xmldecl? +xmled_content +xmlschema +xmp +xpath +y +yaml +yaml_as +yaml_initialize +yaml_tag +yank_api_request +yank_gem +yday +year +year= +yes_clean_other_attr_reader +yes_clean_other_writer +yes_other_attr_reader +yes_other_writer +yield +yyaccept +yydebug +yydebug= +yyerrok +yyerror +yyparse +zero +zero? +zip +zip? +zip_command +zip_file +zlib_version +zone +zone_offset +zone_utc? +| +~ \ No newline at end of file -- cgit 1.4.1 From f7bbd467b53d0ee7c3ca366750ed1fa60972981c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 28 Jun 2024 16:00:19 +0200 Subject: add custom_send_tcp --- custom_mutators/custom_send_tcp/Makefile | 7 ++ custom_mutators/custom_send_tcp/README.md | 13 +++ custom_mutators/custom_send_tcp/custom_send_tcp.c | 113 ++++++++++++++++++++++ docs/Changelog.md | 2 + 4 files changed, 135 insertions(+) create mode 100644 custom_mutators/custom_send_tcp/Makefile create mode 100644 custom_mutators/custom_send_tcp/README.md create mode 100644 custom_mutators/custom_send_tcp/custom_send_tcp.c diff --git a/custom_mutators/custom_send_tcp/Makefile b/custom_mutators/custom_send_tcp/Makefile new file mode 100644 index 00000000..8549ccad --- /dev/null +++ b/custom_mutators/custom_send_tcp/Makefile @@ -0,0 +1,7 @@ +all: custom_send_tcp.so + +custom_send_tcp.so: + $(CC) -Wno-unused-result -g -O3 -shared -fPIC -o custom_send_tcp.so -I../../include custom_send_tcp.c + +clean: + rm -f custom_send_tcp.so *.o *~ core diff --git a/custom_mutators/custom_send_tcp/README.md b/custom_mutators/custom_send_tcp/README.md new file mode 100644 index 00000000..7b4bb869 --- /dev/null +++ b/custom_mutators/custom_send_tcp/README.md @@ -0,0 +1,13 @@ +# Send testcases via TCP custom mutator + +This custom mutator sends the fuzzing testcases via TCP. + +`AFL_CUSTOM_MUTATOR_LATE_SEND` - MUST be set! +`CUSTOM_SEND_IP` - the IP address to send to (basically only 127.0.0.1 makes sense) +`CUSTOM_SEND_PORT` - the TCP port to send to +`CUSTOM_SEND_READ` - if the custom mutator should wait for a reply from the target + +Example: +``` +CUSTOM_SEND_IP=127.0.0.1 CUSTOM_SEND_PORT=8000 CUSTOM_SEND_READ=1 AFL_CUSTOM_MUTATOR_LATE_SEND=1 AFL_CUSTOM_MUTATOR_LIBRARY=custom_send_tcp.so ./afl-fuzz ... +``` diff --git a/custom_mutators/custom_send_tcp/custom_send_tcp.c b/custom_mutators/custom_send_tcp/custom_send_tcp.c new file mode 100644 index 00000000..53689ced --- /dev/null +++ b/custom_mutators/custom_send_tcp/custom_send_tcp.c @@ -0,0 +1,113 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "afl-fuzz.h" + +static int my_debug = 0; +static int my_read = 0; + +#define DEBUG(...) if (my_debug) printf(__VA_ARGS__) + +typedef struct tcp_send_mutator { + afl_state_t* afl; + struct sockaddr_in server_addr; +} tcp_send_mutator_t; + +void *afl_custom_init(afl_state_t* afl, uint32_t seed) { + const char* ip = getenv("CUSTOM_SEND_IP"); + const char* port = getenv("CUSTOM_SEND_PORT"); + + if (getenv("AFL_DEBUG")) my_debug = 1; + if (getenv("CUSTOM_SEND_READ")) my_read = 1; + + if (!ip || !port) { + fprintf(stderr, "You forgot to set CUSTOM_SEND_IP and/or CUSTOM_SEND_PORT\n"); + exit(1); + } + + tcp_send_mutator_t* mutator = calloc(1, sizeof(tcp_send_mutator_t)); + if (!mutator) { + fprintf(stderr, "Failed to allocate mutator struct\n"); + exit(1); + } + + mutator->afl = afl; + + bzero(&mutator->server_addr, sizeof(mutator->server_addr)); + mutator->server_addr.sin_family = AF_INET; + if (inet_pton(AF_INET, ip, &mutator->server_addr.sin_addr) <= 0) { + fprintf(stderr, "Could not convert target ip address!\n"); + exit(1); + } + mutator->server_addr.sin_port = htons(atoi(port)); + + printf("[+] Custom tcp send mutator setup ready to go!\n"); + + return mutator; +} + +int try_connect(tcp_send_mutator_t *mutator, int sock, int max_attempts) { + while (max_attempts > 0) { + if (connect(sock, (struct sockaddr*)&mutator->server_addr, sizeof(mutator->server_addr)) == 0) { + return 0; + } + + // Even with AFL_CUSTOM_LATE_SEND=1, there is a race between the + // application under test having started to listen for connections and + // afl_custom_fuzz_send being called. To address this race, we attempt + // to connect N times and sleep a short period of time in between + // connection attempts. + struct timespec t; + t.tv_sec = 0; + t.tv_nsec = 100; + nanosleep(&t, NULL); + --max_attempts; + } + return 1; +} + +void afl_custom_fuzz_send(tcp_send_mutator_t *mutator, uint8_t *buf, size_t buf_size) { + int sock = socket(AF_INET, SOCK_STREAM, 0); + + int written = 0; + if (sock >= 0 && try_connect(mutator, sock, 10000) == 0) { + DEBUG("connected, write()\n"); + written = write(sock, buf, buf_size); + } else { + DEBUG("socket() or connect() error: %d\n", errno); + } + + if (written < 0) { + DEBUG("write() error: %d\n", errno); + } else if (my_read) { + struct timeval timeout; + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + fd_set set; + FD_ZERO(&set); + FD_SET(sock, &set); + + int select_res = select(sock + 1, &set, NULL, NULL, &timeout); + if (select_res == -1) { + DEBUG("select() error: %d\n", errno); + } else if (select_res == 0) { + DEBUG("read() timeout!\n"); + } else { + uint8_t buf[64]; + (void)read(sock, buf, sizeof(buf)); + } + } + + close(sock); +} + +void afl_custom_deinit(tcp_send_mutator_t* mutator) { + free(mutator); +} diff --git a/docs/Changelog.md b/docs/Changelog.md index c16214e4..0212fd61 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -18,6 +18,8 @@ a function entry - AFL_DEBUG is now the same as AFL_FRIDA_VERBOSE - AFL_FRIDA_DEBUG_MAPS now works as expected + - custom mutators: + - custom_send_tcp custom mutator added, thanks to @dergoegge ### Version ++4.21c (release) -- cgit 1.4.1 From 77cfd504cf0bdc0906ede9b2b54e25f98250b2e7 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 28 Jun 2024 16:33:48 +0200 Subject: update grammar mutator --- custom_mutators/grammar_mutator/GRAMMAR_VERSION | 2 +- custom_mutators/grammar_mutator/grammar_mutator | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/custom_mutators/grammar_mutator/GRAMMAR_VERSION b/custom_mutators/grammar_mutator/GRAMMAR_VERSION index 02119caf..eea76ba3 100644 --- a/custom_mutators/grammar_mutator/GRAMMAR_VERSION +++ b/custom_mutators/grammar_mutator/GRAMMAR_VERSION @@ -1 +1 @@ -95a6857 +05d8f53 diff --git a/custom_mutators/grammar_mutator/grammar_mutator b/custom_mutators/grammar_mutator/grammar_mutator index 95a68577..05d8f537 160000 --- a/custom_mutators/grammar_mutator/grammar_mutator +++ b/custom_mutators/grammar_mutator/grammar_mutator @@ -1 +1 @@ -Subproject commit 95a685773e571620cb6e2788dbbdba333e1b9bfd +Subproject commit 05d8f537f8d656f0754e7ad5dcc653c42cb4f8ff -- cgit 1.4.1 From 9d33580aac21f42cbf83297572f5d2aaa9d7db93 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 28 Jun 2024 16:46:42 +0200 Subject: code format --- include/debug.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/debug.h b/include/debug.h index c66d0334..5496135c 100644 --- a/include/debug.h +++ b/include/debug.h @@ -409,6 +409,8 @@ static inline const char *colorfilter(const char *x) { \ } while (1); \ \ + \ + \ } while (0) #define ck_read(fd, buf, len, fn) \ -- cgit 1.4.1 From e86dcc9f18c5cf4006d59a3a785695da451771d5 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 29 Jun 2024 02:15:35 +0200 Subject: update qemu mode --- qemu_mode/QEMUAFL_VERSION | 2 +- qemu_mode/qemuafl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/qemu_mode/QEMUAFL_VERSION b/qemu_mode/QEMUAFL_VERSION index 296745f9..668eeed4 100644 --- a/qemu_mode/QEMUAFL_VERSION +++ b/qemu_mode/QEMUAFL_VERSION @@ -1 +1 @@ -a6f0632a65 +6d5811db17 diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl index a6f0632a..6d5811db 160000 --- a/qemu_mode/qemuafl +++ b/qemu_mode/qemuafl @@ -1 +1 @@ -Subproject commit a6f0632a65e101e680dd72643a6128dd180dff72 +Subproject commit 6d5811db179772311c8af1f9ec5d2ceb4b9df022 -- cgit 1.4.1 From f6bfa96a9662665559d681b9242c16466d630b3a Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 29 Jun 2024 03:32:37 +0200 Subject: todo --- TODO.md | 1 + 1 file changed, 1 insertion(+) diff --git a/TODO.md b/TODO.md index a1431afa..c6da7fc5 100644 --- a/TODO.md +++ b/TODO.md @@ -2,6 +2,7 @@ ## Must + - in CLASSIC mode - do old forkserver model - docs: AFL_DISABLE_REDUNDANT (large/slow/LAF) - check for null ptr for xml/curl/g_ string transform functions - hardened_usercopy=0 page_alloc.shuffle=0 -- cgit 1.4.1 From 50ae95cee44a8df1629ee360de5d2582ff7d177e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 29 Jun 2024 16:31:08 +0200 Subject: add AFL_OLD_FORKSERVER feature --- docs/Changelog.md | 4 ++ docs/env_variables.md | 37 +++++++++---- include/envs.h | 5 +- instrumentation/afl-compiler-rt.o.c | 103 ++++++++++++++++++++++-------------- 4 files changed, 96 insertions(+), 53 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 0212fd61..487c5688 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -20,6 +20,10 @@ - AFL_FRIDA_DEBUG_MAPS now works as expected - custom mutators: - custom_send_tcp custom mutator added, thanks to @dergoegge + - afl-cc + - new runtime (!) variable: `AFL_OLD_FORKSERVER` to use the old vanilla + AFL type forkserver. Useful for symcc/symqemu/nautilus/etc. with + AFL_LLVM_INSTRUMENT=CLASSIC ### Version ++4.21c (release) diff --git a/docs/env_variables.md b/docs/env_variables.md index eebbcbda..8c2d5848 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -331,7 +331,26 @@ mode. the target performs only a few loops, then this will give a small performance boost. -## 4) Settings for afl-fuzz +## 4) Runtime settings + +The following environment variables are for a compiled AFL++ target. + + - Setting `AFL_DUMP_MAP_SIZE` when executing the target directly will + dump the map size of the target and exit. + + - Setting `AFL_OLD_FORKSERVER` will use the old AFL vanilla forkserver. + This makes only sense when you + a) compile in a classic colliding coverage mode (e.g. + AFL_LLVM_INSTRUMENT=CLASSIC) or if the map size of the target is + below MAP_SIZE (65536 by default), AND + b) you want to use this compiled AFL++ target with a different tool + that expects vanilla AFL behaviour, e.g. symcc, symqemu, nautilus, etc. + You would use this option together with the target fuzzing application. + + - Setting `AFL_DISABLE_LLVM_INSTRUMENTATION` will disable collecting + instrumentation. (More of an internal option.) + +## 5) Settings for afl-fuzz The main fuzzer binary accepts several options that disable a couple of sanity checks or alter some of the more exotic semantics of the tool: @@ -642,7 +661,7 @@ checks or alter some of the more exotic semantics of the tool: Note that will not be exact and with slow targets it can take seconds until there is a slice for the time test. -## 5) Settings for afl-qemu-trace +## 6) Settings for afl-qemu-trace The QEMU wrapper used to instrument binary-only code supports several settings: @@ -714,7 +733,7 @@ The QEMU wrapper used to instrument binary-only code supports several settings: crash is found. Setting `AFL_NO_CRASH_README` will prevent this. Useful when counting crashes based on a file count in that directory. -## 7) Settings for afl-frida-trace +## 8) Settings for afl-frida-trace The FRIDA wrapper used to instrument binary-only code supports many of the same options as `afl-qemu-trace`, but also has a number of additional advanced @@ -804,7 +823,7 @@ support. dump you must set a sufficient timeout (using `-t`) to avoid `afl-fuzz` killing the process whilst it is being dumped. -## 8) Settings for afl-cmin +## 9) Settings for afl-cmin The corpus minimization script offers very little customization: @@ -822,7 +841,7 @@ The corpus minimization script offers very little customization: - `AFL_PRINT_FILENAMES` prints each filename to stdout, as it gets processed. This can help when embedding `afl-cmin` or `afl-showmap` in other scripts. -## 9) Settings for afl-tmin +## 10) Settings for afl-tmin Virtually nothing to play with. Well, in QEMU mode (`-Q`), `AFL_PATH` will be searched for afl-qemu-trace. In addition to this, `TMPDIR` may be used if a @@ -833,12 +852,12 @@ to match when minimizing crashes. This will make minimization less useful, but may prevent the tool from "jumping" from one crashing condition to another in very buggy software. You probably want to combine it with the `-e` flag. -## 10) Settings for afl-analyze +## 11) Settings for afl-analyze You can set `AFL_ANALYZE_HEX` to get file offsets printed as hexadecimal instead of decimal. -## 11) Settings for libdislocator +## 12) Settings for libdislocator The library honors these environment variables: @@ -860,12 +879,12 @@ The library honors these environment variables: - `AFL_LD_VERBOSE` causes the library to output some diagnostic messages that may be useful for pinpointing the cause of any observed issues. -## 11) Settings for libtokencap +## 13) Settings for libtokencap This library accepts `AFL_TOKEN_FILE` to indicate the location to which the discovered tokens should be written. -## 12) Third-party variables set by afl-fuzz & other tools +## 14) Third-party variables set by afl-fuzz & other tools Several variables are not directly interpreted by afl-fuzz, but are set to optimal values if not already present in the environment: diff --git a/include/envs.h b/include/envs.h index 6a0d329b..3accbda0 100644 --- a/include/envs.h +++ b/include/envs.h @@ -40,8 +40,7 @@ static char *afl_environment_variables[] = { "AFL_FRIDA_INST_INSN", "AFL_FRIDA_INST_JIT", "AFL_FRIDA_INST_NO_CACHE", "AFL_FRIDA_INST_NO_DYNAMIC_LOAD", "AFL_FRIDA_INST_NO_OPTIMIZE", "AFL_FRIDA_INST_NO_PREFETCH", "AFL_FRIDA_INST_NO_PREFETCH_BACKPATCH", - "AFL_FRIDA_INST_NO_SUPPRESS" - "AFL_FRIDA_INST_RANGES", + "AFL_FRIDA_INST_NO_SUPPRESS", "AFL_FRIDA_INST_RANGES", "AFL_FRIDA_INST_REGS_FILE", "AFL_FRIDA_INST_SEED", "AFL_FRIDA_INST_TRACE", "AFL_FRIDA_INST_TRACE_UNIQUE", "AFL_FRIDA_INST_UNSTABLE_COVERAGE_FILE", "AFL_FRIDA_JS_SCRIPT", "AFL_FRIDA_OUTPUT_STDOUT", "AFL_FRIDA_OUTPUT_STDERR", @@ -50,7 +49,7 @@ static char *afl_environment_variables[] = { "AFL_FRIDA_PERSISTENT_RET", "AFL_FRIDA_STALKER_ADJACENT_BLOCKS", "AFL_FRIDA_STALKER_IC_ENTRIES", "AFL_FRIDA_STALKER_NO_BACKPATCH", "AFL_FRIDA_STATS_FILE", "AFL_FRIDA_STATS_INTERVAL", "AFL_FRIDA_TRACEABLE", - "AFL_FRIDA_VERBOSE", + "AFL_FRIDA_VERBOSE", "AFL_OLD_FORKSERVER", "AFL_FUZZER_ARGS", // oss-fuzz "AFL_FUZZER_STATS_UPDATE_INTERVAL", "AFL_GDB", "AFL_GCC_ALLOWLIST", "AFL_GCC_DENYLIST", "AFL_GCC_BLOCKLIST", "AFL_GCC_INSTRUMENT_FILE", diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index c08e6380..83aa9486 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -118,6 +118,7 @@ u32 __afl_map_size = MAP_SIZE; u32 __afl_dictionary_len; u64 __afl_map_addr; u32 __afl_first_final_loc; +u32 __afl_old_forkserver; #ifdef __AFL_CODE_COVERAGE typedef struct afl_module_info_t afl_module_info_t; @@ -616,7 +617,7 @@ static void __afl_map_shm(void) { fprintf(stderr, "DEBUG: (2) id_str %s, __afl_area_ptr %p, __afl_area_initial %p, " "__afl_area_ptr_dummy %p, __afl_map_addr 0x%llx, MAP_SIZE " - "%u, __afl_final_loc %u, __afl_map_size %u", + "%u, __afl_final_loc %u, __afl_map_size %u\n", id_str == NULL ? "" : id_str, __afl_area_ptr, __afl_area_initial, __afl_area_ptr_dummy, __afl_map_addr, MAP_SIZE, __afl_final_loc, __afl_map_size); @@ -856,7 +857,7 @@ static void __afl_start_forkserver(void) { signal(SIGTERM, at_exit); u32 already_read_first = 0; - u32 was_killed; + u32 was_killed = 0; u32 version = 0x41464c00 + FS_NEW_VERSION_MAX; u32 tmp = version ^ 0xffffffff, status2, status = version; u8 *msg = (u8 *)&status; @@ -866,75 +867,95 @@ static void __afl_start_forkserver(void) { void (*old_sigchld_handler)(int) = signal(SIGCHLD, SIG_DFL); + if (getenv("AFL_OLD_FORKSERVER")) { + + __afl_old_forkserver = 1; + status = 0; + + if (__afl_final_loc && __afl_final_loc > MAP_SIZE) { + + fprintf(stderr, + "Warning: AFL_OLD_FORKSERVER is used with a target compiled with " + "non-colliding coverage instead of AFL_LLVM_INSTRUMENT=CLASSIC - " + "this target may crash!\n"); + + } + + } + /* Phone home and tell the parent that we're OK. If parent isn't there, assume we're not running in forkserver mode and just execute program. */ // return because possible non-forkserver usage if (write(FORKSRV_FD + 1, msg, 4) != 4) { return; } - if (read(FORKSRV_FD, reply, 4) != 4) { _exit(1); } - if (tmp != status2) { + if (!__afl_old_forkserver) { - write_error("wrong forkserver message from AFL++ tool"); - _exit(1); + if (read(FORKSRV_FD, reply, 4) != 4) { _exit(1); } + if (tmp != status2) { - } + write_error("wrong forkserver message from AFL++ tool"); + _exit(1); - // send the set/requested options to forkserver - status = FS_NEW_OPT_MAPSIZE; // we always send the map size - if (__afl_sharedmem_fuzzing) { status |= FS_NEW_OPT_SHDMEM_FUZZ; } - if (__afl_dictionary_len && __afl_dictionary) { + } - status |= FS_NEW_OPT_AUTODICT; + // send the set/requested options to forkserver + status = FS_NEW_OPT_MAPSIZE; // we always send the map size + if (__afl_sharedmem_fuzzing) { status |= FS_NEW_OPT_SHDMEM_FUZZ; } + if (__afl_dictionary_len && __afl_dictionary) { - } + status |= FS_NEW_OPT_AUTODICT; - if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); } + } - // Now send the parameters for the set options, increasing by option number + if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); } - // FS_NEW_OPT_MAPSIZE - we always send the map size - status = __afl_map_size; - if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); } + // Now send the parameters for the set options, increasing by option number - // FS_NEW_OPT_SHDMEM_FUZZ - no data + // FS_NEW_OPT_MAPSIZE - we always send the map size + status = __afl_map_size; + if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); } - // FS_NEW_OPT_AUTODICT - send autodictionary - if (__afl_dictionary_len && __afl_dictionary) { + // FS_NEW_OPT_SHDMEM_FUZZ - no data - // pass the dictionary through the forkserver FD - u32 len = __afl_dictionary_len, offset = 0; + // FS_NEW_OPT_AUTODICT - send autodictionary + if (__afl_dictionary_len && __afl_dictionary) { - if (write(FORKSRV_FD + 1, &len, 4) != 4) { + // pass the dictionary through the forkserver FD + u32 len = __afl_dictionary_len, offset = 0; - write(2, "Error: could not send dictionary len\n", - strlen("Error: could not send dictionary len\n")); - _exit(1); + if (write(FORKSRV_FD + 1, &len, 4) != 4) { - } + write(2, "Error: could not send dictionary len\n", + strlen("Error: could not send dictionary len\n")); + _exit(1); - while (len != 0) { + } - s32 ret; - ret = write(FORKSRV_FD + 1, __afl_dictionary + offset, len); + while (len != 0) { - if (ret < 1) { + s32 ret; + ret = write(FORKSRV_FD + 1, __afl_dictionary + offset, len); - write_error("could not send dictionary"); - _exit(1); + if (ret < 1) { - } + write_error("could not send dictionary"); + _exit(1); - len -= ret; - offset += ret; + } + + len -= ret; + offset += ret; + + } } - } + // send welcome message as final message + status = version; + if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); } - // send welcome message as final message - status = version; - if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); } + } // END forkserver handshake -- cgit 1.4.1 From a7f928ac31bd75d91f93631790d95a86d13e134f Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 29 Jun 2024 16:45:01 +0200 Subject: update qemuafl --- qemu_mode/QEMUAFL_VERSION | 2 +- qemu_mode/qemuafl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/qemu_mode/QEMUAFL_VERSION b/qemu_mode/QEMUAFL_VERSION index 668eeed4..9a62db20 100644 --- a/qemu_mode/QEMUAFL_VERSION +++ b/qemu_mode/QEMUAFL_VERSION @@ -1 +1 @@ -6d5811db17 +847b43acb1 diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl index 6d5811db..847b43ac 160000 --- a/qemu_mode/qemuafl +++ b/qemu_mode/qemuafl @@ -1 +1 @@ -Subproject commit 6d5811db179772311c8af1f9ec5d2ceb4b9df022 +Subproject commit 847b43acb11530e775013dc24b54c6e27406179c -- cgit 1.4.1 From b169629dbd1cd0b78b541c7fa8eccf6a6a7394b1 Mon Sep 17 00:00:00 2001 From: "Subhojeet Mukherjee, PhD" Date: Mon, 1 Jul 2024 05:43:45 +0000 Subject: Fresh commit with all -- post revertion due to unicornafl update --- qemu_mode/build_qemu_support.sh | 13 +++ qemu_mode/hooking_bridge/Makefile | 18 ++++ qemu_mode/hooking_bridge/README.md | 101 +++++++++++++++++++ qemu_mode/hooking_bridge/inc/common.h | 11 ++ qemu_mode/hooking_bridge/inc/exports.h | 29 ++++++ qemu_mode/hooking_bridge/src/main.c | 36 +++++++ qemu_mode/hooking_bridge/src/patching.c | 173 ++++++++++++++++++++++++++++++++ 7 files changed, 381 insertions(+) create mode 100644 qemu_mode/hooking_bridge/Makefile create mode 100644 qemu_mode/hooking_bridge/README.md create mode 100644 qemu_mode/hooking_bridge/inc/common.h create mode 100644 qemu_mode/hooking_bridge/inc/exports.h create mode 100644 qemu_mode/hooking_bridge/src/main.c create mode 100644 qemu_mode/hooking_bridge/src/patching.c diff --git a/qemu_mode/build_qemu_support.sh b/qemu_mode/build_qemu_support.sh index 19336114..4dd4fad2 100755 --- a/qemu_mode/build_qemu_support.sh +++ b/qemu_mode/build_qemu_support.sh @@ -386,6 +386,19 @@ else make -C libqasan CC="$CROSS $CROSS_FLAGS" && echo "[+] libqasan ready" fi +#### Hooking support +if [ "$ENABLE_HOOKING" = "1" ];then + echo "[+] ENABLING HOOKING" + set -e + cd ./hooking_bridge || exit 255 + mkdir -p ./build + echo "[+] Hook compiler = $CROSS" + make CC="$CROSS $CROSS_FLAGS" GLIB_H="$GLIB_H" GLIB_CONFIG_H="$GLIB_CONFIG_H" + set +e + cd .. +fi +#### End of hooking support + echo "[+] All done for qemu_mode, enjoy!" exit 0 diff --git a/qemu_mode/hooking_bridge/Makefile b/qemu_mode/hooking_bridge/Makefile new file mode 100644 index 00000000..dcc6f12a --- /dev/null +++ b/qemu_mode/hooking_bridge/Makefile @@ -0,0 +1,18 @@ +.PHONY: clean + +all: plugin +SRC=./src +BLD=./build +INC=-I./inc -I../qemuafl/include -I$(GLIB_H) -I$(GLIB_CONFIG_H) +# CC=gcc + +$(BLD)/patching.o:$(SRC)/patching.c + $(CC) -c -fPIC $(INC) -o $(BLD)/patching.o $(SRC)/patching.c + +plugin:$(SRC)/main.c $(BLD)/patching.o + $(CC) -c -fPIC $(INC) -o $(BLD)/plugin.o $(SRC)/main.c + $(CC) -shared -o $(BLD)/plugin.so $(BLD)/plugin.o $(BLD)/patching.o + +clean: + rm -rf $(BLD)/*.o + rm -rf $(BLD)/*.so \ No newline at end of file diff --git a/qemu_mode/hooking_bridge/README.md b/qemu_mode/hooking_bridge/README.md new file mode 100644 index 00000000..ae8e62e4 --- /dev/null +++ b/qemu_mode/hooking_bridge/README.md @@ -0,0 +1,101 @@ +# Native hooking support into QEMUAFL +* The essential idea is to have inbuilt hooking support into QEMU, instead of relying on the more expensive options UNICORN and its children. +* This solution comprises a bridge (QEMU plugin) that connects your hooks (in a shared library (.so)) with the QEMU usermode ecosystem. +* Currently, LINUX only + +## Bridge compilation +Run build_qemu_support.sh as you do to compile qemuafl, additionally with three args namely: +* `ENABLE_HOOKING=1` to compile the bridge +* `GLIB_H` and `GLIB_CONFIG_H` point to headers `glib.h` and `glibconfig.h` to wherever they are installed on your system + +## Writting hooks +1. Create one or more hooking functions in a shared library, say `hook.so`. +2. Include `exports.h` in your hook build. You can find this header at `/qemu_mode/hooking_bridge/inc`. +3. Shown below is an example which will use to walkthrough hook creation + ```C + struct ret* hook_000000400deadc08(){ + memset (buf, 0, 8); + scanf("%s",buf); + r_reg(RSI,(void *)&h_addr); + w_mem(h_addr,8, buf); + to_ret = (struct ret){0x400deadcab, 0}; + return &to_ret; + } + ``` + i. Hook functions must be named as `hook_`. Here, `` means `` left padded with 0's to until the `(system word length)/4` number of hex characters, e.g. 16 on a 64 bit machine. The unpaded part of `` is the absolute address where you want to place the hook. It is basically the file base address (which does not change in QEMU as of now) plus the instruction offset where the hooks is to be placed. The hook function must return a `struct ret *`, which is touched upon later. + + ii. Most likely you will need to access memory or registers in the hook. So we provide four functions + ```C + // Read memory (from address, num. bytes, destination buffer) -> returns 0 on success + int r_mem(unsigned long long addr, unsigned long long len, void *dest); + // Write memory (to address, num. bytes, source buffer) -> returns 0 on success + int w_mem(unsigned long long addr, unsigned long long len, void *src); + // Read register (identifier, destination buffer) -> returns number of bytes read + int r_reg(unsigned char reg, void *dest); + // Read register (identifier, source buffer) -> returns number of bytes written + int w_reg(unsigned char reg, char *src); + ``` + When operating on registers, the functions require a `reg` identifier. This is basically a number gdb uses to lookup a register and can be found under `/gdb-xml` in the architecture specific xml files. For the example case from above, `RSI` is 4 as obtained from `i386-64bit.xml`. + + iii. Once done with the processing, the hooks needs to return a `struct ret` type pointer, the struct format being + ```C + struct ret{ + unsigned long long addr; + char remove_bp; + }; + ``` + As we can see, there are two fields: first that indicates the address to return to and second that indicates whether the installed hook should be removed after the return. The second field becomes critical if the hook is within an ongoing loop and should be kept intact for future references. + + iv. Finally, mention the list of hooks in a `configure` function that we can call and install your hooks + ```C + struct conf config; + struct conf* configure(){ + config.IP_reg_num = 16; + config.entry_addr = 0x4000001000; + config.num_hooks = NUMHOOKS; //1,2,3... + hooks[0] = 0x400deadc08; + // hooks[1] = 0xcafecace + // .... + config.hooks = hooks; + + //Any other processing stuff you need done before fuzztime + + return &config; + } + ``` + The `configure` function must have the signature `struct conf* configure()` i.e. it must return a pointer to the `config` object. The format of the `config` object is + ```C + struct conf{ + unsigned char IP_reg_num; //found in /gdb-xml + unsigned long long entry_addr; //Main, init, or any entry point that is executed by QEMU prior to hooking targets + unsigned long long* hooks; //list of hooked addresses + unsigned long long num_hooks; // Number of hooks + }; + ``` + `IP_reg_num` here is the register number assigned under the architecture specific xml file under `/gdb-xml` to the instruction pointer. + +## Running with hooks +Set `QEMU_PLUGIN="file=qemu_mode/hooking_bridge/build/plugin.so,arg="` before running AFL++ in QEMU mode. Note `` is the absolute path to your hooks library. + +## Contributing +* If you want to enable debugging + * Compile with an additional `DEBUG=1` switch. + * Akin to QEMU's own documentation, set `QEMU_LOG=plugin QEMU_LOG_FILENAME=` before you run. + +## Current limitations +1. Cannot be used to debug (-g option) when using the bridge as it uses the gdbstub internally. This is not a problem if used with AFL++, so not such a big issue. +2. Cannot put a hook on the first block after ``. Not typically a hookable location. +3. The current implementation can only function on Linux. We have tested on the following configuration + ```Bash + lsb_release -a + --------------- + Distributor ID: Ubuntu + Description: Ubuntu 22.04.3 LTS + Release: 22.04 + Codename: jammy + ``` + ```Bash + uname -a + ---------- + Linux someone 6.5.0-28-generic #29~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Apr 4 14:39:20 UTC 2 x86_64 x86_64 x86_64 GNU/Linux + ``` diff --git a/qemu_mode/hooking_bridge/inc/common.h b/qemu_mode/hooking_bridge/inc/common.h new file mode 100644 index 00000000..f2260977 --- /dev/null +++ b/qemu_mode/hooking_bridge/inc/common.h @@ -0,0 +1,11 @@ +#ifndef COMMON_H +#define COMMON_H + +#include + +void patch_finish_cb(void *userdata); +void patch_block_trans_cb(struct qemu_plugin_tb *tb); +void patch_vpu_init_cb(unsigned int vcpu_index); +void patch_init(char *hook_library); + +#endif \ No newline at end of file diff --git a/qemu_mode/hooking_bridge/inc/exports.h b/qemu_mode/hooking_bridge/inc/exports.h new file mode 100644 index 00000000..186976f4 --- /dev/null +++ b/qemu_mode/hooking_bridge/inc/exports.h @@ -0,0 +1,29 @@ +#ifndef API_H +#define API_H + +//# EXPORTS +// Returns 0 on success +int r_mem(unsigned long long addr, unsigned long long len, void *dest); +// // Returns 0 on success +int w_mem(unsigned long long addr, unsigned long long len, void *src); +// Returns num of bytes read; +int r_reg(unsigned char reg, void *dest); +// // Returns num of bytes written +int w_reg(unsigned char reg, char *src); + + +//NOTE hook function must be named hook_<16 hex character at_addr> +//NOTE must define function `struct conf* configure()` +struct conf{ + unsigned char IP_reg_num; + unsigned long long entry_addr; + unsigned long long* hooks; + unsigned long long num_hooks; +}conf; + +struct ret{ + unsigned long long addr; + char remove_bp; +}; + +#endif \ No newline at end of file diff --git a/qemu_mode/hooking_bridge/src/main.c b/qemu_mode/hooking_bridge/src/main.c new file mode 100644 index 00000000..98e8da98 --- /dev/null +++ b/qemu_mode/hooking_bridge/src/main.c @@ -0,0 +1,36 @@ +#include +#include +#include "common.h" + +QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION; + +static void finish_cb(qemu_plugin_id_t id, void *userdata) { + + patch_finish_cb(userdata); + +} + +static void block_trans_cb(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) { + + patch_block_trans_cb(tb); + +} + +static void vpu_init_cb(qemu_plugin_id_t id, unsigned int vcpu_index) { + + patch_vpu_init_cb(vcpu_index); + +} + +QEMU_PLUGIN_EXPORT +int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info, int argc, + char **argv) { + + patch_init(argv[0]); + qemu_plugin_register_vcpu_init_cb(id, vpu_init_cb); + qemu_plugin_register_vcpu_tb_trans_cb(id, block_trans_cb); + qemu_plugin_register_atexit_cb(id, finish_cb, NULL); + return 0; + +} + diff --git a/qemu_mode/hooking_bridge/src/patching.c b/qemu_mode/hooking_bridge/src/patching.c new file mode 100644 index 00000000..123ad99d --- /dev/null +++ b/qemu_mode/hooking_bridge/src/patching.c @@ -0,0 +1,173 @@ +#include +#include +#include +#include +#include "common.h" +#include "exports.h" + +void *handle; +struct conf *config; +struct conf *(*configure)(); +GByteArray *out; +void *cpu; +char cbuf[100]; + +// region GDB Imports +#pragma region GDB Imports +void cpu_single_step(void *cpu, int enabled); +int get_sstep_flags(void); +void gdb_accept_init(int fd); +int gdb_breakpoint_insert(int type, unsigned long long addr, + unsigned long long len); +int gdb_breakpoint_remove(int type, unsigned long long addr, + unsigned long long len); +void *qemu_get_cpu(int index); +int target_memory_rw_debug(void *cpu, unsigned long long addr, void *ptr, + unsigned long long len, char is_write); +int gdb_read_register(void *cs, GByteArray *mem_buf, int n); +int gdb_write_register(void *cs, char *mem_buf, int n); +void gdb_set_cpu_pc(unsigned long long pc); +void gdb_continue(void); +#pragma endregion GDB Imports + +// region API +int r_mem(unsigned long long addr, unsigned long long len, void *dest) { + + return target_memory_rw_debug(cpu, addr, dest, len, 0); + +} + +int w_mem(unsigned long long addr, unsigned long long len, void *src) { + + return target_memory_rw_debug(cpu, addr, src, len, 1); + +} + +int r_reg(unsigned char reg, void *dest) { + + g_byte_array_steal(out, NULL); + int op = gdb_read_register(cpu, out, reg); + memcpy(dest, out->data, out->len); + return op; + +} + +int w_reg(unsigned char reg, char *src) { + + return gdb_write_register(cpu, src, reg); + +} + +// region Breakpoint handling +char single_stepped; +unsigned long long gen_addr; +struct ret *(*hook)(); +struct ret *returned; +// Defined and imported gdbstub.c +void set_signal_callback(void (*cb)(int)); +// Breakpoints are set here +void patch_block_trans_cb(struct qemu_plugin_tb *tb) { + + unsigned long long addr; + addr = qemu_plugin_tb_vaddr(tb); + + if (addr == config->entry_addr) { + + // NOTE This means we cannot put a BP in the first basic block + gdb_accept_init(-1); + for (int i = 0; i < config->num_hooks; i++) { + + gdb_breakpoint_insert(0, config->hooks[i], 1); + + } + + } + +} + +void handle_signal_callback(int sig) { + + if (single_stepped) { + + single_stepped = 0; + gdb_breakpoint_insert(0, gen_addr, 1); + cpu_single_step(cpu, 0); + gdb_continue(); + return; + + } + + r_reg(config->IP_reg_num, cbuf); + gen_addr = *(unsigned long long *)cbuf; + + sprintf(cbuf, "hook_%016llx", gen_addr); + // TODO maybe find a way to put the hook function pointers in the TCG data + // structure instead of this dlsym call + *(unsigned long long **)(&hook) = dlsym(handle, cbuf); + if (!hook) { + + exit(-1); + + } + + returned = hook(); + + if (returned->remove_bp || + (returned->addr == + gen_addr)) { //* force removal of bp in returning to the same address, + //otherwise hook will be called again + gdb_breakpoint_remove(0, gen_addr, 1); + + } + + if (returned->addr == gen_addr) { + + single_stepped = 1; + cpu_single_step(cpu, get_sstep_flags()); + + } else { + + //* no need to rexecute the IP instruction + gdb_set_cpu_pc(returned->addr); + + } + + gdb_continue(); + +} + +// region Constructor/Destructor +void patch_finish_cb(void *userdata) { + + g_byte_array_free(out, 1); + dlclose(handle); + +} + +void patch_vpu_init_cb(unsigned int vcpu_index) { + + cpu = qemu_get_cpu(vcpu_index); + +} + +void patch_init(char *hook_lib) { + + // TODO make OS agnostic, remove dlopen + handle = dlopen(hook_lib, RTLD_NOW); + if (!handle) { + + fprintf(stderr, "DLOPEN Error: %s\n", dlerror()); + exit(-1); + + } + + single_stepped = 0; + + *(void **)(&configure) = dlsym(handle, "configure"); + config = configure(); + + set_signal_callback(handle_signal_callback); + out = g_byte_array_new(); + +} + -- cgit 1.4.1 From 43014cd465eec8cc47eda041802001776dbb5dd5 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 1 Jul 2024 08:57:26 +0200 Subject: changelog --- TODO.md | 3 +-- docs/Changelog.md | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/TODO.md b/TODO.md index c6da7fc5..81196339 100644 --- a/TODO.md +++ b/TODO.md @@ -2,8 +2,7 @@ ## Must - - in CLASSIC mode - do old forkserver model - - docs: AFL_DISABLE_REDUNDANT (large/slow/LAF) + - ijon support? - check for null ptr for xml/curl/g_ string transform functions - hardened_usercopy=0 page_alloc.shuffle=0 - add value_profile but only enable after 15 minutes without finds diff --git a/docs/Changelog.md b/docs/Changelog.md index 487c5688..d33d3121 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -18,6 +18,9 @@ a function entry - AFL_DEBUG is now the same as AFL_FRIDA_VERBOSE - AFL_FRIDA_DEBUG_MAPS now works as expected + - qemu_mode: + - new hooks supported (optional), see qemu_mode/hooking_bridge - thanks to + @CowBoy4mH3LL - custom mutators: - custom_send_tcp custom mutator added, thanks to @dergoegge - afl-cc -- cgit 1.4.1