From 1ee0946f692927eaaed9c8db1d006d8eb38631c3 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Thu, 21 Jan 2021 12:11:12 +0100 Subject: update changelog --- docs/Changelog.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'docs/Changelog.md') diff --git a/docs/Changelog.md b/docs/Changelog.md index 60f09ca5..daae7c47 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -11,22 +11,27 @@ sending a mail to . ### Version ++3.01a (dev) - Mac OS ARM64 support - - New selective instrumentation option with __AFL_COVERAGE_... commands + - Android support fixed and updated by Joey Jiaojg - thanks! + - New selective instrumentation option with __AFL_COVERAGE_* commands to be placed in the source code. Check out instrumentation/README.instrument_list.md - afl-fuzz + - upgraded cmplog/redqueen: solving for floating point, solving + transformations (e.g. toupper, tolower, to/from hex, xor, + arithmetics, etc.). this is costly hence new command line option + -l that sets the intensity (values 1 to 3). recommended is 1 or 2. - fix crash for very, very fast targets+systems (thanks to mhlakhani for reporting) - if determinstic mode is active (-D, or -M without -d) then we sync after every queue entry as this can take very long time otherwise - better detection if a target needs a large shared map - - switched to a faster RNG + - switched to an even faster RNG - added hghwng's patch for faster trace map analysis - afl-cc - allow instrumenting LLVMFuzzerTestOneInput - fixed endless loop for allow/blocklist lines starting with a comment (thanks to Zherya for reporting) - - cmplog/redqueen now also tracks floats/doubles + - cmplog/redqueen now also tracks floating point, _ExtInt() + 128bit - added AFL_LLVM_INSTRUMENT option NATIVE for native clang pc-guard support (less performant than our own), GCC for old afl-gcc and CLANG for old afl-clang @@ -35,7 +40,7 @@ sending a mail to . already building with all cores, the gcc plugin needs only one. - added dummy Makefile to instrumentation/ - Updated utils/afl_frida to be 5% faster - - Added AFL_KILL_SIGNAL env variable for custom targets (thanks @v-p-b) + - Added AFL_KILL_SIGNAL env variable (thanks @v-p-b) ### Version ++3.00c (release) - llvm_mode/ and gcc_plugin/ moved to instrumentation/ -- cgit 1.4.1 From ac21e4dd7304c3306a9acb5fa6ac051d3ab64b20 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Fri, 22 Jan 2021 00:41:23 +0100 Subject: typos --- README.md | 4 ++-- docs/Changelog.md | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'docs/Changelog.md') diff --git a/README.md b/README.md index ce48f336..2806b734 100644 --- a/README.md +++ b/README.md @@ -27,11 +27,11 @@ ## Major changes in afl++ 3.0 -With afl++ 3.0 we introduced changes that breaks some previous afl and afl++ +With afl++ 3.0 we introduced changes that break some previous afl and afl++ behaviours and defaults: * There are no llvm_mode and gcc_plugin subdirectories anymore and there is - only one compiler: afl-cc. All previous compilers now symlink to this. + only one compiler: afl-cc. All previous compilers now symlink to this one. All instrumentation source code is now in the `instrumentation/` folder. * The gcc_plugin was replaced with a new version submitted by AdaCore that supports more features. Thank you! diff --git a/docs/Changelog.md b/docs/Changelog.md index daae7c47..63e8e66e 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -35,7 +35,8 @@ sending a mail to . - added AFL_LLVM_INSTRUMENT option NATIVE for native clang pc-guard support (less performant than our own), GCC for old afl-gcc and CLANG for old afl-clang - - warn on any _AFL and __AFL env var + - changed default: no memory limit for afl-cmin and afl-cmin.bash + - warn on any _AFL and __AFL env vars - LLVM mode is now compiled with -j4, unicorn with all cores. qemu was already building with all cores, the gcc plugin needs only one. - added dummy Makefile to instrumentation/ -- cgit 1.4.1 From baf1ac2e69145d9e411f13df8ab4e7060f2f2685 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Fri, 22 Jan 2021 15:58:12 +0100 Subject: basic cmplog std::string support --- docs/Changelog.md | 2 + instrumentation/afl-compiler-rt.o.c | 4 +- instrumentation/cmplog-routines-pass.cc | 214 ++++++++++++++++++++++++++++++-- 3 files changed, 209 insertions(+), 11 deletions(-) (limited to 'docs/Changelog.md') diff --git a/docs/Changelog.md b/docs/Changelog.md index 63e8e66e..2b8b0e8d 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -32,6 +32,8 @@ sending a mail to . - fixed endless loop for allow/blocklist lines starting with a comment (thanks to Zherya for reporting) - cmplog/redqueen now also tracks floating point, _ExtInt() + 128bit + - cmplog/redqueen can now process basic libc++ and libstdc++ + std::string comparisons (though no position or length type variants) - added AFL_LLVM_INSTRUMENT option NATIVE for native clang pc-guard support (less performant than our own), GCC for old afl-gcc and CLANG for old afl-clang diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index 322141ba..433a1d89 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -1549,10 +1549,10 @@ void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) { u32 i; if (!area_is_mapped(ptr1, 32) || !area_is_mapped(ptr2, 32)) return; fprintf(stderr, "rtn arg0="); - for (i = 0; i < 8; i++) + for (i = 0; i < 24; i++) fprintf(stderr, "%02x", ptr1[i]); fprintf(stderr, " arg1="); - for (i = 0; i < 8; i++) + for (i = 0; i < 24; i++) fprintf(stderr, "%02x", ptr2[i]); fprintf(stderr, "\n"); */ diff --git a/instrumentation/cmplog-routines-pass.cc b/instrumentation/cmplog-routines-pass.cc index 8adf42d5..9d6999ca 100644 --- a/instrumentation/cmplog-routines-pass.cc +++ b/instrumentation/cmplog-routines-pass.cc @@ -87,7 +87,7 @@ char CmpLogRoutines::ID = 0; bool CmpLogRoutines::hookRtns(Module &M) { - std::vector calls; + std::vector calls, llvmStdStd, llvmStdC, gccStdStd, gccStdC; LLVMContext & C = M.getContext(); Type *VoidTy = Type::getVoidTy(C); @@ -112,6 +112,78 @@ bool CmpLogRoutines::hookRtns(Module &M) { FunctionCallee cmplogHookFn = c; #endif +#if LLVM_VERSION_MAJOR < 9 + Constant * +#else + FunctionCallee +#endif + c1 = M.getOrInsertFunction("__cmplog_rtn_llvm_stdstring_stdstring", + VoidTy, i8PtrTy, i8PtrTy +#if LLVM_VERSION_MAJOR < 5 + , + NULL +#endif + ); +#if LLVM_VERSION_MAJOR < 9 + Function *cmplogLlvmStdStd = cast(c1); +#else + FunctionCallee cmplogLlvmStdStd = c1; +#endif + +#if LLVM_VERSION_MAJOR < 9 + Constant * +#else + FunctionCallee +#endif + c2 = M.getOrInsertFunction("__cmplog_rtn_llvm_stdstring_cstring", VoidTy, + i8PtrTy, i8PtrTy +#if LLVM_VERSION_MAJOR < 5 + , + NULL +#endif + ); +#if LLVM_VERSION_MAJOR < 9 + Function *cmplogLlvmStdC = cast(c2); +#else + FunctionCallee cmplogLlvmStdC = c2; +#endif + +#if LLVM_VERSION_MAJOR < 9 + Constant * +#else + FunctionCallee +#endif + c3 = M.getOrInsertFunction("__cmplog_rtn_gcc_stdstring_stdstring", VoidTy, + i8PtrTy, i8PtrTy +#if LLVM_VERSION_MAJOR < 5 + , + NULL +#endif + ); +#if LLVM_VERSION_MAJOR < 9 + Function *cmplogGccStdStd = cast(c3); +#else + FunctionCallee cmplogGccStdStd = c3; +#endif + +#if LLVM_VERSION_MAJOR < 9 + Constant * +#else + FunctionCallee +#endif + c4 = M.getOrInsertFunction("__cmplog_rtn_gcc_stdstring_cstring", VoidTy, + i8PtrTy, i8PtrTy +#if LLVM_VERSION_MAJOR < 5 + , + NULL +#endif + ); +#if LLVM_VERSION_MAJOR < 9 + Function *cmplogGccStdC = cast(c4); +#else + FunctionCallee cmplogGccStdC = c4; +#endif + /* iterate over all functions, bbs and instruction and add suitable calls */ for (auto &F : M) { @@ -131,19 +203,67 @@ bool CmpLogRoutines::hookRtns(Module &M) { FunctionType *FT = Callee->getFunctionType(); - // _ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7compareEmmPKcm - // => libc++ => llvm => __cmplog_rtn_llvm_stdstring_cstring(u8 *stdstring1, u8 *stdstring2) - // _ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE7compareEPKc - // => libstdc++ => gcc => __cmplog_rtn_gcc_stdstring_cstring - bool isPtrRtn = FT->getNumParams() >= 2 && !FT->getReturnType()->isVoidTy() && FT->getParamType(0) == FT->getParamType(1) && FT->getParamType(0)->isPointerTy(); - if (!isPtrRtn) continue; - - calls.push_back(callInst); + bool isGccStdStringStdString = + Callee->getName().find("__is_charIT_EE7__value") != + std::string::npos && + Callee->getName().find( + "St7__cxx1112basic_stringIS2_St11char_traits") != + std::string::npos && + FT->getNumParams() >= 2 && + FT->getParamType(0) == FT->getParamType(1) && + FT->getParamType(0)->isPointerTy(); + + bool isGccStdStringCString = + Callee->getName().find( + "St7__cxx1112basic_stringIcSt11char_" + "traitsIcESaIcEE7compareEPK") != std::string::npos && + FT->getNumParams() >= 2 && FT->getParamType(0)->isPointerTy() && + FT->getParamType(1)->isPointerTy(); + + bool isLlvmStdStringStdString = + Callee->getName().find("_ZNSt3__1eqINS") != std::string::npos && + Callee->getName().find("_12basic_stringIcNS_11char_traits") != + std::string::npos && + FT->getNumParams() >= 2 && FT->getParamType(0)->isPointerTy() && + FT->getParamType(1)->isPointerTy(); + + bool isLlvmStdStringCString = + Callee->getName().find("ZNSt3__1eqIcNS") != std::string::npos && + Callee->getName().find("_12basic_stringI") != std::string::npos && + FT->getNumParams() >= 2 && FT->getParamType(0)->isPointerTy() && + FT->getParamType(1)->isPointerTy(); + + /* + fprintf(stderr, "F:%s C:%s argc:%u\n", + F.getName().str().c_str(), Callee->getName().str().c_str(), + FT->getNumParams()); fprintf(stderr, "ptr0:%u ptr1:%u ptr2:%u\n", + FT->getParamType(0)->isPointerTy(), + FT->getParamType(1)->isPointerTy(), + FT->getNumParams() > 2 ? FT->getParamType(2)->isPointerTy() + : 22 ); + */ + + if (isGccStdStringCString || isGccStdStringStdString || + isLlvmStdStringStdString || isLlvmStdStringCString) { + + isPtrRtn = false; + + fprintf(stderr, "%u %u %u %u\n", isGccStdStringCString, + isGccStdStringStdString, isLlvmStdStringStdString, + isLlvmStdStringCString); + + } + + if (isPtrRtn) { calls.push_back(callInst); } + if (isGccStdStringStdString) { gccStdStd.push_back(callInst); } + if (isGccStdStringCString) { gccStdC.push_back(callInst); } + if (isLlvmStdStringStdString) { llvmStdStd.push_back(callInst); } + if (isLlvmStdStringCString) { llvmStdC.push_back(callInst); } } @@ -179,6 +299,82 @@ bool CmpLogRoutines::hookRtns(Module &M) { } + for (auto &callInst : gccStdStd) { + + Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1); + + IRBuilder<> IRB(callInst->getParent()); + IRB.SetInsertPoint(callInst); + + std::vector args; + Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); + Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); + args.push_back(v1Pcasted); + args.push_back(v2Pcasted); + + IRB.CreateCall(cmplogGccStdStd, args); + + // errs() << callInst->getCalledFunction()->getName() << "\n"; + + } + + for (auto &callInst : gccStdC) { + + Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1); + + IRBuilder<> IRB(callInst->getParent()); + IRB.SetInsertPoint(callInst); + + std::vector args; + Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); + Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); + args.push_back(v1Pcasted); + args.push_back(v2Pcasted); + + IRB.CreateCall(cmplogGccStdC, args); + + // errs() << callInst->getCalledFunction()->getName() << "\n"; + + } + + for (auto &callInst : llvmStdStd) { + + Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1); + + IRBuilder<> IRB(callInst->getParent()); + IRB.SetInsertPoint(callInst); + + std::vector args; + Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); + Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); + args.push_back(v1Pcasted); + args.push_back(v2Pcasted); + + IRB.CreateCall(cmplogLlvmStdStd, args); + + // errs() << callInst->getCalledFunction()->getName() << "\n"; + + } + + for (auto &callInst : llvmStdC) { + + Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1); + + IRBuilder<> IRB(callInst->getParent()); + IRB.SetInsertPoint(callInst); + + std::vector args; + Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); + Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); + args.push_back(v1Pcasted); + args.push_back(v2Pcasted); + + IRB.CreateCall(cmplogLlvmStdC, args); + + // errs() << callInst->getCalledFunction()->getName() << "\n"; + + } + return true; } -- cgit 1.4.1 From b0a8bc28d2465292c5d1aff2e1d87ffeb65a2324 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 23 Jan 2021 00:13:32 +0100 Subject: changelog --- docs/Changelog.md | 3 +++ 1 file changed, 3 insertions(+) (limited to 'docs/Changelog.md') diff --git a/docs/Changelog.md b/docs/Changelog.md index 63e8e66e..97f816b6 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -35,6 +35,9 @@ sending a mail to . - added AFL_LLVM_INSTRUMENT option NATIVE for native clang pc-guard support (less performant than our own), GCC for old afl-gcc and CLANG for old afl-clang + - unicornafl + - Substential speed gains in python bindings for certain use cases + - Added a new example harness to compare python, c, and rust bindings - changed default: no memory limit for afl-cmin and afl-cmin.bash - warn on any _AFL and __AFL env vars - LLVM mode is now compiled with -j4, unicorn with all cores. qemu was -- cgit 1.4.1 From afc15965c00b6b2646902d8073cf9c925862b853 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 25 Jan 2021 02:01:34 +0100 Subject: updated unicornalf, bindings --- docs/Changelog.md | 1 + unicorn_mode/UNICORNAFL_VERSION | 2 +- unicorn_mode/samples/speedtest/rust/src/main.rs | 5 +++-- unicorn_mode/unicornafl | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) (limited to 'docs/Changelog.md') diff --git a/docs/Changelog.md b/docs/Changelog.md index 062dd785..12f81571 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -39,6 +39,7 @@ sending a mail to . CLANG for old afl-clang - unicornafl - Substential speed gains in python bindings for certain use cases + - Improved rust bindings - Added a new example harness to compare python, c, and rust bindings - changed default: no memory limit for afl-cmin and afl-cmin.bash - warn on any _AFL and __AFL env vars diff --git a/unicorn_mode/UNICORNAFL_VERSION b/unicorn_mode/UNICORNAFL_VERSION index f1fb7f18..a02531ec 100644 --- a/unicorn_mode/UNICORNAFL_VERSION +++ b/unicorn_mode/UNICORNAFL_VERSION @@ -1 +1 @@ -0dd17c58 +2a54500c diff --git a/unicorn_mode/samples/speedtest/rust/src/main.rs b/unicorn_mode/samples/speedtest/rust/src/main.rs index 8e31d2e2..1e35ff0b 100644 --- a/unicorn_mode/samples/speedtest/rust/src/main.rs +++ b/unicorn_mode/samples/speedtest/rust/src/main.rs @@ -194,18 +194,19 @@ fn fuzz(input_file: &str) -> Result<(), uc_error> { } let place_input_callback = - |mut uc: UnicornHandle<'_, _>, afl_input: &[u8], _persistent_round| { + |mut uc: UnicornHandle<'_, _>, afl_input: &mut [u8], _persistent_round| { // apply constraints to the mutated input if afl_input.len() > INPUT_MAX as usize { //println!("Skipping testcase with leng {}", afl_input.len()); return false; } - // TODO: afl_input[-1] = b'\0' + afl_input[afl_input.len() - 1] = b'\0'; uc.mem_write(INPUT_ADDRESS, afl_input).unwrap(); true }; + // return true if the last run should be counted as crash let crash_validation_callback = |_uc: UnicornHandle<'_, _>, result, _input: &[u8], _persistent_round| { result != uc_error::OK diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl index 0dd17c58..2a54500c 160000 --- a/unicorn_mode/unicornafl +++ b/unicorn_mode/unicornafl @@ -1 +1 @@ -Subproject commit 0dd17c58d51ed6dc69a367adbe8d2dca4d224c4d +Subproject commit 2a54500c08758d29caacd1ccf47d034d9faa4a18 -- cgit 1.4.1 From 9a7531942dd02797c69dd23ee8e13f504a8a30a7 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Mon, 25 Jan 2021 10:04:21 +0100 Subject: fix rpc_stats.md --- docs/Changelog.md | 2 ++ docs/rpc_statsd.md | 6 +++--- docs/visualization/StatsD-grafana.png | Bin 163646 -> 0 bytes docs/visualization/statsd-grafana.png | Bin 0 -> 163646 bytes 4 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 docs/visualization/StatsD-grafana.png create mode 100644 docs/visualization/statsd-grafana.png (limited to 'docs/Changelog.md') diff --git a/docs/Changelog.md b/docs/Changelog.md index 12f81571..5c6b0663 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -48,6 +48,8 @@ sending a mail to . - added dummy Makefile to instrumentation/ - Updated utils/afl_frida to be 5% faster - Added AFL_KILL_SIGNAL env variable (thanks @v-p-b) + - @Edznux added a nice documentation on how to use rpc.statsd with + afl++ in docs/rpc_statsd.md, thanks! ### Version ++3.00c (release) - llvm_mode/ and gcc_plugin/ moved to instrumentation/ diff --git a/docs/rpc_statsd.md b/docs/rpc_statsd.md index 26544ff5..02f72be6 100644 --- a/docs/rpc_statsd.md +++ b/docs/rpc_statsd.md @@ -31,9 +31,9 @@ By doing so, you might be able to see when the fuzzing process has reached a sta (according to your own criteria) for your targets, etc. And doing so without requiring to log into each instance manually. An example visualisation may look like the following: -![StatsD Grafana](./visualization/StatsD-grafana.png) +![StatsD Grafana](visualization/statsd-grafana.png) -*Notes: The exact same dashboard can be imported with [this JSON template](./statsd/grafana-afl++.json).* +*Notes: The exact same dashboard can be imported with [this JSON template](statsd/grafana-afl++.json).* ## How to use @@ -140,4 +140,4 @@ AFL_STATSD_TAGS_FLAVOR=dogstatsd AFL_STATSD=1 afl-fuzz -S test-fuzzer-2 -i i -o ``` This setup may be modified before use in production environment. Depending on your needs: addind passwords, creating volumes for storage, -tweaking the metrics gathering to get host metrics (CPU, RAM ...). \ No newline at end of file +tweaking the metrics gathering to get host metrics (CPU, RAM ...). diff --git a/docs/visualization/StatsD-grafana.png b/docs/visualization/StatsD-grafana.png deleted file mode 100644 index 1bdc1722..00000000 Binary files a/docs/visualization/StatsD-grafana.png and /dev/null differ diff --git a/docs/visualization/statsd-grafana.png b/docs/visualization/statsd-grafana.png new file mode 100644 index 00000000..1bdc1722 Binary files /dev/null and b/docs/visualization/statsd-grafana.png differ -- cgit 1.4.1 From aaec45b6528e41a217de95ca3db1173fb2539672 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Fri, 29 Jan 2021 18:51:44 +0100 Subject: changelog --- docs/Changelog.md | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'docs/Changelog.md') diff --git a/docs/Changelog.md b/docs/Changelog.md index 5c6b0663..dd160b14 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -37,6 +37,11 @@ sending a mail to . - added AFL_LLVM_INSTRUMENT option NATIVE for native clang pc-guard support (less performant than our own), GCC for old afl-gcc and CLANG for old afl-clang + - qemuafl + - solved some persistent mode bugs (thanks Dil4rd) + - solved an issue when dumping the memory maps (thanks wizche) + - ported QASan to qemuafl + - ported the QASan runtime adding support for Android - unicornafl - Substential speed gains in python bindings for certain use cases - Improved rust bindings -- cgit 1.4.1 From 2f96f1e9204f60d0a1b91a01f5da34b64b29cf9b Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sat, 30 Jan 2021 10:28:34 +0100 Subject: afl-frida faster for x86_x64 --- docs/Changelog.md | 6 ++-- utils/afl_frida/afl-frida.c | 87 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 89 insertions(+), 4 deletions(-) (limited to 'docs/Changelog.md') diff --git a/docs/Changelog.md b/docs/Changelog.md index dd160b14..329b7520 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -38,10 +38,10 @@ sending a mail to . support (less performant than our own), GCC for old afl-gcc and CLANG for old afl-clang - qemuafl + - ported QASan to qemuafl! see qemu_mode/libqasan/README.md - solved some persistent mode bugs (thanks Dil4rd) - solved an issue when dumping the memory maps (thanks wizche) - - ported QASan to qemuafl - - ported the QASan runtime adding support for Android + - Android support for QASan - unicornafl - Substential speed gains in python bindings for certain use cases - Improved rust bindings @@ -51,7 +51,7 @@ sending a mail to . - LLVM mode is now compiled with -j4, unicorn with all cores. qemu was already building with all cores, the gcc plugin needs only one. - added dummy Makefile to instrumentation/ - - Updated utils/afl_frida to be 5% faster + - Updated utils/afl_frida to be 5% faster, 7% on x86_x64 - Added AFL_KILL_SIGNAL env variable (thanks @v-p-b) - @Edznux added a nice documentation on how to use rpc.statsd with afl++ in docs/rpc_statsd.md, thanks! diff --git a/utils/afl_frida/afl-frida.c b/utils/afl_frida/afl-frida.c index 85cf2e9d..711d8f33 100644 --- a/utils/afl_frida/afl-frida.c +++ b/utils/afl_frida/afl-frida.c @@ -94,6 +94,8 @@ typedef struct { GumAddress base_address; guint64 code_start, code_end; + GumAddress current_log_impl; + uint64_t afl_prev_loc; } range_t; @@ -109,12 +111,58 @@ inline static void afl_maybe_log(guint64 current_pc) { } +#if GUM_NATIVE_CPU == GUM_CPU_AMD64 + +static const guint8 afl_maybe_log_code[] = { + + 0x9c, // pushfq + 0x50, // push rax + 0x51, // push rcx + 0x52, // push rdx + 0x56, // push rsi + + 0x89, 0xf8, // mov eax, edi + 0xc1, 0xe0, 0x08, // shl eax, 8 + 0xc1, 0xef, 0x04, // shr edi, 4 + 0x31, 0xc7, // xor edi, eax + 0x0f, 0xb7, 0xc7, // movzx eax, di + 0x48, 0x8d, 0x0d, 0x30, 0x00, 0x00, 0x00, // lea rcx, sym._afl_area_ptr_ptr + 0x48, 0x8b, 0x09, // mov rcx, qword [rcx] + 0x48, 0x8b, 0x09, // mov rcx, qword [rcx] + 0x48, 0x8d, 0x15, 0x1b, 0x00, 0x00, 0x00, // lea rdx, sym._afl_prev_loc_ptr + 0x48, 0x8b, 0x32, // mov rsi, qword [rdx] + 0x48, 0x8b, 0x36, // mov rsi, qword [rsi] + 0x48, 0x31, 0xc6, // xor rsi, rax + 0xfe, 0x04, 0x31, // inc byte [rcx + rsi] + + 0x48, 0xd1, 0xe8, // shr rax, 1 + 0x48, 0x8b, 0x0a, // mov rcx, qword [rdx] + 0x48, 0x89, 0x01, // mov qword [rcx], rax + + 0x5e, // pop rsi + 0x5a, // pop rdx + 0x59, // pop rcx + 0x58, // pop rax + 0x9d, // popfq + + 0xc3, // ret + // Read-only data goes here: + // uint64_t* afl_prev_loc_ptr + // uint8_t** afl_area_ptr_ptr + // unsigned int afl_instr_rms + +}; + +#else + static void on_basic_block(GumCpuContext *context, gpointer user_data) { afl_maybe_log((guint64)user_data); } +#endif + void instr_basic_block(GumStalkerIterator *iterator, GumStalkerOutput *output, gpointer user_data) { @@ -129,8 +177,45 @@ void instr_basic_block(GumStalkerIterator *iterator, GumStalkerOutput *output, if (instr->address >= range->code_start && instr->address <= range->code_end) { +#if GUM_NATIVE_CPU == GUM_CPU_AMD64 + GumX86Writer *cw = output->writer.x86; + if (range->current_log_impl == 0 || + !gum_x86_writer_can_branch_directly_between( + cw->pc, range->current_log_impl) || + !gum_x86_writer_can_branch_directly_between( + cw->pc + 128, range->current_log_impl)) { + + gconstpointer after_log_impl = cw->code + 1; + + gum_x86_writer_put_jmp_near_label(cw, after_log_impl); + + range->current_log_impl = cw->pc; + gum_x86_writer_put_bytes(cw, afl_maybe_log_code, + sizeof(afl_maybe_log_code)); + + uint64_t *afl_prev_loc_ptr = &range->afl_prev_loc; + uint8_t **afl_area_ptr_ptr = &__afl_area_ptr; + gum_x86_writer_put_bytes(cw, (const guint8 *)&afl_prev_loc_ptr, + sizeof(afl_prev_loc_ptr)); + gum_x86_writer_put_bytes(cw, (const guint8 *)&afl_area_ptr_ptr, + sizeof(afl_area_ptr_ptr)); + gum_x86_writer_put_label(cw, after_log_impl); + + } + + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, + -GUM_RED_ZONE_SIZE); + gum_x86_writer_put_push_reg(cw, GUM_REG_RDI); + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RDI, + GUM_ADDRESS(instr->address)); + gum_x86_writer_put_call_address(cw, range->current_log_impl); + gum_x86_writer_put_pop_reg(cw, GUM_REG_RDI); + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, + GUM_RED_ZONE_SIZE); +#else gum_stalker_iterator_put_callout(iterator, on_basic_block, (gpointer)instr->address, NULL); +#endif begin = FALSE; } @@ -228,7 +313,7 @@ int main(int argc, char **argv) { guint64 code_start = code_range.base_address; guint64 code_end = code_range.base_address + code_range.size; - range_t instr_range = {0, code_start, code_end}; + range_t instr_range = {0, code_start, code_end, 0, 0}; printf("Frida instrumentation: base=0x%lx instrumenting=0x%lx-%lx\n", base_address, code_start, code_end); -- cgit 1.4.1 From 9d08f0d098c91e69b5fe41674e4c5d05363af604 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sat, 30 Jan 2021 15:39:47 +0100 Subject: added AFL_CMPLOG_ONLY_NEW feature --- docs/Changelog.md | 2 + docs/env_variables.md | 5 ++ include/afl-fuzz.h | 2 +- include/common.h | 2 +- include/envs.h | 1 + src/afl-analyze.c | 22 ++++---- src/afl-common.c | 6 +-- src/afl-fuzz-init.c | 3 ++ src/afl-fuzz-one.c | 5 +- src/afl-fuzz-redqueen.c | 135 +++++++++++++++++++++++++----------------------- src/afl-fuzz-state.c | 7 +++ src/afl-fuzz.c | 35 +++++++------ src/afl-showmap.c | 24 ++++----- src/afl-tmin.c | 24 ++++----- 14 files changed, 147 insertions(+), 126 deletions(-) (limited to 'docs/Changelog.md') diff --git a/docs/Changelog.md b/docs/Changelog.md index 329b7520..6e59961b 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -20,6 +20,8 @@ sending a mail to . transformations (e.g. toupper, tolower, to/from hex, xor, arithmetics, etc.). this is costly hence new command line option -l that sets the intensity (values 1 to 3). recommended is 1 or 2. + - added `AFL_CMPLOG_ONLY_NEW` to not use cmplog on initial testcases from + `-i` or resumes (as these have most likely already been done) - fix crash for very, very fast targets+systems (thanks to mhlakhani for reporting) - if determinstic mode is active (-D, or -M without -d) then we sync diff --git a/docs/env_variables.md b/docs/env_variables.md index 66d85749..4c3b1cfb 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -287,6 +287,11 @@ checks or alter some of the more exotic semantics of the tool: the target. This must be equal or larger than the size the target was compiled with. + - `AFL_CMPLOG_ONLY_NEW` will only perform the expensive cmplog feature for + newly found testcases and not for testcases that are loaded on startup + (`-i in`). This is an important feature to set when resuming a fuzzing + session. + - `AFL_TESTCACHE_SIZE` allows you to override the size of `#define TESTCASE_CACHE` in config.h. Recommended values are 50-250MB - or more if your fuzzing finds a huge amount of paths for large inputs. diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 12db9e4d..e8a21cb5 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -384,7 +384,7 @@ typedef struct afl_env_vars { 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_bench_until_crash, afl_debug_child, afl_autoresume, afl_cal_fast, - afl_cycle_schedules, afl_expand_havoc, afl_statsd; + afl_cycle_schedules, afl_expand_havoc, afl_statsd, afl_cmplog_only_new; u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path, *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_skip_crashes, *afl_preload, diff --git a/include/common.h b/include/common.h index bdaa1735..bb8831f2 100644 --- a/include/common.h +++ b/include/common.h @@ -47,7 +47,7 @@ void argv_cpy_free(char **argv); char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv); char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv); char * get_afl_env(char *env); -u8 *get_libqasan_path(u8 *own_loc); +u8 * get_libqasan_path(u8 *own_loc); extern u8 be_quiet; extern u8 *doc_path; /* path to documentation dir */ diff --git a/include/envs.h b/include/envs.h index 926c9e27..210b34a6 100644 --- a/include/envs.h +++ b/include/envs.h @@ -28,6 +28,7 @@ static char *afl_environment_variables[] = { "AFL_CC", "AFL_CMIN_ALLOW_ANY", "AFL_CMIN_CRASHES_ONLY", + "AFL_CMPLOG_ONLY_NEW", "AFL_CODE_END", "AFL_CODE_START", "AFL_COMPCOV_BINNAME", diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 28598ba0..20aef2da 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -1079,28 +1079,28 @@ int main(int argc, char **argv_orig, char **envp) { if (optind == argc || !in_file) { usage(argv[0]); } if (qemu_mode && getenv("AFL_USE_QASAN")) { - - u8* preload = getenv("AFL_PRELOAD"); - u8* libqasan = get_libqasan_path(argv_orig[0]); - + + u8 *preload = getenv("AFL_PRELOAD"); + u8 *libqasan = get_libqasan_path(argv_orig[0]); + if (!preload) { - + setenv("AFL_PRELOAD", libqasan, 0); - + } else { - + u8 *result = ck_alloc(strlen(libqasan) + strlen(preload) + 2); strcpy(result, libqasan); strcat(result, " "); strcat(result, preload); - + setenv("AFL_PRELOAD", result, 1); ck_free(result); - + } - + ck_free(libqasan); - + } map_size = get_map_size(); diff --git a/src/afl-common.c b/src/afl-common.c index a69f2e97..235c4c05 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -364,11 +364,7 @@ u8 *get_libqasan_path(u8 *own_loc) { cp = alloc_printf("%s/libqasan.so", own_copy); ck_free(own_copy); - if (!access(cp, X_OK)) { - - return cp; - - } + if (!access(cp, X_OK)) { return cp; } } else { diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 1808f0a1..2a7864f9 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -25,6 +25,7 @@ #include "afl-fuzz.h" #include +#include "cmplog.h" #ifdef HAVE_AFFINITY @@ -833,6 +834,8 @@ void perform_dry_run(afl_state_t *afl) { } + if (afl->afl_env.afl_cmplog_only_new) { q->colorized = CMPLOG_LVL_MAX; } + u8 *fn = strrchr(q->fname, '/') + 1; ACTF("Attempting dry run with '%s'...", fn); diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index ff766158..0cf889a8 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -26,6 +26,7 @@ #include "afl-fuzz.h" #include #include +#include "cmplog.h" /* MOpt */ @@ -553,7 +554,7 @@ u8 fuzz_one_original(afl_state_t *afl) { if (unlikely(len < 4)) { - afl->queue_cur->colorized = 0xff; + afl->queue_cur->colorized = CMPLOG_LVL_MAX; } else { @@ -2981,7 +2982,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { if (unlikely(len < 4)) { - afl->queue_cur->colorized = 0xff; + afl->queue_cur->colorized = CMPLOG_LVL_MAX; } else { diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index fc620781..d7657c1d 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -1118,7 +1118,11 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, #ifdef ARITHMETIC_LESSER_GREATER if (lvl < LVL3 || attr == IS_TRANSFORM) { return 0; } - if (!(attr & (IS_GREATER | IS_LESSER)) || SHAPE_BYTES(h->shape) < 4) { return 0; } + if (!(attr & (IS_GREATER | IS_LESSER)) || SHAPE_BYTES(h->shape) < 4) { + + return 0; + + } // transform >= to < and <= to > if ((attr & IS_EQUAL) && (attr & (IS_GREATER | IS_LESSER))) { @@ -1138,110 +1142,110 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, // lesser/greater FP comparison if (attr >= IS_FP && attr < IS_FP_MOD) { - u64 repl_new; - - if (attr & IS_GREATER) { + u64 repl_new; - if (SHAPE_BYTES(h->shape) == 4 && its_len >= 4) { + if (attr & IS_GREATER) { - float *f = (float *)&repl; - float g = *f; - g += 1.0; - u32 *r = (u32 *)&g; - repl_new = (u32)*r; + if (SHAPE_BYTES(h->shape) == 4 && its_len >= 4) { - } else if (SHAPE_BYTES(h->shape) == 8 && its_len >= 8) { + float *f = (float *)&repl; + float g = *f; + g += 1.0; + u32 *r = (u32 *)&g; + repl_new = (u32)*r; - double *f = (double *)&repl; - double g = *f; - g += 1.0; + } else if (SHAPE_BYTES(h->shape) == 8 && its_len >= 8) { - u64 *r = (u64 *)&g; - repl_new = *r; + double *f = (double *)&repl; + double g = *f; + g += 1.0; - } else { + u64 *r = (u64 *)&g; + repl_new = *r; - return 0; + } else { - } + return 0; - changed_val = repl_new; + } - if (unlikely(cmp_extend_encoding( - afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx, - taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) { + changed_val = repl_new; - return 1; + if (unlikely(cmp_extend_encoding( + afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx, + taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) { - } + return 1; - } else { + } - if (SHAPE_BYTES(h->shape) == 4) { + } else { - float *f = (float *)&repl; - float g = *f; - g -= 1.0; - u32 *r = (u32 *)&g; - repl_new = (u32)*r; + if (SHAPE_BYTES(h->shape) == 4) { - } else if (SHAPE_BYTES(h->shape) == 8) { + float *f = (float *)&repl; + float g = *f; + g -= 1.0; + u32 *r = (u32 *)&g; + repl_new = (u32)*r; - double *f = (double *)&repl; - double g = *f; - g -= 1.0; - u64 *r = (u64 *)&g; - repl_new = *r; + } else if (SHAPE_BYTES(h->shape) == 8) { - } else { + double *f = (double *)&repl; + double g = *f; + g -= 1.0; + u64 *r = (u64 *)&g; + repl_new = *r; - return 0; + } else { - } + return 0; - changed_val = repl_new; + } - if (unlikely(cmp_extend_encoding( - afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx, - taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) { + changed_val = repl_new; - return 1; + if (unlikely(cmp_extend_encoding( + afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx, + taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) { - } + return 1; } - // transform double to float, llvm likes to do that internally ... - if (SHAPE_BYTES(h->shape) == 8 && its_len >= 4) { + } - double *f = (double *)&repl; - float g = (float)*f; - repl_new = 0; + // transform double to float, llvm likes to do that internally ... + if (SHAPE_BYTES(h->shape) == 8 && its_len >= 4) { + + double *f = (double *)&repl; + float g = (float)*f; + repl_new = 0; #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) - memcpy((char *)&repl_new, (char *)&g, 4); + memcpy((char *)&repl_new, (char *)&g, 4); #else - memcpy(((char *)&repl_new) + 4, (char *)&g, 4); + memcpy(((char *)&repl_new) + 4, (char *)&g, 4); #endif - changed_val = repl_new; - h->shape = 3; // modify shape - - // fprintf(stderr, "DOUBLE2FLOAT %llx\n", repl_new); + changed_val = repl_new; + h->shape = 3; // modify shape - if (unlikely(cmp_extend_encoding( - afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx, - taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) { + // fprintf(stderr, "DOUBLE2FLOAT %llx\n", repl_new); - h->shape = 7; // recover shape - return 1; - - } + if (unlikely(cmp_extend_encoding( + afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx, + taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) { h->shape = 7; // recover shape + return 1; } + h->shape = 7; // recover shape + } + } + else if (attr < IS_FP) { // lesser/greater integer comparison @@ -1707,6 +1711,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, try_to_add_to_dictN(afl, s128_v1, SHAPE_BYTES(h->shape)); } else + #endif { diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 8423a3d1..5040e3ef 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -236,6 +236,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_CMPLOG_ONLY_NEW", + + afl_environment_variable_len)) { + + afl->afl_env.afl_cmplog_only_new = + get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_NO_UI", afl_environment_variable_len)) { afl->afl_env.afl_no_ui = diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 312d9424..9d9b0434 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -181,6 +181,7 @@ static void usage(u8 *argv0, int more_help) { "AFL_AUTORESUME: resume fuzzing if directory specified by -o already exists\n" "AFL_BENCH_JUST_ONE: run the target just once\n" "AFL_BENCH_UNTIL_CRASH: exit soon when the first crashing input has been found\n" + "AFL_CMPLOG_ONLY_NEW: do not run cmplog on initial testcases (good for resumes!)\n" "AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n" "AFL_CUSTOM_MUTATOR_LIBRARY: lib with afl_custom_fuzz() to mutate inputs\n" "AFL_CUSTOM_MUTATOR_ONLY: avoid AFL++'s internal mutators\n" @@ -326,8 +327,9 @@ int main(int argc, char **argv_orig, char **envp) { "compile time)"); } + #endif - + char **argv = argv_cpy_dup(argc, argv_orig); afl_state_t *afl = calloc(1, sizeof(afl_state_t)); @@ -356,8 +358,7 @@ int main(int argc, char **argv_orig, char **envp) { while ((opt = getopt( argc, argv, - "+b:B:c:CdDe:E:hi:I:f:F:l:L:m:M:nNo:p:RQs:S:t:T:UV:Wx:Z")) > - 0) { + "+b:B:c:CdDe:E:hi:I:f:F:l:L:m:M:nNo:p:RQs:S:t:T:UV:Wx:Z")) > 0) { switch (opt) { @@ -984,31 +985,31 @@ int main(int argc, char **argv_orig, char **envp) { usage(argv[0], show_help); } - + if (afl->fsrv.qemu_mode && getenv("AFL_USE_QASAN")) { - - u8* preload = getenv("AFL_PRELOAD"); - u8* libqasan = get_libqasan_path(argv_orig[0]); - + + u8 *preload = getenv("AFL_PRELOAD"); + u8 *libqasan = get_libqasan_path(argv_orig[0]); + if (!preload) { - + setenv("AFL_PRELOAD", libqasan, 0); - + } else { - + u8 *result = ck_alloc(strlen(libqasan) + strlen(preload) + 2); strcpy(result, libqasan); strcat(result, " "); strcat(result, preload); - + setenv("AFL_PRELOAD", result, 1); ck_free(result); - + } - + afl->afl_env.afl_preload = (u8 *)getenv("AFL_PRELOAD"); ck_free(libqasan); - + } if (afl->fsrv.mem_limit && afl->shm.cmplog_mode) afl->fsrv.mem_limit += 260; @@ -1270,7 +1271,7 @@ int main(int argc, char **argv_orig, char **envp) { "instead of using AFL_PRELOAD?"); } - + if (afl->afl_env.afl_preload) { if (afl->fsrv.qemu_mode) { @@ -1322,7 +1323,7 @@ int main(int argc, char **argv_orig, char **envp) { FATAL("Use AFL_PRELOAD instead of AFL_LD_PRELOAD"); } - + save_cmdline(afl, argc, argv); fix_up_banner(afl, argv[optind]); diff --git a/src/afl-showmap.c b/src/afl-showmap.c index f3cd5a90..62bf1021 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -942,30 +942,30 @@ int main(int argc, char **argv_orig, char **envp) { } if (optind == argc || !out_file) { usage(argv[0]); } - + if (fsrv->qemu_mode && getenv("AFL_USE_QASAN")) { - - u8* preload = getenv("AFL_PRELOAD"); - u8* libqasan = get_libqasan_path(argv_orig[0]); - + + u8 *preload = getenv("AFL_PRELOAD"); + u8 *libqasan = get_libqasan_path(argv_orig[0]); + if (!preload) { - + setenv("AFL_PRELOAD", libqasan, 0); - + } else { - + u8 *result = ck_alloc(strlen(libqasan) + strlen(preload) + 2); strcpy(result, libqasan); strcat(result, " "); strcat(result, preload); - + setenv("AFL_PRELOAD", result, 1); ck_free(result); - + } - + ck_free(libqasan); - + } if (in_dir) { diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 9e9e2d63..09b5211d 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -1074,30 +1074,30 @@ int main(int argc, char **argv_orig, char **envp) { if (optind == argc || !in_file || !output_file) { usage(argv[0]); } check_environment_vars(envp); - + if (fsrv->qemu_mode && getenv("AFL_USE_QASAN")) { - - u8* preload = getenv("AFL_PRELOAD"); - u8* libqasan = get_libqasan_path(argv_orig[0]); - + + u8 *preload = getenv("AFL_PRELOAD"); + u8 *libqasan = get_libqasan_path(argv_orig[0]); + if (!preload) { - + setenv("AFL_PRELOAD", libqasan, 0); - + } else { - + u8 *result = ck_alloc(strlen(libqasan) + strlen(preload) + 2); strcpy(result, libqasan); strcat(result, " "); strcat(result, preload); - + setenv("AFL_PRELOAD", result, 1); ck_free(result); - + } - + ck_free(libqasan); - + } /* initialize cmplog_mode */ -- cgit 1.4.1 From 7a861498c27997cd7be01a5650d54cff3b87a02e Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sun, 31 Jan 2021 15:04:40 +0100 Subject: added support for __afl_coverage_interesting --- docs/Changelog.md | 3 ++ instrumentation/README.instrument_list.md | 7 +++++ instrumentation/SanitizerCoverageLTO.so.cc | 20 ++++++++++++++ instrumentation/SanitizerCoveragePCGUARD.so.cc | 38 +++++++++++++++++++++++--- src/afl-cc.c | 16 ++++++----- src/afl-fuzz.c | 5 ++-- 6 files changed, 76 insertions(+), 13 deletions(-) (limited to 'docs/Changelog.md') diff --git a/docs/Changelog.md b/docs/Changelog.md index 6e59961b..99bc8b47 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -36,6 +36,9 @@ sending a mail to . - cmplog/redqueen now also tracks floating point, _ExtInt() + 128bit - cmplog/redqueen can now process basic libc++ and libstdc++ std::string comparisons (though no position or length type variants) + - added support for __afl_coverage_interesting() for LTO and + and our own PCGUARD (llvm 10.0.1+), read more about this function + and selective coverage in instrumentation/README.instrument_list.md - added AFL_LLVM_INSTRUMENT option NATIVE for native clang pc-guard support (less performant than our own), GCC for old afl-gcc and CLANG for old afl-clang diff --git a/instrumentation/README.instrument_list.md b/instrumentation/README.instrument_list.md index b47b50f6..b7dfb40c 100644 --- a/instrumentation/README.instrument_list.md +++ b/instrumentation/README.instrument_list.md @@ -43,6 +43,13 @@ in any function where you want: * `__AFL_COVERAGE_DISCARD();` - reset all coverage gathered until this point * `__AFL_COVERAGE_SKIP();` - mark this test case as unimportant. Whatever happens, afl-fuzz will ignore it. +A special function is `__afl_coverage_interesting`. +To use this, you must define `void __afl_coverage_interesting(u8 val, u32 id);`. +Then you can use this function globally, where the `val` parameter can be set +by you, the `id` parameter is for afl-fuzz and will be overwritten. +Note that useful parameters are for `val` are: 1, 2, 3, 4, 8, 16, 32, 64, 128. +A value of e.g. 33 will be seen as 32 for coverage purposes. + ## 3) Selective instrumenation with AFL_LLVM_ALLOWLIST/AFL_LLVM_DENYLIST This feature is equivalent to llvm 12 sancov feature and allows to specify diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index 016ac71f..e3490847 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -1237,6 +1237,25 @@ void ModuleSanitizerCoverage::instrumentFunction( for (auto &BB : F) { + for (auto &IN : BB) { + + CallInst *callInst = nullptr; + + if ((callInst = dyn_cast(&IN))) { + + Function *Callee = callInst->getCalledFunction(); + if (!Callee) continue; + if (callInst->getCallingConv() != llvm::CallingConv::C) continue; + StringRef FuncName = Callee->getName(); + if (FuncName.compare(StringRef("__afl_coverage_interesting"))) continue; + + Value *val = ConstantInt::get(Int32Ty, ++afl_global_id); + callInst->setOperand(1, val); + + } + + } + if (shouldInstrumentBlock(F, &BB, DT, PDT, Options)) BlocksToInstrument.push_back(&BB); for (auto &Inst : BB) { @@ -1338,6 +1357,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, if (AllBlocks.empty()) return false; CreateFunctionLocalArrays(F, AllBlocks); + for (size_t i = 0, N = AllBlocks.size(); i < N; i++) { // afl++ START diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index ecd6bc9b..5b274770 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -311,7 +311,8 @@ class ModuleSanitizerCoverage { Function &F, Type *Ty, const char *Section); GlobalVariable *CreatePCArray(Function &F, ArrayRef AllBlocks); - void CreateFunctionLocalArrays(Function &F, ArrayRef AllBlocks); + void CreateFunctionLocalArrays(Function &F, ArrayRef AllBlocks, + uint32_t special); void InjectCoverageAtBlock(Function &F, BasicBlock &BB, size_t Idx, bool IsLeafFunc = true); Function *CreateInitCallsForSections(Module &M, const char *CtorName, @@ -970,11 +971,11 @@ GlobalVariable *ModuleSanitizerCoverage::CreatePCArray( } void ModuleSanitizerCoverage::CreateFunctionLocalArrays( - Function &F, ArrayRef AllBlocks) { + Function &F, ArrayRef AllBlocks, uint32_t special) { if (Options.TracePCGuard) FunctionGuardArray = CreateFunctionLocalArrayInSection( - AllBlocks.size(), F, Int32Ty, SanCovGuardsSectionName); + AllBlocks.size() + special, F, Int32Ty, SanCovGuardsSectionName); if (Options.Inline8bitCounters) Function8bitCounterArray = CreateFunctionLocalArrayInSection( @@ -993,9 +994,38 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, bool IsLeafFunc) { if (AllBlocks.empty()) return false; - CreateFunctionLocalArrays(F, AllBlocks); + + uint32_t special = 0; + for (auto &BB : F) { + + for (auto &IN : BB) { + + CallInst *callInst = nullptr; + + if ((callInst = dyn_cast(&IN))) { + + Function *Callee = callInst->getCalledFunction(); + StringRef FuncName = Callee->getName(); + if (!Callee) continue; + if (callInst->getCallingConv() != llvm::CallingConv::C) continue; + if (FuncName.compare(StringRef("__afl_coverage_interesting"))) continue; + + uint32_t id = 1 + instr + (uint32_t)AllBlocks.size() + special++; + Value * val = ConstantInt::get(Int32Ty, id); + callInst->setOperand(1, val); + + } + + } + + } + + CreateFunctionLocalArrays(F, AllBlocks, special); for (size_t i = 0, N = AllBlocks.size(); i < N; i++) InjectCoverageAtBlock(F, *AllBlocks[i], i, IsLeafFunc); + + instr += special; + return true; } diff --git a/src/afl-cc.c b/src/afl-cc.c index b5dcb632..f513764a 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -572,7 +572,8 @@ static void edit_params(u32 argc, char **argv, char **envp) { cc_params[cc_par_cnt++] = "-Wl,--allow-multiple-definition"; - if (instrument_mode == INSTRUMENT_CFG) + if (instrument_mode == INSTRUMENT_CFG || + instrument_mode == INSTRUMENT_PCGUARD) cc_params[cc_par_cnt++] = alloc_printf( "-Wl,-mllvm=-load=%s/SanitizerCoverageLTO.so", obj_path); else @@ -1670,15 +1671,16 @@ int main(int argc, char **argv, char **envp) { if (compiler_mode == LTO) { if (instrument_mode == 0 || instrument_mode == INSTRUMENT_LTO || - instrument_mode == INSTRUMENT_CFG) { + instrument_mode == INSTRUMENT_CFG || + instrument_mode == INSTRUMENT_PCGUARD) { lto_mode = 1; - if (!instrument_mode) { + // force CFG + // if (!instrument_mode) { - instrument_mode = INSTRUMENT_CFG; - // ptr = instrument_mode_string[instrument_mode]; - - } + instrument_mode = INSTRUMENT_PCGUARD; + // ptr = instrument_mode_string[instrument_mode]; + // } } else if (instrument_mode == INSTRUMENT_LTO || diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 647a665e..82eff61f 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -145,7 +145,8 @@ static void usage(u8 *argv0, int more_help) { "Other stuff:\n" " -M/-S id - distributed mode (see docs/parallel_fuzzing.md)\n" - " -M auto-sets -D, -Z (use -d to disable -D) and no trimming\n" + " -M auto-sets -D, -Z (use -d to disable -D) and no " + "trimming\n" " -F path - sync to a foreign fuzzer queue directory (requires " "-M, can\n" " be specified up to %u times)\n" @@ -502,7 +503,7 @@ int main(int argc, char **argv_orig, char **envp) { afl->sync_id = ck_strdup(optarg); afl->skip_deterministic = 0; // force deterministic fuzzing afl->old_seed_selection = 1; // force old queue walking seed selection - afl->disable_trim = 1; // disable trimming + afl->disable_trim = 1; // disable trimming if ((c = strchr(afl->sync_id, ':'))) { -- cgit 1.4.1 From cc0210426a5a31d56d8a0e850dcc00d90833afcd Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sun, 31 Jan 2021 17:32:24 +0100 Subject: code-format --- docs/Changelog.md | 1 + include/xxhash.h | 2 +- instrumentation/compare-transform-pass.so.cc | 2 +- src/afl-fuzz.c | 3 +++ utils/afl_untracer/afl-untracer.c | 2 +- utils/libtokencap/libtokencap.so.c | 10 +++++----- utils/persistent_mode/persistent_demo_new.c | 2 +- utils/persistent_mode/test-instr.c | 2 +- 8 files changed, 14 insertions(+), 10 deletions(-) (limited to 'docs/Changelog.md') diff --git a/docs/Changelog.md b/docs/Changelog.md index 99bc8b47..ff69c949 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -27,6 +27,7 @@ sending a mail to . - if determinstic mode is active (-D, or -M without -d) then we sync after every queue entry as this can take very long time otherwise - better detection if a target needs a large shared map + - fix for -Z - switched to an even faster RNG - added hghwng's patch for faster trace map analysis - afl-cc diff --git a/include/xxhash.h b/include/xxhash.h index 3bd56d13..006d3f3d 100644 --- a/include/xxhash.h +++ b/include/xxhash.h @@ -287,7 +287,7 @@ typedef uint32_t XXH32_hash_t; #else #include #if UINT_MAX == 0xFFFFFFFFUL -typedef unsigned int XXH32_hash_t; +typedef unsigned int XXH32_hash_t; #else #if ULONG_MAX == 0xFFFFFFFFUL typedef unsigned long XXH32_hash_t; diff --git a/instrumentation/compare-transform-pass.so.cc b/instrumentation/compare-transform-pass.so.cc index 932540a7..da5cf7e9 100644 --- a/instrumentation/compare-transform-pass.so.cc +++ b/instrumentation/compare-transform-pass.so.cc @@ -68,7 +68,7 @@ class CompareTransform : public ModulePass { const char *getPassName() const override { #else - StringRef getPassName() const override { + StringRef getPassName() const override { #endif return "transforms compare functions"; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 276074a4..f1f92717 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1632,8 +1632,11 @@ int main(int argc, char **argv_orig, char **envp) { afl->current_entry = 0; while (unlikely(afl->queue_buf[afl->current_entry]->disabled)) { + ++afl->current_entry; + } + afl->queue_cur = afl->queue_buf[afl->current_entry]; if (unlikely(seek_to)) { diff --git a/utils/afl_untracer/afl-untracer.c b/utils/afl_untracer/afl-untracer.c index d2bad0b9..f3894a06 100644 --- a/utils/afl_untracer/afl-untracer.c +++ b/utils/afl_untracer/afl-untracer.c @@ -284,7 +284,7 @@ library_list_t *find_library(char *name) { // this seems to work for clang too. nice :) requires gcc 4.4+ #pragma GCC push_options #pragma GCC optimize("O0") -void breakpoint(void) { +void breakpoint(void) { if (debug) fprintf(stderr, "Breakpoint function \"breakpoint\" reached.\n"); diff --git a/utils/libtokencap/libtokencap.so.c b/utils/libtokencap/libtokencap.so.c index 26033b46..3629e804 100644 --- a/utils/libtokencap/libtokencap.so.c +++ b/utils/libtokencap/libtokencap.so.c @@ -161,8 +161,8 @@ static void __tokencap_load_mappings(void) { #elif defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__ - #if defined __FreeBSD__ - int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, __tokencap_pid}; + #if defined __FreeBSD__ + int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, __tokencap_pid}; #elif defined __OpenBSD__ int mib[] = {CTL_KERN, KERN_PROC_VMMAP, __tokencap_pid}; #elif defined __NetBSD__ @@ -177,7 +177,7 @@ static void __tokencap_load_mappings(void) { #if defined __FreeBSD__ || defined __NetBSD__ len = len * 4 / 3; - #elif defined __OpenBSD__ + #elif defined __OpenBSD__ len -= len % sizeof(struct kinfo_vmentry); #endif @@ -202,8 +202,8 @@ static void __tokencap_load_mappings(void) { #if defined __FreeBSD__ || defined __NetBSD__ - #if defined __FreeBSD__ - size_t size = region->kve_structsize; + #if defined __FreeBSD__ + size_t size = region->kve_structsize; if (size == 0) break; #elif defined __NetBSD__ diff --git a/utils/persistent_mode/persistent_demo_new.c b/utils/persistent_mode/persistent_demo_new.c index ca616236..7e694696 100644 --- a/utils/persistent_mode/persistent_demo_new.c +++ b/utils/persistent_mode/persistent_demo_new.c @@ -51,7 +51,7 @@ __AFL_FUZZ_INIT(); /* To ensure checks are not optimized out it is recommended to disable code optimization for the fuzzer harness main() */ #pragma clang optimize off -#pragma GCC optimize("O0") +#pragma GCC optimize("O0") int main(int argc, char **argv) { diff --git a/utils/persistent_mode/test-instr.c b/utils/persistent_mode/test-instr.c index 2c6b6d77..6da511de 100644 --- a/utils/persistent_mode/test-instr.c +++ b/utils/persistent_mode/test-instr.c @@ -24,7 +24,7 @@ __AFL_FUZZ_INIT(); /* To ensure checks are not optimized out it is recommended to disable code optimization for the fuzzer harness main() */ #pragma clang optimize off -#pragma GCC optimize("O0") +#pragma GCC optimize("O0") int main(int argc, char **argv) { -- cgit 1.4.1 From 981ffb27a8a166b51a06d57fce044ed1eaf1aa62 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Mon, 1 Feb 2021 12:01:23 +0100 Subject: making AFL_MAP_SIZE obsolete --- afl-cmin | 4 +-- docs/Changelog.md | 2 ++ include/forkserver.h | 3 ++ include/sharedmem.h | 1 + src/afl-forkserver.c | 28 ++++++++++++++----- src/afl-fuzz-init.c | 14 ++++++---- src/afl-fuzz.c | 73 +++++++++++++++++++++++++++++++++++++++++++------ src/afl-sharedmem.c | 14 ++++++++-- src/afl-showmap.c | 41 +++++++++++++++++++++++++-- src/afl-tmin.c | 37 +++++++++++++++++++++++-- test-instr.c | 5 +++- test/test-basic.sh | 12 ++++---- test/test-gcc-plugin.sh | 10 +++---- test/test-llvm-lto.sh | 8 +++--- test/test-llvm.sh | 10 +++---- 15 files changed, 211 insertions(+), 51 deletions(-) (limited to 'docs/Changelog.md') diff --git a/afl-cmin b/afl-cmin index ffefaead..31d7ddad 100755 --- a/afl-cmin +++ b/afl-cmin @@ -343,7 +343,7 @@ BEGIN { stat_format = "-f '%z %N'" # *BSD, MacOS } cmdline = "cd "in_dir" && find . \\( ! -name . -a -type d -prune \\) -o -type f -exec stat "stat_format" \\{\\} \\; | sort -k1n -k2r" - cmdline = "ls "in_dir" | (cd "in_dir" && xargs stat "stat_format") | sort -k1n -k2r" + cmdline = "ls "in_dir" | (cd "in_dir" && xargs stat "stat_format" 2>/dev/null) | sort -k1n -k2r" while (cmdline | getline) { sub(/^[0-9]+ (\.\/)?/,"",$0) infilesSmallToBig[i++] = $0 @@ -355,7 +355,7 @@ BEGIN { # Make sure that we're not dealing with a directory. if (0 == system("test -d "in_dir"/"first_file)) { - print "[-] Error: The input directory contains subdirectories - please fix." > "/dev/stderr" + print "[-] Error: The input directory is empty or contains subdirectories - please fix." > "/dev/stderr" exit 1 } diff --git a/docs/Changelog.md b/docs/Changelog.md index ff69c949..e9efdf38 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -16,6 +16,8 @@ sending a mail to . to be placed in the source code. Check out instrumentation/README.instrument_list.md - afl-fuzz + - Making AFL_MAP_SIZE obsolete - afl-fuzz now learns on start the + target map size - upgraded cmplog/redqueen: solving for floating point, solving transformations (e.g. toupper, tolower, to/from hex, xor, arithmetics, etc.). this is costly hence new command line option diff --git a/include/forkserver.h b/include/forkserver.h index d2fcaa20..ac027f81 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -120,11 +120,14 @@ void afl_fsrv_init(afl_forkserver_t *fsrv); void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from); void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, volatile u8 *stop_soon_p, u8 debug_child_output); +u32 afl_fsrv_get_mapsize(afl_forkserver_t *fsrv, char **argv, + volatile u8 *stop_soon_p, u8 debug_child_output); void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len); fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, volatile u8 *stop_soon_p); void afl_fsrv_killall(void); void afl_fsrv_deinit(afl_forkserver_t *fsrv); +void afl_fsrv_kill(afl_forkserver_t *fsrv); #ifdef __APPLE__ #define MSG_FORK_ON_APPLE \ diff --git a/include/sharedmem.h b/include/sharedmem.h index b15d0535..fdc947f9 100644 --- a/include/sharedmem.h +++ b/include/sharedmem.h @@ -51,6 +51,7 @@ typedef struct sharedmem { size_t map_size; /* actual allocated size */ int cmplog_mode; + int shmemfuzz_mode; struct cmp_map *cmp_map; } sharedmem_t; diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index e59f0d11..9ee59822 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -682,11 +682,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if ((status & FS_OPT_AUTODICT) == FS_OPT_AUTODICT) { - if (ignore_autodict) { - - if (!be_quiet) { WARNF("Ignoring offered AUTODICT feature."); } - - } else { + if (!ignore_autodict) { if (fsrv->add_extra_func == NULL || fsrv->afl_ptr == NULL) { @@ -969,7 +965,9 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } -static void afl_fsrv_kill(afl_forkserver_t *fsrv) { +/* Stop the forkserver and child */ + +void afl_fsrv_kill(afl_forkserver_t *fsrv) { if (fsrv->child_pid > 0) { kill(fsrv->child_pid, fsrv->kill_signal); } if (fsrv->fsrv_pid > 0) { @@ -979,13 +977,28 @@ static void afl_fsrv_kill(afl_forkserver_t *fsrv) { } + close(fsrv->fsrv_ctl_fd); + close(fsrv->fsrv_st_fd); + fsrv->fsrv_pid = -1; + fsrv->child_pid = -1; + +} + +/* Get the map size from the target forkserver */ + +u32 afl_fsrv_get_mapsize(afl_forkserver_t *fsrv, char **argv, + volatile u8 *stop_soon_p, u8 debug_child_output) { + + afl_fsrv_start(fsrv, argv, stop_soon_p, debug_child_output); + return fsrv->map_size; + } /* Delete the current testcase and write the buf to the testcase file */ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) { - if (fsrv->shmem_fuzz) { + if (likely(fsrv->use_shmem_fuzz && fsrv->shmem_fuzz)) { if (unlikely(len > MAX_FILE)) len = MAX_FILE; @@ -1042,6 +1055,7 @@ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) { } + // fprintf(stderr, "WRITE %d %u\n", fd, len); ck_write(fd, buf, len, fsrv->out_file); if (fsrv->use_stdin) { diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 56dae48c..40ba20c7 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -766,13 +766,16 @@ void read_testcases(afl_state_t *afl, u8 *directory) { } - if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) { + /* + if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) { - u64 cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); - afl->queue_top->n_fuzz_entry = cksum % N_FUZZ_SIZE; - afl->n_fuzz[afl->queue_top->n_fuzz_entry] = 1; + u64 cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, + HASH_CONST); afl->queue_top->n_fuzz_entry = cksum % N_FUZZ_SIZE; + afl->n_fuzz[afl->queue_top->n_fuzz_entry] = 1; - } + } + + */ } @@ -2490,6 +2493,7 @@ void setup_testcase_shmem(afl_state_t *afl) { // we need to set the non-instrumented mode to not overwrite the SHM_ENV_VAR u8 *map = afl_shm_init(afl->shm_fuzz, MAX_FILE + sizeof(u32), 1); + afl->shm_fuzz->shmemfuzz_mode = 1; if (!map) { FATAL("BUG: Zero return from afl_shm_init."); } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index f1f92717..49733594 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -342,7 +342,6 @@ int main(int argc, char **argv_orig, char **envp) { afl->debug = debug; afl_fsrv_init(&afl->fsrv); if (debug) { afl->fsrv.debug = true; } - read_afl_environment(afl, envp); if (afl->shm.map_size) { afl->fsrv.map_size = afl->shm.map_size; } exit_1 = !!afl->afl_env.afl_bench_just_one; @@ -702,7 +701,6 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->in_bitmap) { FATAL("Multiple -B options not supported"); } afl->in_bitmap = optarg; - read_bitmap(afl->in_bitmap, afl->virgin_bits, afl->fsrv.map_size); break; case 'C': /* crash mode */ @@ -1369,13 +1367,6 @@ int main(int argc, char **argv_orig, char **envp) { set_scheduler_mode(SCHEDULER_MODE_LOW_LATENCY); #endif - afl->fsrv.trace_bits = - afl_shm_init(&afl->shm, afl->fsrv.map_size, afl->non_instrumented_mode); - - if (!afl->in_bitmap) { memset(afl->virgin_bits, 255, afl->fsrv.map_size); } - memset(afl->virgin_tmout, 255, afl->fsrv.map_size); - memset(afl->virgin_crash, 255, afl->fsrv.map_size); - init_count_class16(); if (afl->is_main_node && check_main_node_exists(afl) == 1) { @@ -1542,6 +1533,70 @@ int main(int argc, char **argv_orig, char **envp) { } afl->argv = use_argv; + afl->fsrv.trace_bits = + afl_shm_init(&afl->shm, afl->fsrv.map_size, afl->non_instrumented_mode); + + if (!afl->non_instrumented_mode) { + + afl->fsrv.map_size = 4194304; // dummy temporary value + + u32 new_map_size = afl_fsrv_get_mapsize( + &afl->fsrv, afl->argv, &afl->stop_soon, afl->afl_env.afl_debug_child); + + if (new_map_size && new_map_size != 4194304) { + + // only reinitialize when it makes sense + if (map_size != new_map_size) { + + // if (map_size < new_map_size || + // (new_map_size > map_size && new_map_size - map_size > + // MAP_SIZE)) { + + OKF("Re-initializing maps to %u bytes", new_map_size); + + afl->virgin_bits = ck_realloc(afl->virgin_bits, map_size); + afl->virgin_tmout = ck_realloc(afl->virgin_tmout, map_size); + afl->virgin_crash = ck_realloc(afl->virgin_crash, map_size); + afl->var_bytes = ck_realloc(afl->var_bytes, map_size); + afl->top_rated = ck_realloc(afl->top_rated, map_size * sizeof(void *)); + afl->clean_trace = ck_realloc(afl->clean_trace, map_size); + afl->clean_trace_custom = ck_realloc(afl->clean_trace_custom, map_size); + afl->first_trace = ck_realloc(afl->first_trace, map_size); + afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, map_size); + + afl_shm_deinit(&afl->shm); + afl_fsrv_kill(&afl->fsrv); + afl->fsrv.map_size = new_map_size; + afl->fsrv.trace_bits = afl_shm_init(&afl->shm, afl->fsrv.map_size, + afl->non_instrumented_mode); + setenv("AFL_NO_AUTODICT", "1", 1); // loaded already + afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon, + afl->afl_env.afl_debug_child); + + } + + map_size = new_map_size; + + } + + afl->fsrv.map_size = map_size; + + } + + // after we have the correct bitmap size we can read the bitmap -B option + // and set the virgin maps + if (!afl->in_bitmap) { + + memset(afl->virgin_bits, 255, afl->fsrv.map_size); + + } else { + + read_bitmap(afl->in_bitmap, afl->virgin_bits, afl->fsrv.map_size); + + } + + memset(afl->virgin_tmout, 255, afl->fsrv.map_size); + memset(afl->virgin_crash, 255, afl->fsrv.map_size); if (afl->cmplog_binary) { diff --git a/src/afl-sharedmem.c b/src/afl-sharedmem.c index fe641d0d..3241a130 100644 --- a/src/afl-sharedmem.c +++ b/src/afl-sharedmem.c @@ -66,9 +66,17 @@ static list_t shm_list = {.element_prealloc_count = 0}; void afl_shm_deinit(sharedmem_t *shm) { - if (shm == NULL) return; - + if (shm == NULL) { return; } list_remove(&shm_list, shm); + if (shm->shmemfuzz_mode) { + + unsetenv(SHM_FUZZ_ENV_VAR); + + } else { + + unsetenv(SHM_ENV_VAR); + + } #ifdef USEMMAP if (shm->map != NULL) { @@ -94,6 +102,8 @@ void afl_shm_deinit(sharedmem_t *shm) { if (shm->cmplog_mode) { + unsetenv(CMPLOG_SHM_ENV_VAR); + if (shm->cmp_map != NULL) { munmap(shm->cmp_map, shm->map_size); diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 62bf1021..56abe4f1 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -86,7 +86,8 @@ static u8 quiet_mode, /* Hide non-essential messages? */ remove_shm = 1, /* remove shmem? */ collect_coverage, /* collect coverage */ have_coverage, /* have coverage? */ - no_classify; /* do not classify counts */ + no_classify, /* do not classify counts */ + debug; /* debug mode */ static volatile u8 stop_soon, /* Ctrl-C pressed? */ child_crashed; /* Child crashed? */ @@ -743,6 +744,7 @@ int main(int argc, char **argv_orig, char **envp) { char **argv = argv_cpy_dup(argc, argv_orig); afl_forkserver_t fsrv_var = {0}; + if (getenv("AFL_DEBUG")) { debug = 1; } fsrv = &fsrv_var; afl_fsrv_init(fsrv); map_size = get_map_size(); @@ -991,14 +993,16 @@ int main(int argc, char **argv_orig, char **envp) { // if (afl->shmem_testcase_mode) { setup_testcase_shmem(afl); } + setenv("AFL_NO_AUTODICT", "1", 1); + /* initialize cmplog_mode */ shm.cmplog_mode = 0; - fsrv->trace_bits = afl_shm_init(&shm, map_size, 0); setup_signal_handlers(); set_up_environment(fsrv); fsrv->target_path = find_binary(argv[optind]); + fsrv->trace_bits = afl_shm_init(&shm, map_size, 0); if (!quiet_mode) { @@ -1051,6 +1055,7 @@ int main(int argc, char **argv_orig, char **envp) { /* initialize cmplog_mode */ shm_fuzz->cmplog_mode = 0; u8 *map = afl_shm_init(shm_fuzz, MAX_FILE + sizeof(u32), 1); + shm_fuzz->shmemfuzz_mode = 1; if (!map) { FATAL("BUG: Zero return from afl_shm_init."); } #ifdef USEMMAP setenv(SHM_FUZZ_ENV_VAR, shm_fuzz->g_shm_file_path, 1); @@ -1063,6 +1068,38 @@ int main(int argc, char **argv_orig, char **envp) { fsrv->shmem_fuzz_len = (u32 *)map; fsrv->shmem_fuzz = map + sizeof(u32); + u32 save_be_quiet = be_quiet; + be_quiet = debug; + fsrv->map_size = 4194304; // dummy temporary value + u32 new_map_size = afl_fsrv_get_mapsize( + fsrv, use_argv, &stop_soon, + (get_afl_env("AFL_DEBUG_CHILD") || get_afl_env("AFL_DEBUG_CHILD_OUTPUT")) + ? 1 + : 0); + be_quiet = save_be_quiet; + + if (new_map_size) { + + // only reinitialize when it makes sense + if (map_size < new_map_size || + (new_map_size > map_size && new_map_size - map_size > MAP_SIZE)) { + + if (!be_quiet) + ACTF("Aquired new map size for target: %u bytes\n", new_map_size); + + afl_shm_deinit(&shm); + afl_fsrv_kill(fsrv); + fsrv->map_size = new_map_size; + fsrv->trace_bits = afl_shm_init(&shm, new_map_size, 0); + + } + + map_size = new_map_size; + + } + + fsrv->map_size = map_size; + if (in_dir) { DIR * dir_in, *dir_out = NULL; diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 09b5211d..799a4b87 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -79,7 +79,8 @@ static u8 crash_mode, /* Crash-centric mode? */ edges_only, /* Ignore hit counts? */ exact_mode, /* Require path match for crashes? */ remove_out_file, /* remove out_file on exit? */ - remove_shm = 1; /* remove shmem on exit? */ + remove_shm = 1, /* remove shmem on exit? */ + debug; /* debug mode */ static volatile u8 stop_soon; /* Ctrl-C pressed? */ @@ -878,6 +879,7 @@ int main(int argc, char **argv_orig, char **envp) { char **argv = argv_cpy_dup(argc, argv_orig); afl_forkserver_t fsrv_var = {0}; + if (getenv("AFL_DEBUG")) { debug = 1; } fsrv = &fsrv_var; afl_fsrv_init(fsrv); map_size = get_map_size(); @@ -1074,6 +1076,7 @@ int main(int argc, char **argv_orig, char **envp) { if (optind == argc || !in_file || !output_file) { usage(argv[0]); } check_environment_vars(envp); + setenv("AFL_NO_AUTODICT", "1", 1); if (fsrv->qemu_mode && getenv("AFL_USE_QASAN")) { @@ -1102,7 +1105,6 @@ int main(int argc, char **argv_orig, char **envp) { /* initialize cmplog_mode */ shm.cmplog_mode = 0; - fsrv->trace_bits = afl_shm_init(&shm, map_size, 0); atexit(at_exit_handler); setup_signal_handlers(); @@ -1110,6 +1112,7 @@ int main(int argc, char **argv_orig, char **envp) { set_up_environment(fsrv); fsrv->target_path = find_binary(argv[optind]); + fsrv->trace_bits = afl_shm_init(&shm, map_size, 0); detect_file_args(argv + optind, out_file, &fsrv->use_stdin); if (fsrv->qemu_mode) { @@ -1181,6 +1184,7 @@ int main(int argc, char **argv_orig, char **envp) { /* initialize cmplog_mode */ shm_fuzz->cmplog_mode = 0; u8 *map = afl_shm_init(shm_fuzz, MAX_FILE + sizeof(u32), 1); + shm_fuzz->shmemfuzz_mode = 1; if (!map) { FATAL("BUG: Zero return from afl_shm_init."); } #ifdef USEMMAP setenv(SHM_FUZZ_ENV_VAR, shm_fuzz->g_shm_file_path, 1); @@ -1195,12 +1199,39 @@ int main(int argc, char **argv_orig, char **envp) { read_initial_file(); - afl_fsrv_start( + fsrv->map_size = 4194304; // dummy temporary value + u32 new_map_size = afl_fsrv_get_mapsize( fsrv, use_argv, &stop_soon, (get_afl_env("AFL_DEBUG_CHILD") || get_afl_env("AFL_DEBUG_CHILD_OUTPUT")) ? 1 : 0); + if (new_map_size) { + + if (map_size < new_map_size || + (new_map_size > map_size && new_map_size - map_size > MAP_SIZE)) { + + if (!be_quiet) + ACTF("Aquired new map size for target: %u bytes\n", new_map_size); + + afl_shm_deinit(&shm); + afl_fsrv_kill(fsrv); + fsrv->map_size = new_map_size; + fsrv->trace_bits = afl_shm_init(&shm, new_map_size, 0); + afl_fsrv_start(fsrv, use_argv, &stop_soon, + (get_afl_env("AFL_DEBUG_CHILD") || + get_afl_env("AFL_DEBUG_CHILD_OUTPUT")) + ? 1 + : 0); + + } + + map_size = new_map_size; + + } + + fsrv->map_size = map_size; + if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz) shm_fuzz = deinit_shmem(fsrv, shm_fuzz); diff --git a/test-instr.c b/test-instr.c index 84ac0036..00799103 100644 --- a/test-instr.c +++ b/test-instr.c @@ -32,7 +32,8 @@ int main(int argc, char **argv) { } else { - if (argc >= 3 && strcmp(argv[1], "-f") == 0) + if (argc >= 3 && strcmp(argv[1], "-f") == 0) { + if ((fd = open(argv[2], O_RDONLY)) < 0) { fprintf(stderr, "Error: unable to open %s\n", argv[2]); @@ -40,6 +41,8 @@ int main(int argc, char **argv) { } + } + if (read(fd, buf, sizeof(buf)) < 1) { printf("Hum?\n"); diff --git a/test/test-basic.sh b/test/test-basic.sh index fcac8ca3..132610c0 100755 --- a/test/test-basic.sh +++ b/test/test-basic.sh @@ -11,8 +11,8 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc AFL_HARDEN=1 ../${AFL_GCC} -o test-compcov.harden test-compcov.c > /dev/null 2>&1 test -e test-instr.plain && { $ECHO "$GREEN[+] ${AFL_GCC} compilation succeeded" - echo 0 | ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.0 -r -- ./test-instr.plain > /dev/null 2>&1 - ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.1 -r -- ./test-instr.plain < /dev/null > /dev/null 2>&1 + echo 0 | AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.0 -r -- ./test-instr.plain > /dev/null 2>&1 + AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.1 -r -- ./test-instr.plain < /dev/null > /dev/null 2>&1 test -e test-instr.plain.0 -a -e test-instr.plain.1 && { diff test-instr.plain.0 test-instr.plain.1 > /dev/null 2>&1 && { $ECHO "$RED[!] ${AFL_GCC} instrumentation should be different on different input but is not" @@ -26,7 +26,7 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc } rm -f test-instr.plain.0 test-instr.plain.1 SKIP= - TUPLES=`echo 1|../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain 2>&1 | grep Captur | awk '{print$3}'` + TUPLES=`echo 1|AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain 2>&1 | grep Captur | awk '{print$3}'` test "$TUPLES" -gt 1 -a "$TUPLES" -lt 12 && { $ECHO "$GREEN[+] ${AFL_GCC} run reported $TUPLES instrumented locations which is fine" } || { @@ -132,8 +132,8 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc AFL_HARDEN=1 ../${AFL_GCC} -o test-compcov.harden test-compcov.c > /dev/null 2>&1 test -e test-instr.plain && { $ECHO "$GREEN[+] ${AFL_GCC} compilation succeeded" - echo 0 | ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.0 -r -- ./test-instr.plain > /dev/null 2>&1 - ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.1 -r -- ./test-instr.plain < /dev/null > /dev/null 2>&1 + echo 0 | AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.0 -r -- ./test-instr.plain > /dev/null 2>&1 + AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.1 -r -- ./test-instr.plain < /dev/null > /dev/null 2>&1 test -e test-instr.plain.0 -a -e test-instr.plain.1 && { diff test-instr.plain.0 test-instr.plain.1 > /dev/null 2>&1 && { $ECHO "$RED[!] ${AFL_GCC} instrumentation should be different on different input but is not" @@ -146,7 +146,7 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc CODE=1 } rm -f test-instr.plain.0 test-instr.plain.1 - TUPLES=`echo 1|../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain 2>&1 | grep Captur | awk '{print$3}'` + TUPLES=`echo 1|AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain 2>&1 | grep Captur | awk '{print$3}'` test "$TUPLES" -gt 1 -a "$TUPLES" -lt 12 && { $ECHO "$GREEN[+] ${AFL_GCC} run reported $TUPLES instrumented locations which is fine" } || { diff --git a/test/test-gcc-plugin.sh b/test/test-gcc-plugin.sh index cce6336b..4c36b6c9 100755 --- a/test/test-gcc-plugin.sh +++ b/test/test-gcc-plugin.sh @@ -10,15 +10,15 @@ test -e ../afl-gcc-fast -a -e ../afl-compiler-rt.o && { AFL_HARDEN=1 ../afl-gcc-fast -o test-compcov.harden.gccpi test-compcov.c > /dev/null 2>&1 test -e test-instr.plain.gccpi && { $ECHO "$GREEN[+] gcc_plugin compilation succeeded" - echo 0 | ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.0 -r -- ./test-instr.plain.gccpi > /dev/null 2>&1 - ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.1 -r -- ./test-instr.plain.gccpi < /dev/null > /dev/null 2>&1 + echo 0 | AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.0 -r -- ./test-instr.plain.gccpi > /dev/null 2>&1 + AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.1 -r -- ./test-instr.plain.gccpi < /dev/null > /dev/null 2>&1 test -e test-instr.plain.0 -a -e test-instr.plain.1 && { diff test-instr.plain.0 test-instr.plain.1 > /dev/null 2>&1 && { $ECHO "$RED[!] gcc_plugin instrumentation should be different on different input but is not" CODE=1 } || { $ECHO "$GREEN[+] gcc_plugin instrumentation present and working correctly" - TUPLES=`echo 0|../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain.gccpi 2>&1 | grep Captur | awk '{print$3}'` + TUPLES=`echo 0|AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain.gccpi 2>&1 | grep Captur | awk '{print$3}'` test "$TUPLES" -gt 1 -a "$TUPLES" -lt 9 && { $ECHO "$GREEN[+] gcc_plugin run reported $TUPLES instrumented locations which is fine" } || { @@ -87,7 +87,7 @@ test -e ../afl-gcc-fast -a -e ../afl-compiler-rt.o && { echo foobar.c > instrumentlist.txt AFL_GCC_INSTRUMENT_FILE=instrumentlist.txt ../afl-gcc-fast -o test-compcov test-compcov.c > /dev/null 2>&1 test -x test-compcov && test_compcov_binary_functionality ./test-compcov && { - echo 1 | ../afl-showmap -m ${MEM_LIMIT} -o - -r -- ./test-compcov 2>&1 | grep -q "Captured 0 tuples" && { + echo 1 | AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o - -r -- ./test-compcov 2>&1 | grep -q "Captured 0 tuples" && { $ECHO "$GREEN[+] gcc_plugin instrumentlist feature works correctly" } || { $ECHO "$RED[!] gcc_plugin instrumentlist feature failed" @@ -100,7 +100,7 @@ test -e ../afl-gcc-fast -a -e ../afl-compiler-rt.o && { rm -f test-compcov test.out instrumentlist.txt ../afl-gcc-fast -o test-persistent ../utils/persistent_mode/persistent_demo.c > /dev/null 2>&1 test -e test-persistent && { - echo foo | ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -q -r ./test-persistent && { + echo foo | AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -q -r ./test-persistent && { $ECHO "$GREEN[+] gcc_plugin persistent mode feature works correctly" } || { $ECHO "$RED[!] gcc_plugin persistent mode feature failed to work" diff --git a/test/test-llvm-lto.sh b/test/test-llvm-lto.sh index a931afb7..3e762acf 100755 --- a/test/test-llvm-lto.sh +++ b/test/test-llvm-lto.sh @@ -16,15 +16,15 @@ test -e ../afl-clang-lto -a -e ../afl-llvm-lto-instrumentation.so && { ../afl-clang-lto -o test-instr.plain ../test-instr.c > /dev/null 2>&1 test -e test-instr.plain && { $ECHO "$GREEN[+] llvm_mode LTO compilation succeeded" - echo 0 | ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.0 -r -- ./test-instr.plain > /dev/null 2>&1 - ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.1 -r -- ./test-instr.plain < /dev/null > /dev/null 2>&1 + echo 0 | AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.0 -r -- ./test-instr.plain > /dev/null 2>&1 + AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.1 -r -- ./test-instr.plain < /dev/null > /dev/null 2>&1 test -e test-instr.plain.0 -a -e test-instr.plain.1 && { diff -q test-instr.plain.0 test-instr.plain.1 > /dev/null 2>&1 && { $ECHO "$RED[!] llvm_mode LTO instrumentation should be different on different input but is not" CODE=1 } || { $ECHO "$GREEN[+] llvm_mode LTO instrumentation present and working correctly" - TUPLES=`echo 0|../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain 2>&1 | grep Captur | awk '{print$3}'` + TUPLES=`echo 0|AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain 2>&1 | grep Captur | awk '{print$3}'` test "$TUPLES" -gt 2 -a "$TUPLES" -lt 7 && { $ECHO "$GREEN[+] llvm_mode LTO run reported $TUPLES instrumented locations which is fine" } || { @@ -59,7 +59,7 @@ test -e ../afl-clang-lto -a -e ../afl-llvm-lto-instrumentation.so && { rm -f test-compcov test.out instrumentlist.txt ../afl-clang-lto -o test-persistent ../utils/persistent_mode/persistent_demo.c > /dev/null 2>&1 test -e test-persistent && { - echo foo | ../afl-showmap -m none -o /dev/null -q -r ./test-persistent && { + echo foo | AFL_QUIET=1 ../afl-showmap -m none -o /dev/null -q -r ./test-persistent && { $ECHO "$GREEN[+] llvm_mode LTO persistent mode feature works correctly" } || { $ECHO "$RED[!] llvm_mode LTO persistent mode feature failed to work" diff --git a/test/test-llvm.sh b/test/test-llvm.sh index c968d5a9..156b8920 100755 --- a/test/test-llvm.sh +++ b/test/test-llvm.sh @@ -16,15 +16,15 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { AFL_HARDEN=1 ../afl-clang-fast -o test-compcov.harden test-compcov.c > /dev/null 2>&1 test -e test-instr.plain && { $ECHO "$GREEN[+] llvm_mode compilation succeeded" - echo 0 | ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.0 -r -- ./test-instr.plain > /dev/null 2>&1 - ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.1 -r -- ./test-instr.plain < /dev/null > /dev/null 2>&1 + echo 0 | AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.0 -r -- ./test-instr.plain > /dev/null 2>&1 + AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.1 -r -- ./test-instr.plain < /dev/null > /dev/null 2>&1 test -e test-instr.plain.0 -a -e test-instr.plain.1 && { diff test-instr.plain.0 test-instr.plain.1 > /dev/null 2>&1 && { $ECHO "$RED[!] llvm_mode instrumentation should be different on different input but is not" CODE=1 } || { $ECHO "$GREEN[+] llvm_mode instrumentation present and working correctly" - TUPLES=`echo 0|../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain 2>&1 | grep Captur | awk '{print$3}'` + TUPLES=`echo 0|AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain 2>&1 | grep Captur | awk '{print$3}'` test "$TUPLES" -gt 2 -a "$TUPLES" -lt 8 && { $ECHO "$GREEN[+] llvm_mode run reported $TUPLES instrumented locations which is fine" } || { @@ -128,7 +128,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { test -e ../libLLVMInsTrim.so && { AFL_LLVM_INSTRUMENT=CFG AFL_LLVM_INSTRIM_LOOPHEAD=1 ../afl-clang-fast -o test-instr.instrim ../test-instr.c > /dev/null 2>test.out test -e test-instr.instrim && { - TUPLES=`echo 0|../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.instrim 2>&1 | grep Captur | awk '{print$3}'` + TUPLES=`echo 0|AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.instrim 2>&1 | grep Captur | awk '{print$3}'` test "$TUPLES" -gt 1 -a "$TUPLES" -lt 5 && { $ECHO "$GREEN[+] llvm_mode InsTrim reported $TUPLES instrumented locations which is fine" } || { @@ -216,7 +216,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { rm -rf errors test-cmplog in core.* ../afl-clang-fast -o test-persistent ../utils/persistent_mode/persistent_demo.c > /dev/null 2>&1 test -e test-persistent && { - echo foo | ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -q -r ./test-persistent && { + echo foo | AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -q -r ./test-persistent && { $ECHO "$GREEN[+] llvm_mode persistent mode feature works correctly" } || { $ECHO "$RED[!] llvm_mode persistent mode feature failed to work" -- cgit 1.4.1 From 209c5ba4657b641bf261da7ac9ce7d3f809109c2 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 7 Feb 2021 05:33:02 +0100 Subject: larger map, stats reload fix, code format --- docs/Changelog.md | 2 + instrumentation/afl-compiler-rt.o.c | 2 +- instrumentation/afl-llvm-lto-instrumentation.so.cc | 3 +- qemu_mode/libqasan/dlmalloc.c | 5 ++ src/afl-fuzz-bitmap.c | 3 +- src/afl-fuzz-statsd.c | 63 ++++++++++++---------- utils/afl_untracer/afl-untracer.c | 10 ++-- 7 files changed, 52 insertions(+), 36 deletions(-) (limited to 'docs/Changelog.md') diff --git a/docs/Changelog.md b/docs/Changelog.md index e9efdf38..f2041917 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -26,6 +26,8 @@ sending a mail to . `-i` or resumes (as these have most likely already been done) - fix crash for very, very fast targets+systems (thanks to mhlakhani for reporting) + - on restarts (-i)/autoresume (AFL_AUTORESUME) the stats are now + reloaded and used, thanks to Vimal Joseph for this PR! - if determinstic mode is active (-D, or -M without -d) then we sync after every queue entry as this can take very long time otherwise - better detection if a target needs a large shared map diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index 65a5d3d2..059691ec 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -70,7 +70,7 @@ run. It will end up as .comm, so it shouldn't be too wasteful. */ #if MAP_SIZE <= 65536 - #define MAP_INITIAL_SIZE 1048576 + #define MAP_INITIAL_SIZE 2097152 #else #define MAP_INITIAL_SIZE MAP_SIZE #endif diff --git a/instrumentation/afl-llvm-lto-instrumentation.so.cc b/instrumentation/afl-llvm-lto-instrumentation.so.cc index fa494f44..841d52e5 100644 --- a/instrumentation/afl-llvm-lto-instrumentation.so.cc +++ b/instrumentation/afl-llvm-lto-instrumentation.so.cc @@ -69,7 +69,8 @@ class AFLLTOPass : public ModulePass { if (getenv("AFL_DEBUG")) debug = 1; if ((ptr = getenv("AFL_LLVM_LTO_STARTID")) != NULL) - if ((afl_global_id = (uint32_t)atoi(ptr)) < 0 || afl_global_id >= MAP_SIZE) + if ((afl_global_id = (uint32_t)atoi(ptr)) < 0 || + afl_global_id >= MAP_SIZE) FATAL("AFL_LLVM_LTO_STARTID value of \"%s\" is not between 0 and %u\n", ptr, MAP_SIZE - 1); diff --git a/qemu_mode/libqasan/dlmalloc.c b/qemu_mode/libqasan/dlmalloc.c index 39ca4301..ce94451d 100644 --- a/qemu_mode/libqasan/dlmalloc.c +++ b/qemu_mode/libqasan/dlmalloc.c @@ -3907,6 +3907,7 @@ static void internal_malloc_stats(mstate m) { clear_smallmap(M, I); \ \ } else if (RTCHECK(B == smallbin_at(M, I) || \ + \ (ok_address(M, B) && B->fd == P))) { \ \ F->bk = B; \ @@ -4117,6 +4118,7 @@ static void internal_malloc_stats(mstate m) { XP->child[1] = R; \ \ } else \ + \ CORRUPTION_ERROR_ACTION(M); \ if (R != 0) { \ \ @@ -4132,6 +4134,7 @@ static void internal_malloc_stats(mstate m) { C0->parent = R; \ \ } else \ + \ CORRUPTION_ERROR_ACTION(M); \ \ } \ @@ -4143,11 +4146,13 @@ static void internal_malloc_stats(mstate m) { C1->parent = R; \ \ } else \ + \ CORRUPTION_ERROR_ACTION(M); \ \ } \ \ } else \ + \ CORRUPTION_ERROR_ACTION(M); \ \ } \ diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 0c4a114e..4ed59364 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -325,7 +325,8 @@ u8 *describe_op(afl_state_t *afl, u8 new_bits, size_t max_description_len) { } - sprintf(ret + strlen(ret), ",time:%llu", get_cur_time() - afl->start_time); + sprintf(ret + strlen(ret), ",time:%llu", + get_cur_time() + afl->prev_run_time - afl->start_time); if (afl->current_custom_fuzz && afl->current_custom_fuzz->afl_custom_describe) { diff --git a/src/afl-fuzz-statsd.c b/src/afl-fuzz-statsd.c index 69cafd90..461bbbf6 100644 --- a/src/afl-fuzz-statsd.c +++ b/src/afl-fuzz-statsd.c @@ -1,3 +1,8 @@ +/* + * This implements rpc.statsd support, see docs/rpc_statsd.md + * + */ + #include #include #include @@ -226,37 +231,39 @@ int statsd_format_metric(afl_state_t *afl, char *buff, size_t bufflen) { */ if (afl->statsd_metric_format_type == STATSD_TAGS_TYPE_SUFFIX) { - snprintf(buff, bufflen, afl->statsd_metric_format, - afl->queue_cycle ? (afl->queue_cycle - 1) : 0, tags, - afl->cycles_wo_finds, tags, afl->fsrv.total_execs, tags, - afl->fsrv.total_execs / - ((double)(get_cur_time() - afl->start_time) / 1000), - tags, afl->queued_paths, tags, afl->queued_favored, tags, - afl->queued_discovered, tags, afl->queued_imported, tags, - afl->max_depth, tags, afl->current_entry, tags, - afl->pending_favored, tags, afl->pending_not_fuzzed, tags, - afl->queued_variable, tags, afl->unique_crashes, tags, - afl->unique_hangs, tags, afl->total_crashes, tags, - afl->slowest_exec_ms, tags, - count_non_255_bytes(afl, afl->virgin_bits), tags, - afl->var_byte_count, tags, afl->expand_havoc, tags); + snprintf( + buff, bufflen, afl->statsd_metric_format, + afl->queue_cycle ? (afl->queue_cycle - 1) : 0, tags, + afl->cycles_wo_finds, tags, afl->fsrv.total_execs, tags, + afl->fsrv.total_execs / + ((double)(get_cur_time() + afl->prev_run_time - afl->start_time) / + 1000), + tags, afl->queued_paths, tags, afl->queued_favored, tags, + afl->queued_discovered, tags, afl->queued_imported, tags, + afl->max_depth, tags, afl->current_entry, tags, afl->pending_favored, + tags, afl->pending_not_fuzzed, tags, afl->queued_variable, tags, + afl->unique_crashes, tags, afl->unique_hangs, tags, afl->total_crashes, + tags, afl->slowest_exec_ms, tags, + count_non_255_bytes(afl, afl->virgin_bits), tags, afl->var_byte_count, + tags, afl->expand_havoc, tags); } else if (afl->statsd_metric_format_type == STATSD_TAGS_TYPE_MID) { - snprintf(buff, bufflen, afl->statsd_metric_format, tags, - afl->queue_cycle ? (afl->queue_cycle - 1) : 0, tags, - afl->cycles_wo_finds, tags, afl->fsrv.total_execs, tags, - afl->fsrv.total_execs / - ((double)(get_cur_time() - afl->start_time) / 1000), - tags, afl->queued_paths, tags, afl->queued_favored, tags, - afl->queued_discovered, tags, afl->queued_imported, tags, - afl->max_depth, tags, afl->current_entry, tags, - afl->pending_favored, tags, afl->pending_not_fuzzed, tags, - afl->queued_variable, tags, afl->unique_crashes, tags, - afl->unique_hangs, tags, afl->total_crashes, tags, - afl->slowest_exec_ms, tags, - count_non_255_bytes(afl, afl->virgin_bits), tags, - afl->var_byte_count, tags, afl->expand_havoc); + snprintf( + buff, bufflen, afl->statsd_metric_format, tags, + afl->queue_cycle ? (afl->queue_cycle - 1) : 0, tags, + afl->cycles_wo_finds, tags, afl->fsrv.total_execs, tags, + afl->fsrv.total_execs / + ((double)(get_cur_time() + afl->prev_run_time - afl->start_time) / + 1000), + tags, afl->queued_paths, tags, afl->queued_favored, tags, + afl->queued_discovered, tags, afl->queued_imported, tags, + afl->max_depth, tags, afl->current_entry, tags, afl->pending_favored, + tags, afl->pending_not_fuzzed, tags, afl->queued_variable, tags, + afl->unique_crashes, tags, afl->unique_hangs, tags, afl->total_crashes, + tags, afl->slowest_exec_ms, tags, + count_non_255_bytes(afl, afl->virgin_bits), tags, afl->var_byte_count, + tags, afl->expand_havoc); } diff --git a/utils/afl_untracer/afl-untracer.c b/utils/afl_untracer/afl-untracer.c index 1f1a10ea..2baeb58d 100644 --- a/utils/afl_untracer/afl-untracer.c +++ b/utils/afl_untracer/afl-untracer.c @@ -480,9 +480,9 @@ void setup_trap_instrumentation(void) { // Index into the coverage bitmap for the current trap instruction. #ifdef __aarch64__ uint64_t bitmap_index = 0; -#ifdef __APPLE__ + #ifdef __APPLE__ pthread_jit_write_protect_np(0); -#endif + #endif #else uint32_t bitmap_index = 0; #endif @@ -627,13 +627,13 @@ static void sigtrap_handler(int signum, siginfo_t *si, void *context) { // Must re-execute the instruction, so decrement PC by one instruction. ucontext_t *ctx = (ucontext_t *)context; #if defined(__APPLE__) && defined(__LP64__) -#if defined(__x86_64__) + #if defined(__x86_64__) ctx->uc_mcontext->__ss.__rip -= 1; addr = ctx->uc_mcontext->__ss.__rip; -#else + #else ctx->uc_mcontext->__ss.__pc -= 4; addr = ctx->uc_mcontext->__ss.__pc; -#endif + #endif #elif defined(__linux__) #if defined(__x86_64__) || defined(__i386__) ctx->uc_mcontext.gregs[REG_RIP] -= 1; -- cgit 1.4.1 From 5b2634f711e95b48b6105d3cac659e51706ff4e9 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 10 Feb 2021 17:56:27 +0100 Subject: update changelog + ideas --- docs/Changelog.md | 12 ++++++------ docs/ideas.md | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) (limited to 'docs/Changelog.md') diff --git a/docs/Changelog.md b/docs/Changelog.md index f2041917..56137eec 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -16,8 +16,8 @@ sending a mail to . to be placed in the source code. Check out instrumentation/README.instrument_list.md - afl-fuzz - - Making AFL_MAP_SIZE obsolete - afl-fuzz now learns on start the - target map size + - Making AFL_MAP_SIZE (mostly) obsolete - afl-fuzz now learns on start + the target map size - upgraded cmplog/redqueen: solving for floating point, solving transformations (e.g. toupper, tolower, to/from hex, xor, arithmetics, etc.). this is costly hence new command line option @@ -27,7 +27,7 @@ sending a mail to . - fix crash for very, very fast targets+systems (thanks to mhlakhani for reporting) - on restarts (-i)/autoresume (AFL_AUTORESUME) the stats are now - reloaded and used, thanks to Vimal Joseph for this PR! + reloaded and used, thanks to Vimal Joseph for this patch! - if determinstic mode is active (-D, or -M without -d) then we sync after every queue entry as this can take very long time otherwise - better detection if a target needs a large shared map @@ -47,8 +47,10 @@ sending a mail to . - added AFL_LLVM_INSTRUMENT option NATIVE for native clang pc-guard support (less performant than our own), GCC for old afl-gcc and CLANG for old afl-clang + - fixed a potential crash in the LAF feature - qemuafl - - ported QASan to qemuafl! see qemu_mode/libqasan/README.md + - QASan (address sanitizer for Qemu) ported to qemuafl! + See qemu_mode/libqasan/README.md - solved some persistent mode bugs (thanks Dil4rd) - solved an issue when dumping the memory maps (thanks wizche) - Android support for QASan @@ -58,8 +60,6 @@ sending a mail to . - Added a new example harness to compare python, c, and rust bindings - changed default: no memory limit for afl-cmin and afl-cmin.bash - warn on any _AFL and __AFL env vars - - LLVM mode is now compiled with -j4, unicorn with all cores. qemu was - already building with all cores, the gcc plugin needs only one. - added dummy Makefile to instrumentation/ - Updated utils/afl_frida to be 5% faster, 7% on x86_x64 - Added AFL_KILL_SIGNAL env variable (thanks @v-p-b) diff --git a/docs/ideas.md b/docs/ideas.md index 7cbe60a5..08cb16ef 100644 --- a/docs/ideas.md +++ b/docs/ideas.md @@ -3,6 +3,40 @@ In the following, we describe a variety of ideas that could be implemented for future AFL++ versions. +# GSoC 2021 + +All GSoC 2021 projects will be in the Rust development language! + +## UI for libaflrs + +Write a user interface to libaflrs, the upcoming backend of afl++. +This might look like the afl-fuzz UI, but you can improve on it - and should! + +## Schedulers for libaflrs + +Schedulers is a mechanism that selects items from the fuzzing corpus based +on strategy and randomness. One scheduler might focus on long paths, +another on rarity of edges disocvered, still another on a combination on +things. Some of the schedulers in afl++ have to be ported, but you are free +to come up with your own if you want to - and see how it performs. + +## Forkserver support for libaflrs + +The current libaflrs implementation fuzzes in-memory, however obviously we +want to support afl instrumented binaries as well. +Hence a forkserver support needs to be implemented - forking off the target +and talking to the target via a socketpair and the communication protocol +within. + +## More Observers for libaflrs + +An observer is measuring functionality that looks at the target being fuzzed +and documents something about it. In traditional fuzzing this is the coverage +in the target, however we want to add various more observers, e.g. stack depth, +heap usage, etc. - this is a topic for an experienced Rust developer. + +# Generic ideas and wishlist + ## Analysis software Currently analysis is done by using afl-plot, which is rather outdated. -- cgit 1.4.1 From dd3f4bb41c47025c490e7687d7bd1f04188f7bc4 Mon Sep 17 00:00:00 2001 From: hexcoder Date: Thu, 11 Feb 2021 20:05:06 +0100 Subject: typos & formatting --- docs/Changelog.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'docs/Changelog.md') diff --git a/docs/Changelog.md b/docs/Changelog.md index 56137eec..919e2aeb 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -20,18 +20,18 @@ sending a mail to . the target map size - upgraded cmplog/redqueen: solving for floating point, solving transformations (e.g. toupper, tolower, to/from hex, xor, - arithmetics, etc.). this is costly hence new command line option - -l that sets the intensity (values 1 to 3). recommended is 1 or 2. + arithmetics, etc.). This is costly hence new command line option + `-l` that sets the intensity (values 1 to 3). Recommended is 1 or 2. - added `AFL_CMPLOG_ONLY_NEW` to not use cmplog on initial testcases from `-i` or resumes (as these have most likely already been done) - fix crash for very, very fast targets+systems (thanks to mhlakhani for reporting) - - on restarts (-i)/autoresume (AFL_AUTORESUME) the stats are now + - on restarts (`-i`)/autoresume (AFL_AUTORESUME) the stats are now reloaded and used, thanks to Vimal Joseph for this patch! - - if determinstic mode is active (-D, or -M without -d) then we sync + - if deterministic mode is active (`-D`, or `-M` without `-d`) then we sync after every queue entry as this can take very long time otherwise - better detection if a target needs a large shared map - - fix for -Z + - fix for `-Z` - switched to an even faster RNG - added hghwng's patch for faster trace map analysis - afl-cc @@ -55,7 +55,7 @@ sending a mail to . - solved an issue when dumping the memory maps (thanks wizche) - Android support for QASan - unicornafl - - Substential speed gains in python bindings for certain use cases + - Substantial speed gains in python bindings for certain use cases - Improved rust bindings - Added a new example harness to compare python, c, and rust bindings - changed default: no memory limit for afl-cmin and afl-cmin.bash -- cgit 1.4.1 From 87a607c7d081dac1e4afd7c3cbe5accf62d355e4 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 13 Feb 2021 11:17:53 +0100 Subject: update doc --- docs/Changelog.md | 1 + instrumentation/SanitizerCoveragePCGUARD.so.cc | 10 +++++----- unicorn_mode/unicornafl | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'docs/Changelog.md') diff --git a/docs/Changelog.md b/docs/Changelog.md index 919e2aeb..c59a1a7a 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -48,6 +48,7 @@ sending a mail to . support (less performant than our own), GCC for old afl-gcc and CLANG for old afl-clang - fixed a potential crash in the LAF feature + - workaround for llvm 13 - qemuafl - QASan (address sanitizer for Qemu) ported to qemuafl! See qemu_mode/libqasan/README.md diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index 5d6d6703..80c8f917 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -1088,7 +1088,7 @@ void ModuleSanitizerCoverage::InjectTraceForSwitch( } - llvm::sort(Initializers.begin() + 2, Initializers.end(), + llvm::sort(drop_begin(Initializers, 2), [](const Constant *A, const Constant *B) { return cast(A)->getLimitedValue() < @@ -1136,10 +1136,10 @@ void ModuleSanitizerCoverage::InjectTraceForGep( for (auto GEP : GepTraceTargets) { IRBuilder<> IRB(GEP); - for (auto I = GEP->idx_begin(); I != GEP->idx_end(); ++I) - if (!isa(*I) && (*I)->getType()->isIntegerTy()) - IRB.CreateCall(SanCovTraceGepFunction, - {IRB.CreateIntCast(*I, IntptrTy, true)}); + for (Use &Idx : GEP->indices()) + if (!isa(Idx) && Idx->getType()->isIntegerTy()) + IRB.CreateCall(SanCovTraceGepFunction, + {IRB.CreateIntCast(Idx, IntptrTy, true)}); } diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl index 80d31ef3..fb2fc9f2 160000 --- a/unicorn_mode/unicornafl +++ b/unicorn_mode/unicornafl @@ -1 +1 @@ -Subproject commit 80d31ef367f7a1a75fc48e08e129d10f2ffa0498 +Subproject commit fb2fc9f25df32f17f6b6b859e4dbd70f9a857e0c -- cgit 1.4.1 From 6ce9230ed66dbd091001436cdab2fc1718e8e61e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 13 Feb 2021 14:24:21 +0100 Subject: afl-cmin/afl-showmap -f --- docs/Changelog.md | 1 + 1 file changed, 1 insertion(+) (limited to 'docs/Changelog.md') diff --git a/docs/Changelog.md b/docs/Changelog.md index c59a1a7a..895ab845 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -59,6 +59,7 @@ sending a mail to . - Substantial speed gains in python bindings for certain use cases - Improved rust bindings - Added a new example harness to compare python, c, and rust bindings + - afl-cmin and afl-showmap now support the -f option - changed default: no memory limit for afl-cmin and afl-cmin.bash - warn on any _AFL and __AFL env vars - added dummy Makefile to instrumentation/ -- cgit 1.4.1 From 9bd1e19d7f004b4da6a610b07e59f99d66bb7ec2 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 13 Feb 2021 22:43:56 +0100 Subject: added AFL_IGNORE_UNKNOWN_ENVS --- docs/Changelog.md | 3 ++- docs/env_variables.md | 5 ++++- include/envs.h | 1 + instrumentation/SanitizerCoveragePCGUARD.so.cc | 2 +- src/afl-cc.c | 1 + src/afl-common.c | 4 ++-- src/afl-fuzz.c | 1 + src/afl-showmap.c | 5 +++-- 8 files changed, 15 insertions(+), 7 deletions(-) (limited to 'docs/Changelog.md') diff --git a/docs/Changelog.md b/docs/Changelog.md index 895ab845..71ef4c2c 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -61,7 +61,8 @@ sending a mail to . - Added a new example harness to compare python, c, and rust bindings - afl-cmin and afl-showmap now support the -f option - changed default: no memory limit for afl-cmin and afl-cmin.bash - - warn on any _AFL and __AFL env vars + - warn on any _AFL and __AFL env vars. + - set AFL_IGNORE_UNKNOWN_ENVS to not warn on unknown AFL_... env vars. - added dummy Makefile to instrumentation/ - Updated utils/afl_frida to be 5% faster, 7% on x86_x64 - Added AFL_KILL_SIGNAL env variable (thanks @v-p-b) diff --git a/docs/env_variables.md b/docs/env_variables.md index 886669ad..f7745247 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -5,6 +5,10 @@ users or for some types of custom fuzzing setups. See [README.md](README.md) for the general instruction manual. + Note that most tools will warn on any unknown AFL environment variables. + This is for warning on typos that can happen. If you want to disable this + check then set the `AFL_IGNORE_UNKNOWN_ENVS` environment variable. + ## 1) Settings for all compilers Starting with afl++ 3.0 there is only one compiler: afl-cc @@ -18,7 +22,6 @@ To select the different instrumentation modes this can be done by `MODE` can be one of `LTO` (afl-clang-lto*), `LLVM` (afl-clang-fast*), `GCC_PLUGIN` (afl-g*-fast) or `GCC` (afl-gcc/afl-g++). - Because (with the exception of the --afl-MODE command line option) the compile-time tools do not accept afl specific command-line options, they make fairly broad use of environmental variables instead: diff --git a/include/envs.h b/include/envs.h index 210b34a6..4313e053 100644 --- a/include/envs.h +++ b/include/envs.h @@ -61,6 +61,7 @@ static char *afl_environment_variables[] = { "AFL_FORKSRV_INIT_TMOUT", "AFL_HARDEN", "AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES", + "AFL_IGNORE_UNKNOWN_ENVS", "AFL_IMPORT_FIRST", "AFL_INST_LIBS", "AFL_INST_RATIO", diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index 80c8f917..9b1351b0 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -1138,7 +1138,7 @@ void ModuleSanitizerCoverage::InjectTraceForGep( IRBuilder<> IRB(GEP); for (Use &Idx : GEP->indices()) if (!isa(Idx) && Idx->getType()->isIntegerTy()) - IRB.CreateCall(SanCovTraceGepFunction, + IRB.CreateCall(SanCovTraceGepFunction, {IRB.CreateIntCast(Idx, IntptrTy, true)}); } diff --git a/src/afl-cc.c b/src/afl-cc.c index 9d88f262..d41f79a2 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1587,6 +1587,7 @@ int main(int argc, char **argv, char **envp) { "libtokencap.so)\n" " AFL_PATH: path to instrumenting pass and runtime " "(afl-compiler-rt.*o)\n" + " AFL_IGNORE_UNKNOWN_ENVS: don't warn on unknown env vars\n" " AFL_INST_RATIO: percentage of branches to instrument\n" " AFL_QUIET: suppress verbose output\n" " AFL_HARDEN: adds code hardening to catch memory bugs\n" diff --git a/src/afl-common.c b/src/afl-common.c index 1cc7f462..589aac71 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -523,7 +523,7 @@ void check_environment_vars(char **envp) { if (be_quiet) { return; } int index = 0, issue_detected = 0; - char *env, *val; + char *env, *val, *ignore = getenv("AFL_IGNORE_UNKNOWN_ENVS"); while ((env = envp[index++]) != NULL) { if (strncmp(env, "ALF_", 4) == 0 || strncmp(env, "_ALF", 4) == 0 || @@ -582,7 +582,7 @@ void check_environment_vars(char **envp) { } - if (match == 0) { + if (match == 0 && !ignore) { WARNF("Mistyped AFL environment variable: %s", env); issue_detected = 1; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index e4139857..e0ac8840 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -198,6 +198,7 @@ static void usage(u8 *argv0, int more_help) { "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n" "AFL_HANG_TMOUT: override timeout value (in milliseconds)\n" "AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: don't warn about core dump handlers\n" + "AFL_IGNORE_UNKNOWN_ENVS: don't warn on unknown env vars\n" "AFL_IMPORT_FIRST: sync and import test cases from other fuzzer instances first\n" "AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc. (default: SIGKILL)\n" "AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n" diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 0d2c5ceb..b40527d3 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -1168,8 +1168,9 @@ int main(int argc, char **argv_orig, char **envp) { } - stdin_file = at_file ? strdup(at_file) : (char *) - alloc_printf("%s/.afl-showmap-temp-%u", use_dir, (u32)getpid()); + stdin_file = at_file ? strdup(at_file) + : (char *)alloc_printf("%s/.afl-showmap-temp-%u", + use_dir, (u32)getpid()); unlink(stdin_file); atexit(at_exit_handler); fsrv->out_file = stdin_file; -- cgit 1.4.1 From e3a5c31307f323452dc4b5288e0d19a02b596a33 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 15 Feb 2021 13:25:15 +0100 Subject: llvm bug workaround for lto extint --- docs/Changelog.md | 1 + include/envs.h | 1 + instrumentation/cmplog-instructions-pass.cc | 39 ++++++++++++++++++++++++++--- qemu_mode/libqasan/dlmalloc.c | 5 ++++ src/afl-cc.c | 2 ++ src/afl-fuzz-redqueen.c | 1 + 6 files changed, 45 insertions(+), 4 deletions(-) (limited to 'docs/Changelog.md') diff --git a/docs/Changelog.md b/docs/Changelog.md index 71ef4c2c..e2482f8f 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -49,6 +49,7 @@ sending a mail to . CLANG for old afl-clang - fixed a potential crash in the LAF feature - workaround for llvm 13 + - workaround for llvm internal lto bug that lets not bitcast from _ExtInt() - qemuafl - QASan (address sanitizer for Qemu) ported to qemuafl! See qemu_mode/libqasan/README.md diff --git a/include/envs.h b/include/envs.h index 4313e053..36667ebc 100644 --- a/include/envs.h +++ b/include/envs.h @@ -16,6 +16,7 @@ static char *afl_environment_deprecated[] = { static char *afl_environment_variables[] = { + "_AFL_LTO_COMPILE", "AFL_ALIGNED_ALLOC", "AFL_ALLOW_TMP", "AFL_ANALYZE_HEX", diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc index b5cc1882..6b071b48 100644 --- a/instrumentation/cmplog-instructions-pass.cc +++ b/instrumentation/cmplog-instructions-pass.cc @@ -113,6 +113,8 @@ bool CmpLogInstructions::hookInstrs(Module &M) { IntegerType *Int64Ty = IntegerType::getInt64Ty(C); IntegerType *Int128Ty = IntegerType::getInt128Ty(C); + char *is_lto = getenv("_AFL_LTO_COMPILE"); + #if LLVM_VERSION_MAJOR < 9 Constant * #else @@ -265,10 +267,20 @@ bool CmpLogInstructions::hookInstrs(Module &M) { unsigned int max_size = Val->getType()->getIntegerBitWidth(), cast_size; unsigned char do_cast = 0; - if (!SI->getNumCases() || max_size < 16 || max_size % 8) { + if (!SI->getNumCases() || max_size < 16) { continue; } + + if (max_size % 8) { + + if (is_lto) { + + continue; // LTO cannot bitcast from _ExtInt() :( + + } else { - // if (!be_quiet) errs() << "skip trivial switch..\n"; - continue; + max_size = (((max_size / 8) + 1) * 8); + do_cast = 1; + + } } @@ -285,6 +297,7 @@ bool CmpLogInstructions::hookInstrs(Module &M) { } + if (is_lto) { continue; } // LTO cannot bitcast _ExtInt() :( max_size = 128; do_cast = 1; @@ -301,6 +314,7 @@ bool CmpLogInstructions::hookInstrs(Module &M) { cast_size = max_size; break; default: + if (is_lto) { continue; } // LTO cannot bitcast _ExtInt() :( cast_size = 128; do_cast = 1; @@ -540,7 +554,22 @@ bool CmpLogInstructions::hookInstrs(Module &M) { } - if (!max_size || max_size % 8 || max_size < 16) { continue; } + if (!max_size || max_size < 16) { continue; } + + if (max_size % 8) { + + if (is_lto) { + + continue; // LTO cannot bitcast from _ExtInt() :( + + } else { + + max_size = (((max_size / 8) + 1) * 8); + do_cast = 1; + + } + + } if (max_size > 128) { @@ -552,6 +581,7 @@ bool CmpLogInstructions::hookInstrs(Module &M) { } + if (is_lto) { continue; } // LTO cannot bitcast from _ExtInt() :( max_size = 128; do_cast = 1; @@ -568,6 +598,7 @@ bool CmpLogInstructions::hookInstrs(Module &M) { cast_size = max_size; break; default: + if (is_lto) { continue; } // LTO cannot bitcast from _ExtInt() :( cast_size = 128; do_cast = 1; diff --git a/qemu_mode/libqasan/dlmalloc.c b/qemu_mode/libqasan/dlmalloc.c index bace0ff6..aff58ad5 100644 --- a/qemu_mode/libqasan/dlmalloc.c +++ b/qemu_mode/libqasan/dlmalloc.c @@ -3917,6 +3917,7 @@ static void internal_malloc_stats(mstate m) { \ } else if (RTCHECK(B == smallbin_at(M, I) || \ \ + \ (ok_address(M, B) && B->fd == P))) { \ \ F->bk = B; \ @@ -4128,6 +4129,7 @@ static void internal_malloc_stats(mstate m) { \ } else \ \ + \ CORRUPTION_ERROR_ACTION(M); \ if (R != 0) { \ \ @@ -4144,6 +4146,7 @@ static void internal_malloc_stats(mstate m) { \ } else \ \ + \ CORRUPTION_ERROR_ACTION(M); \ \ } \ @@ -4156,12 +4159,14 @@ static void internal_malloc_stats(mstate m) { \ } else \ \ + \ CORRUPTION_ERROR_ACTION(M); \ \ } \ \ } else \ \ + \ CORRUPTION_ERROR_ACTION(M); \ \ } \ diff --git a/src/afl-cc.c b/src/afl-cc.c index d41f79a2..959c9a6f 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1875,6 +1875,8 @@ int main(int argc, char **argv, char **envp) { edit_params(argc, argv, envp); + if (lto_mode) { setenv("_AFL_LTO_COMPILE", "1", 1); } + if (debug) { DEBUGF("cd '%s';", getthecwd()); diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 527feef5..2b01ecad 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -1533,6 +1533,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, is_n = 1; } + #endif for (i = 0; i < loggeds; ++i) { -- cgit 1.4.1