document new environment variables and code format

This commit is contained in:
van Hauser
2020-03-10 07:14:42 +01:00
parent 38d9aedb26
commit 1148a2d0d1
9 changed files with 61 additions and 24 deletions

View File

@ -25,8 +25,8 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
- llvm_mode InsTrim mode: - llvm_mode InsTrim mode:
- removed workaround for bug where paths were not instrumented and - removed workaround for bug where paths were not instrumented and
imported fix by author imported fix by author
- made skipping 1 block functions an option and is disable by default - made skipping 1 block functions an option and is disable by default,
-> TODO: document this! set AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK=1 to renable this
- qemu_mode: - qemu_mode:
- qemu_mode now uses solely the internal capstone version to fix builds - qemu_mode now uses solely the internal capstone version to fix builds
on modern Linux distributions on modern Linux distributions

View File

@ -15,7 +15,7 @@ cases beyond those available in AFL. For example, to enable structure-aware
fuzzing by using libraries that perform mutations according to a given grammar. fuzzing by using libraries that perform mutations according to a given grammar.
The custom mutator is passed to `afl-fuzz` via the `AFL_CUSTOM_MUTATOR_LIBRARY` The custom mutator is passed to `afl-fuzz` via the `AFL_CUSTOM_MUTATOR_LIBRARY`
or `AFL_PYTHON_MODULE` environment variable., and must export a fuzz function. or `AFL_PYTHON_MODULE` environment variable, and must export a fuzz function.
Please see [APIs](#2-apis) and [Usage](#3-usage) for detail. Please see [APIs](#2-apis) and [Usage](#3-usage) for detail.
The custom mutation stage is set to be the first non-deterministic stage (right before the havoc stage). The custom mutation stage is set to be the first non-deterministic stage (right before the havoc stage).

View File

@ -91,6 +91,25 @@ of the settings discussed in section #1, with the exception of:
Then there are a few specific features that are only available in llvm_mode: Then there are a few specific features that are only available in llvm_mode:
### LTO
This is a different kind way of instrumentation: first it compiles all
code in LTO (link time optimization) and then performs an edge inserting
instrumentation which is 100% collision free (collisions are a big issue
in afl and afl-like instrumentations). This is performed by using
afl-clang-lto/afl-clang-lto++ instead of afl-clang-fast, but is only
built if LLVM 9 or newer is used.
None of these options are necessary to be used and are rather for manual
use (which only ever the author of this LTO implementation will use ;-)
These are used if several seperated instrumentation are performed which
are then later combined.
- AFL_LLVM_LTO_STARTID sets the starting location ID for the instrumentation.
This defaults to 1
- AFL_LLVM_LTO_DONTWRITEID prevents that the highest location ID written
into the instrumentation is set in a global variable
### LAF-INTEL ### LAF-INTEL
This great feature will split compares to series of single byte comparisons This great feature will split compares to series of single byte comparisons
@ -126,6 +145,10 @@ Then there are a few specific features that are only available in llvm_mode:
afl-fuzz will only be able to see the path the loop took, but not how afl-fuzz will only be able to see the path the loop took, but not how
many times it was called (unless it is a complex loop). many times it was called (unless it is a complex loop).
- Setting AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK=1 will skip instrumenting
functions with a single basic block. This is useful for most C and
some C++ targets.
See llvm_mode/README.instrim.md See llvm_mode/README.instrim.md
### NOT_ZERO ### NOT_ZERO

View File

@ -14,12 +14,13 @@ const char *afl_environment_variables[] = {
"AFL_INST_LIBS", "AFL_INST_RATIO", "AFL_KEEP_TRACES", "AFL_KEEP_ASSEMBLY", "AFL_INST_LIBS", "AFL_INST_RATIO", "AFL_KEEP_TRACES", "AFL_KEEP_ASSEMBLY",
"AFL_LD_HARD_FAIL", "AFL_LD_LIMIT_MB", "AFL_LD_NO_CALLOC_OVER", "AFL_LD_HARD_FAIL", "AFL_LD_LIMIT_MB", "AFL_LD_NO_CALLOC_OVER",
"AFL_LD_PRELOAD", "AFL_LD_VERBOSE", "AFL_LLVM_CMPLOG", "AFL_LLVM_INSTRIM", "AFL_LD_PRELOAD", "AFL_LD_VERBOSE", "AFL_LLVM_CMPLOG", "AFL_LLVM_INSTRIM",
"AFL_LLVM_INSTRIM_LOOPHEAD", "AFL_LLVM_LAF_SPLIT_COMPARES", "AFL_LLVM_INSTRIM_LOOPHEAD", "AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK",
"AFL_LLVM_LAF_SPLIT_COMPARES_BITW", "AFL_LLVM_LAF_SPLIT_FLOATS", "AFL_LLVM_LAF_SPLIT_COMPARES", "AFL_LLVM_LAF_SPLIT_COMPARES_BITW",
"AFL_LLVM_LAF_SPLIT_SWITCHES", "AFL_LLVM_LAF_TRANSFORM_COMPARES", "AFL_LLVM_LAF_SPLIT_FLOATS", "AFL_LLVM_LAF_SPLIT_SWITCHES",
"AFL_LLVM_NOT_ZERO", "AFL_LLVM_WHITELIST", "AFL_NO_AFFINITY", "AFL_LLVM_LAF_TRANSFORM_COMPARES", "AFL_LLVM_NOT_ZERO",
"AFL_LLVM_LTO_STARTID", "AFL_LLVM_LTO_DONTWRITEID", "AFL_NO_ARITH", "AFL_LLVM_WHITELIST", "AFL_NO_AFFINITY", "AFL_LLVM_LTO_STARTID",
"AFL_NO_BUILTIN", "AFL_NO_CPU_RED", "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_LLVM_LTO_DONTWRITEID", "AFL_NO_ARITH", "AFL_NO_BUILTIN",
"AFL_NO_CPU_RED", "AFL_NO_FORKSRV", "AFL_NO_UI",
"AFL_NO_X86", // not really an env but we dont want to warn on it "AFL_NO_X86", // not really an env but we dont want to warn on it
"AFL_PATH", "AFL_PERFORMANCE_FILE", "AFL_PATH", "AFL_PERFORMANCE_FILE",
//"AFL_PERSISTENT", // not implemented anymore, so warn additionally //"AFL_PERSISTENT", // not implemented anymore, so warn additionally

View File

@ -388,14 +388,17 @@ struct InsTrim : public ModulePass {
} }
if (function_minimum_size < 2) { if (function_minimum_size < 2) {
for (BasicBlock &BB : F) { for (BasicBlock &BB : F) {
if (MS.find(&BB) == MS.end()) {
continue; if (MS.find(&BB) == MS.end()) { continue; }
}
IRBuilder<> IRB(&*BB.getFirstInsertionPt()); IRBuilder<> IRB(&*BB.getFirstInsertionPt());
IRB.CreateStore(ConstantInt::get(Int32Ty, genLabel()), OldPrev); IRB.CreateStore(ConstantInt::get(Int32Ty, genLabel()), OldPrev);
} }
} }
} }
for (BasicBlock &BB : F) { for (BasicBlock &BB : F) {

View File

@ -395,8 +395,7 @@ bool MarkSubGraph(uint32_t ss, uint32_t tt) {
} }
// Check if there is an empty path. // Check if there is an empty path.
if (NextMarked[tt].count(TopoOrder[0]) > 0) if (NextMarked[tt].count(TopoOrder[0]) > 0) return true;
return true;
return false; return false;
} }
@ -432,8 +431,10 @@ void MarkVertice() {
} }
if (emptyPathExists) { if (emptyPathExists) {
// Mark all exit blocks to catch the empty path. // Mark all exit blocks to catch the empty path.
Marked.insert(t_Pred[0].begin(), t_Pred[0].end()); Marked.insert(t_Pred[0].begin(), t_Pred[0].end());
} }
} }

View File

@ -19,6 +19,15 @@ see how often the loop has been rerun.
This again is a tradeoff for speed for less path information. This again is a tradeoff for speed for less path information.
To enable this mode set `AFL_LLVM_INSTRIM_LOOPHEAD=1`. To enable this mode set `AFL_LLVM_INSTRIM_LOOPHEAD=1`.
There is an additional optimization option that skips single block
functions. In 95% of the C targets and (guess) 50% of the C++ targets
it is good to enable this, as otherwise pointless instrumentation occurs.
The corner case where we want this instrumentation is when vtable/call table
is used and the index to that vtable/call table is not set in specific
basic blocks.
To enable skipping these (most of the time) unnecessary instrumentations set
`AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK=1`
## Background ## Background
The paper: [InsTrim: Lightweight Instrumentation for Coverage-guided Fuzzing] The paper: [InsTrim: Lightweight Instrumentation for Coverage-guided Fuzzing]