diff --git a/docs/Changelog.md b/docs/Changelog.md index 39947c1b..e24c2335 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -15,6 +15,10 @@ (thanks to @kcwu for raising the issues and providing support!) - more 64 bit archicture support by @maribu - afl-cc: + - Added instrumenting hidden edges (approx 5% edges were not instrumented, + LLVM sancov overall misses 8% of edges compared to our implementation) + Note that is is currently only implemented for our PCGUARD plugin, not + LTO, CLASSIC, etc.! - Fix to make AFL_SAN_NO_INST work with gcc_plugin - MacOS aflpp driver compilation fix (-fsanitize=fuzzer implementation) - Make AFL_DUMP_MAP_SIZE work even if the target has sanitizer issues diff --git a/docs/fuzzing_in_depth.md b/docs/fuzzing_in_depth.md index 59a6d4bc..60c2aade 100644 --- a/docs/fuzzing_in_depth.md +++ b/docs/fuzzing_in_depth.md @@ -869,10 +869,11 @@ Here are some of the most important caveats for AFL++: - There is no direct support for fuzzing network services, background daemons, or interactive apps that require UI interaction to work. You may need to make - simple code changes to make them behave in a more traditional way. Preeny or - libdesock may offer a relatively simple option, too - see: + simple code changes to make them behave in a more traditional way. Preeny, + libdesock or desockmulti may offer a relatively simple option, too - see: [https://github.com/zardus/preeny](https://github.com/zardus/preeny) or [https://github.com/fkie-cad/libdesock](https://github.com/fkie-cad/libdesock) + [https://github.com/zyingp/desockmulti](https://github.com/zyingp/desockmulti) Some useful tips for modifying network-based services can be also found at: [https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop](https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index c4d2c8f2..c1e6e0c8 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -1216,7 +1216,6 @@ u8 *describe_op(afl_state_t *, u8, size_t); #endif u8 save_if_interesting(afl_state_t *, void *, u32, u8); u8 has_new_bits(afl_state_t *, u8 *); -u8 has_new_bits_unclassified(afl_state_t *, u8 *); #ifndef AFL_SHOWMAP void classify_counts(afl_forkserver_t *); #endif diff --git a/include/forkserver.h b/include/forkserver.h index db3bfcb3..41f85327 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -242,6 +242,7 @@ typedef enum fsrv_run_result { 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_setup_preload(afl_forkserver_t *fsrv, char *argv0); 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, diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index 7d2e45b3..726319c2 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -333,7 +333,7 @@ class ModuleSanitizerCoverageLTOLegacyPass : public ModulePass { } else { - if (getenv("AFL_DEBUG")) { DEBUGF("Instrument disabled\n"); } + if (getenv("AFL_DEBUG")) { DEBUGF("Instrumentation disabled\n"); } return false; } @@ -396,7 +396,7 @@ PreservedAnalyses ModuleSanitizerCoverageLTO::run(Module &M, } else { - if (debug) { DEBUGF("Instrument disabled\n"); } + if (debug) { DEBUGF("Instrumentation disabled\n"); } } diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index 7c70a42e..6cd770ee 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -13,6 +13,7 @@ #include "llvm/Transforms/Instrumentation/SanitizerCoverage.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" +// #include "llvm/IR/Verifier.h" #if LLVM_VERSION_MAJOR >= 15 #if LLVM_VERSION_MAJOR < 17 #include "llvm/ADT/Triple.h" @@ -76,9 +77,9 @@ #else #include "llvm/Transforms/Utils/Instrumentation.h" #endif - #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/ModuleUtils.h" +#include "llvm/ADT/STLExtras.h" #include "config.h" #include "debug.h" @@ -206,7 +207,8 @@ class ModuleSanitizerCoverageAFL SanitizerCoverageOptions Options; - uint32_t instr = 0, selects = 0, unhandled = 0, dump_cc = 0; + uint32_t instr = 0, selects = 0, hidden = 0, unhandled = 0, skippedbb = 0, + dump_cc = 0; GlobalVariable *AFLMapPtr = NULL; ConstantInt *One = NULL; ConstantInt *Zero = NULL; @@ -279,7 +281,7 @@ PreservedAnalyses ModuleSanitizerCoverageAFL::run(Module &M, } else { - if (getenv("AFL_DEBUG")) { DEBUGF("Instrument disabled\n"); } + if (getenv("AFL_DEBUG")) { DEBUGF("Instrumentation disabled\n"); } } @@ -505,9 +507,16 @@ bool ModuleSanitizerCoverageAFL::instrumentModule( getenv("AFL_USE_TSAN") ? ", TSAN" : "", getenv("AFL_USE_CFISAN") ? ", CFISAN" : "", getenv("AFL_USE_UBSAN") ? ", UBSAN" : ""); + char buf[32] = ""; + if (skippedbb) { + + snprintf(buf, sizeof(buf), " %u instrumentations saved.", skippedbb); + + } + OKF("Instrumented %u locations with no collisions (%s mode) of which are " - "%u handled and %u unhandled selects.", - instr, modeline, selects, unhandled); + "%u handled and %u unhandled special instructions.%s", + instr, modeline, selects + hidden, unhandled, buf); } @@ -781,11 +790,14 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage( if (AllBlocks.empty()) return false; - uint32_t cnt_cov = 0, cnt_sel = 0, cnt_sel_inc = 0; + uint32_t cnt_cov = 0, cnt_sel = 0, cnt_sel_inc = 0, cnt_hidden_sel = 0, + cnt_hidden_sel_inc = 0, skip_blocks = 0; static uint32_t first = 1; for (auto &BB : F) { + bool block_is_instrumented = false; + for (auto &IN : BB) { CallInst *callInst = nullptr; @@ -799,11 +811,11 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage( if (!FuncName.compare(StringRef("dlopen")) || !FuncName.compare(StringRef("_dlopen"))) { - fprintf(stderr, - "WARNING: dlopen() detected. To have coverage for a library " - "that your target dlopen()'s this must either happen before " - "__AFL_INIT() or you must use AFL_PRELOAD to preload all " - "dlopen()'ed libraries!\n"); + WARNF( + "dlopen() detected. To have coverage for a library that your " + "target dlopen()'s this must either happen before __AFL_INIT() " + "or you must use AFL_PRELOAD to preload all dlopen()'ed " + "libraries!\n"); continue; } @@ -811,53 +823,183 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage( if (!FuncName.compare(StringRef("__afl_coverage_interesting"))) { cnt_cov++; + block_is_instrumented = true; } } - SelectInst *selectInst = nullptr; + bool instrumentInst = false; + ICmpInst *icmp; + FCmpInst *fcmp; - if ((selectInst = dyn_cast(&IN))) { + if ((icmp = dyn_cast(&IN)) || + (fcmp = dyn_cast(&IN)) || isa(&IN)) { - Value *c = selectInst->getCondition(); - auto t = c->getType(); - if (t->getTypeID() == llvm::Type::IntegerTyID) { + // || isa(&IN) - cnt_sel++; - cnt_sel_inc += 2; + bool usedInBranch = false, usedInSelectDecision = false; - } + for (auto *U : IN.users()) { - else if (t->getTypeID() == llvm::Type::FixedVectorTyID) { + if (isa(U)) { - FixedVectorType *tt = dyn_cast(t); - if (tt) { + usedInBranch = true; + break; - cnt_sel++; - cnt_sel_inc += (tt->getElementCount().getKnownMinValue() * 2); + } + + if (auto *sel = dyn_cast(U)) { + + if (icmp && sel->getCondition() == icmp) { + + usedInSelectDecision = true; + + } else if (fcmp && sel->getCondition() == fcmp) { + + usedInSelectDecision = true; + + } } } + if (!usedInBranch && !usedInSelectDecision) { + + // errs() << "Instrument! " << *(&IN) << "\n"; + instrumentInst = true; + + } + } + if (instrumentInst) { + + block_is_instrumented = true; + SelectInst *selectInst; + ICmpInst *icmp; + FCmpInst *fcmp; + // PHINode *phiInst; + // errs() << "IN: " << *(&IN) << "\n"; + + /* if ((phiInst = dyn_cast(&IN))) { + + cnt_hidden_sel++; + cnt_hidden_sel_inc += phiInst->getNumIncomingValues(); + + } else*/ + + if ((icmp = dyn_cast(&IN))) { + + if (icmp->getType()->isIntegerTy(1)) { + + cnt_sel++; + cnt_sel_inc += 2; + + } else { + + unhandled++; + + } + + } else if ((fcmp = dyn_cast(&IN))) { + + if (fcmp->getType()->isIntegerTy(1)) { + + cnt_sel++; + cnt_sel_inc += 2; + + } else { + + unhandled++; + + } + + } else if ((selectInst = dyn_cast(&IN))) { + + Value *c = selectInst->getCondition(); + auto t = c->getType(); + if (t->getTypeID() == llvm::Type::IntegerTyID) { + + cnt_sel++; + cnt_sel_inc += 2; + + } else if (t->getTypeID() == llvm::Type::FixedVectorTyID) { + + FixedVectorType *tt = dyn_cast(t); + if (tt) { + + cnt_sel++; + cnt_sel_inc += (tt->getElementCount().getKnownMinValue() * 2); + + } + + } else { + + if (!be_quiet) { + + WARNF("unknown select ID type: %u\n", t->getTypeID()); + + } + + } + + } /*else { + + cnt_hidden_sel++; + cnt_hidden_sel_inc += 2; + + }*/ + + } + + } + + if (block_is_instrumented && &BB != &BB.getParent()->getEntryBlock() && + llvm::is_contained(AllBlocks, &BB)) { + + Instruction *instr = &*BB.begin(); + LLVMContext &Ctx = BB.getContext(); + MDNode *md = MDNode::get(Ctx, MDString::get(Ctx, "skipinstrument")); + instr->setMetadata("tag", md); + skip_blocks++; + } } - CreateFunctionLocalArrays(F, AllBlocks, first + cnt_cov + cnt_sel_inc); + uint32_t xtra = 0; + if (skip_blocks < first + cnt_cov + cnt_sel_inc + cnt_hidden_sel_inc) { + + xtra = first + cnt_cov + cnt_sel_inc + cnt_hidden_sel_inc - skip_blocks; + + } + + CreateFunctionLocalArrays(F, AllBlocks, xtra); + + if (!FunctionGuardArray) { + + WARNF( + "SANCOV: FunctionGuardArray is NULL, failed to emit instrumentation."); + return false; + + } if (first) { first = 0; } selects += cnt_sel; + hidden += cnt_hidden_sel; - uint32_t special = 0, local_selects = 0, skip_next = 0; + uint32_t special = 0, local_selects = 0, skip_select = 0, skip_icmp = 0; + // uint32_t skip_phi = 0; for (auto &BB : F) { + // errs() << *(&BB) << "\n"; + for (auto &IN : BB) { + // errs() << *(&IN) << "\n"; CallInst *callInst = nullptr; if ((callInst = dyn_cast(&IN))) { @@ -875,15 +1017,6 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage( IRBuilder<> IRB(callInst); #endif - if (!FunctionGuardArray) { - - fprintf(stderr, - "SANCOV: FunctionGuardArray is NULL, failed to emit " - "instrumentation."); - continue; - - } - Value *GuardPtr = IRB.CreateIntToPtr( IRB.CreateAdd( IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), @@ -897,132 +1030,324 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage( } - SelectInst *selectInst = nullptr; + bool instrumentInst = false; + ICmpInst *icmp; + FCmpInst *fcmp; - if (!skip_next && (selectInst = dyn_cast(&IN))) { + if ((icmp = dyn_cast(&IN)) || + (fcmp = dyn_cast(&IN)) || isa(&IN)) { - uint32_t vector_cnt = 0; - Value *condition = selectInst->getCondition(); - Value *result; - auto t = condition->getType(); - IRBuilder<> IRB(selectInst->getNextNode()); + // || isa(&IN) - if (t->getTypeID() == llvm::Type::IntegerTyID) { + bool usedInBranch = false, usedInSelectDecision = false; - if (!FunctionGuardArray) { + for (auto *U : IN.users()) { - fprintf(stderr, - "SANCOV: FunctionGuardArray is NULL, failed to emit " - "instrumentation."); - continue; + if (isa(U)) { + + usedInBranch = true; + break; } - auto GuardPtr1 = IRB.CreateIntToPtr( - IRB.CreateAdd( - IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), - ConstantInt::get( - IntptrTy, - (cnt_cov + local_selects++ + AllBlocks.size()) * 4)), - Int32PtrTy); + if (auto *sel = dyn_cast(U)) { - auto GuardPtr2 = IRB.CreateIntToPtr( - IRB.CreateAdd( - IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), - ConstantInt::get( - IntptrTy, - (cnt_cov + local_selects++ + AllBlocks.size()) * 4)), - Int32PtrTy); + if (icmp && sel->getCondition() == icmp) { - result = IRB.CreateSelect(condition, GuardPtr1, GuardPtr2); + usedInSelectDecision = true; + break; - } else + } else if (fcmp && sel->getCondition() == fcmp) { -#if LLVM_VERSION_MAJOR >= 14 - if (t->getTypeID() == llvm::Type::FixedVectorTyID) { - - FixedVectorType *tt = dyn_cast(t); - if (tt) { - - uint32_t elements = tt->getElementCount().getFixedValue(); - vector_cnt = elements; - if (elements) { - - FixedVectorType *GuardPtr1 = - FixedVectorType::get(Int32PtrTy, elements); - FixedVectorType *GuardPtr2 = - FixedVectorType::get(Int32PtrTy, elements); - Value *x, *y; - - if (!FunctionGuardArray) { - - fprintf(stderr, - "SANCOV: FunctionGuardArray is NULL, failed to emit " - "instrumentation."); - continue; - - } - - Value *val1 = IRB.CreateIntToPtr( - IRB.CreateAdd( - IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), - ConstantInt::get( - IntptrTy, - (cnt_cov + local_selects++ + AllBlocks.size()) * 4)), - Int32PtrTy); - x = IRB.CreateInsertElement(GuardPtr1, val1, (uint64_t)0); - - Value *val2 = IRB.CreateIntToPtr( - IRB.CreateAdd( - IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), - ConstantInt::get( - IntptrTy, - (cnt_cov + local_selects++ + AllBlocks.size()) * 4)), - Int32PtrTy); - y = IRB.CreateInsertElement(GuardPtr2, val2, (uint64_t)0); - - for (uint64_t i = 1; i < elements; i++) { - - val1 = IRB.CreateIntToPtr( - IRB.CreateAdd( - IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), - ConstantInt::get(IntptrTy, (cnt_cov + local_selects++ + - AllBlocks.size()) * - 4)), - Int32PtrTy); - x = IRB.CreateInsertElement(x, val1, i); - - val2 = IRB.CreateIntToPtr( - IRB.CreateAdd( - IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), - ConstantInt::get(IntptrTy, (cnt_cov + local_selects++ + - AllBlocks.size()) * - 4)), - Int32PtrTy); - y = IRB.CreateInsertElement(y, val2, i); - - } - - result = IRB.CreateSelect(condition, x, y); + usedInSelectDecision = true; + break; } } - } else + } + + if (!usedInBranch && !usedInSelectDecision) { + + // errs() << "Instrument! " << *(&IN) << "\n"; + instrumentInst = true; + + } + + } + + if (instrumentInst) { + + Value *result = nullptr; + uint32_t vector_cnt = 0; + SelectInst *selectInst; + // PHINode *phi = nullptr, *newPhi = nullptr; + IRBuilder<> IRB(IN.getNextNode()); + + if ((icmp = dyn_cast(&IN))) { + + if (!icmp->getType()->isIntegerTy(1)) { continue; } + + if (skip_icmp) { + + skip_icmp--; + continue; + + } + + if (debug) { + + if (DILocation *Loc = IN.getDebugLoc()) { + + llvm::errs() << "DEBUG " << Loc->getFilename() << ":" + << Loc->getLine() << ":"; + std::string path = + Loc->getDirectory().str() + "/" + Loc->getFilename().str(); + std::ifstream sourceFile(path); + std::string lineContent; + for (unsigned line = 1; line <= Loc->getLine(); ++line) + std::getline(sourceFile, lineContent); + llvm::errs() << lineContent << "\n"; + + } + + errs() << *(&IN) << "\n"; + + } + + auto res = icmp; + auto GuardPtr1 = IRB.CreateInBoundsGEP( + FunctionGuardArray->getValueType(), FunctionGuardArray, + {IRB.getInt64(0), + IRB.getInt32((cnt_cov + local_selects++ + AllBlocks.size()))}); + + auto GuardPtr2 = IRB.CreateInBoundsGEP( + FunctionGuardArray->getValueType(), FunctionGuardArray, + {IRB.getInt64(0), + IRB.getInt32((cnt_cov + local_selects++ + AllBlocks.size()))}); + + result = IRB.CreateSelect(res, GuardPtr1, GuardPtr2); + skip_select = 1; + // fprintf(stderr, "Icmp!\n"); + + } else if ((fcmp = dyn_cast(&IN))) { + + if (!fcmp->getType()->isIntegerTy(1)) { continue; } + + if (debug) { + + if (DILocation *Loc = IN.getDebugLoc()) { + + llvm::errs() << "DEBUG " << Loc->getFilename() << ":" + << Loc->getLine() << ":"; + std::string path = + Loc->getDirectory().str() + "/" + Loc->getFilename().str(); + std::ifstream sourceFile(path); + std::string lineContent; + for (unsigned line = 1; line <= Loc->getLine(); ++line) + std::getline(sourceFile, lineContent); + llvm::errs() << lineContent << "\n"; + + } + + errs() << *(&IN) << "\n"; + + } + + auto res = fcmp; + auto GuardPtr1 = IRB.CreateInBoundsGEP( + FunctionGuardArray->getValueType(), FunctionGuardArray, + {IRB.getInt64(0), + IRB.getInt32((cnt_cov + local_selects++ + AllBlocks.size()))}); + + auto GuardPtr2 = IRB.CreateInBoundsGEP( + FunctionGuardArray->getValueType(), FunctionGuardArray, + {IRB.getInt64(0), + IRB.getInt32((cnt_cov + local_selects++ + AllBlocks.size()))}); + + result = IRB.CreateSelect(res, GuardPtr1, GuardPtr2); + skip_select = 1; + // fprintf(stderr, "Fcmp!\n"); + + /*} else if ((phi = dyn_cast(&IN))) { + + if (skip_phi) { + + skip_phi = 0; + // errs() << "SKIP: " << *(&IN) << "\n"; + continue; + + } + + // errs() << "-->PHI: " << *(&IN) << "\n"; + // continue; + Instruction *insertBefore = + &*phi->getParent()->getFirstInsertionPt(); newPhi = + PHINode::Create(Int32PtrTy, 0, "", insertBefore); BasicBlock + *phiBlock = phi->getParent(); + + for (BasicBlock *pred : predecessors(phiBlock)) { + + IRBuilder<> predBuilder(pred->getTerminator()); + + Value *ptr = predBuilder.CreateInBoundsGEP( + FunctionGuardArray->getValueType(), FunctionGuardArray, + ConstantInt::get( + IntptrTy, (cnt_cov + local_selects++ + + AllBlocks.size()))); newPhi->addIncoming(ptr, pred); + + } + + result = newPhi; + skip_phi = 1; + // fprintf(stderr, "Phi!\n"); + */ + + } else if ((selectInst = dyn_cast(&IN))) { + + if (skip_select) { + + skip_select = 0; + continue; + + } else { + + // fprintf(stderr, "Select!\n"); + + } + + Value *condition = selectInst->getCondition(); + auto t = condition->getType(); + + if (t->getTypeID() == llvm::Type::IntegerTyID) { + + auto GuardPtr1 = IRB.CreateIntToPtr( + IRB.CreateAdd( + IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), + ConstantInt::get( + IntptrTy, + (cnt_cov + local_selects++ + AllBlocks.size()) * 4)), + Int32PtrTy); + + auto GuardPtr2 = IRB.CreateIntToPtr( + IRB.CreateAdd( + IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), + ConstantInt::get( + IntptrTy, + (cnt_cov + local_selects++ + AllBlocks.size()) * 4)), + Int32PtrTy); + + result = IRB.CreateSelect(condition, GuardPtr1, GuardPtr2); + skip_select = 1; + + } else + +#if LLVM_VERSION_MAJOR >= 14 + if (t->getTypeID() == llvm::Type::FixedVectorTyID) { + + FixedVectorType *tt = dyn_cast(t); + + if (tt) { + + uint32_t elements = tt->getElementCount().getFixedValue(); + vector_cnt = elements; + if (elements) { + + FixedVectorType *GuardPtr1 = + FixedVectorType::get(Int32PtrTy, elements); + FixedVectorType *GuardPtr2 = + FixedVectorType::get(Int32PtrTy, elements); + Value *x, *y; + + Value *val1 = IRB.CreateIntToPtr( + IRB.CreateAdd( + IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), + ConstantInt::get(IntptrTy, (cnt_cov + local_selects++ + + AllBlocks.size()) * + 4)), + Int32PtrTy); + x = IRB.CreateInsertElement(GuardPtr1, val1, (uint64_t)0); + + Value *val2 = IRB.CreateIntToPtr( + IRB.CreateAdd( + IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), + ConstantInt::get(IntptrTy, (cnt_cov + local_selects++ + + AllBlocks.size()) * + 4)), + Int32PtrTy); + y = IRB.CreateInsertElement(GuardPtr2, val2, (uint64_t)0); + + for (uint64_t i = 1; i < elements; i++) { + + val1 = IRB.CreateIntToPtr( + IRB.CreateAdd( + IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), + ConstantInt::get( + IntptrTy, + (cnt_cov + local_selects++ + AllBlocks.size()) * + 4)), + Int32PtrTy); + x = IRB.CreateInsertElement(x, val1, i); + + val2 = IRB.CreateIntToPtr( + IRB.CreateAdd( + IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), + ConstantInt::get( + IntptrTy, + (cnt_cov + local_selects++ + AllBlocks.size()) * + 4)), + Int32PtrTy); + y = IRB.CreateInsertElement(y, val2, i); + + } + + result = IRB.CreateSelect(condition, x, y); + skip_select = 1; + + } + + } + + } else #endif - { + { - // fprintf(stderr, "UNHANDLED: %u\n", t->getTypeID()); - unhandled++; - continue; + if (!be_quiet) { + + WARNF("Warning: Unhandled ID type: %u\n", t->getTypeID()); + + } + + unhandled++; + continue; + + } } uint32_t vector_cur = 0; /* Load SHM pointer */ + /* + if (newPhi) { + + auto *inst = dyn_cast(result); + PHINode *nphi; + + while ((nphi = dyn_cast(inst))) { + + // fprintf(stderr, "NEXT!\n"); + inst = inst->getNextNode(); + + } + + IRB.SetInsertPoint(inst); + + } + + */ LoadInst *MapPtr = IRB.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr); @@ -1073,6 +1398,7 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage( auto cf = IRB.CreateICmpEQ(Incr, Zero); auto carry = IRB.CreateZExt(cf, Int8Ty); Incr = IRB.CreateAdd(Incr, carry); + skip_icmp++; } @@ -1094,13 +1420,8 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage( } - skip_next = 1; instr += vector_cnt; - } else { - - skip_next = 0; - } } @@ -1109,9 +1430,40 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage( if (AllBlocks.empty() && !special && !local_selects) return false; - if (!AllBlocks.empty()) - for (size_t i = 0, N = AllBlocks.size(); i < N; i++) - InjectCoverageAtBlock(F, *AllBlocks[i], i, IsLeafFunc); + uint32_t skipped = 0; + + if (!AllBlocks.empty()) { + + for (size_t i = 0, N = AllBlocks.size(); i < N; i++) { + + auto instr = AllBlocks[i]->begin(); + if (instr->getMetadata("skipinstrument")) { + + skipped++; + // fprintf(stderr, "Skipped!\n"); + + } else { + + InjectCoverageAtBlock(F, *AllBlocks[i], i - skipped, IsLeafFunc); + + } + + } + + } + + skippedbb += skipped; + + /* + if (verifyFunction(F, &errs())) { + + errs() << "Broken function after instrumentation\n"; + F.print(errs(), nullptr); + report_fatal_error("Invalid IR"); + + } + + */ return true; diff --git a/instrumentation/afl-llvm-pass.so.cc b/instrumentation/afl-llvm-pass.so.cc index e7839612..fe8cc06c 100644 --- a/instrumentation/afl-llvm-pass.so.cc +++ b/instrumentation/afl-llvm-pass.so.cc @@ -227,7 +227,7 @@ bool AFLCoverage::runOnModule(Module &M) { #if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ if (getenv("AFL_LLVM_ONLY_FSRV")) { - if (debug) { fprintf(stderr, "Instrument disabled\n"); } + if (debug) { fprintf(stderr, "Instrumentation disabled\n"); } return PreservedAnalyses::all(); } @@ -235,7 +235,7 @@ bool AFLCoverage::runOnModule(Module &M) { #else if (getenv("AFL_LLVM_ONLY_FSRV")) { - if (debug) { fprintf(stderr, "Instrument disabled\n"); } + if (debug) { fprintf(stderr, "Instrumentation disabled\n"); } return true; } diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc index a2165d7b..3fbe13f2 100644 --- a/instrumentation/cmplog-instructions-pass.cc +++ b/instrumentation/cmplog-instructions-pass.cc @@ -64,6 +64,8 @@ using namespace llvm; namespace { +using DomTreeCallback = function_ref; + #if LLVM_MAJOR >= 11 /* use new pass manager */ class CmpLogInstructions : public PassInfoMixin { @@ -92,6 +94,8 @@ class CmpLogInstructions : public ModulePass { #else bool runOnModule(Module &M) override; + bool IsBackEdge(BasicBlock *From, BasicBlock *To, const DominatorTree *DT); + #if LLVM_VERSION_MAJOR >= 4 StringRef getPassName() const override { @@ -106,7 +110,7 @@ class CmpLogInstructions : public ModulePass { #endif private: - bool hookInstrs(Module &M); + bool hookInstrs(Module &M, DomTreeCallback DTCallback); }; @@ -158,7 +162,16 @@ Iterator Unique(Iterator first, Iterator last) { } -bool CmpLogInstructions::hookInstrs(Module &M) { +bool IsBackEdge(BasicBlock *From, BasicBlock *To, const DominatorTree *DT) { + + if (DT->dominates(To, From)) return true; + if (auto Next = To->getUniqueSuccessor()) + if (DT->dominates(Next, From)) return true; + return false; + +} + +bool CmpLogInstructions::hookInstrs(Module &M, DomTreeCallback DTCallback) { std::vector icomps; LLVMContext &C = M.getContext(); @@ -296,6 +309,7 @@ bool CmpLogInstructions::hookInstrs(Module &M) { for (auto &F : M) { if (!isInInstrumentList(&F, MNAME)) continue; + const DominatorTree *DT = DTCallback(F); for (auto &BB : F) { @@ -304,6 +318,12 @@ bool CmpLogInstructions::hookInstrs(Module &M) { CmpInst *selectcmpInst = nullptr; if ((selectcmpInst = dyn_cast(&IN))) { + // skip loop comparisons + if (selectcmpInst->hasOneUse()) + if (auto BR = dyn_cast(selectcmpInst->user_back())) + for (BasicBlock *B : BR->successors()) + if (IsBackEdge(BR->getParent(), B, DT)) continue; + icomps.push_back(selectcmpInst); } @@ -681,11 +701,19 @@ bool CmpLogInstructions::runOnModule(Module &M) { #endif + auto &FAM = MAM.getResult(M).getManager(); + auto DTCallback = [&FAM](Function &F) -> const DominatorTree *{ + + return &FAM.getResult(F); + + }; + if (getenv("AFL_QUIET") == NULL) printf("Running cmplog-instructions-pass by andreafioraldi@gmail.com\n"); else be_quiet = 1; - bool ret = hookInstrs(M); + + bool ret = hookInstrs(M, DTCallback); verifyModule(M); #if LLVM_MAJOR >= 11 /* use new pass manager */ diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 89a27f63..a006498a 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -75,7 +75,6 @@ static bool edges_only, /* Ignore hit counts? */ static volatile u8 stop_soon; /* Ctrl-C pressed? */ static u8 *target_path; -static u8 frida_mode; static u8 qemu_mode; static u8 cs_mode; static u32 map_size = MAP_SIZE; @@ -628,9 +627,7 @@ static void handle_stop_sig(int sig) { static void set_up_environment(char **argv) { - u8 *x; - char *afl_preload; - char *frida_afl_preload = NULL; + u8 *x; fsrv.dev_null_fd = open("/dev/null", O_RDWR); if (fsrv.dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); } @@ -672,57 +669,7 @@ static void set_up_environment(char **argv) { } set_sanitizer_defaults(); - - if (get_afl_env("AFL_PRELOAD")) { - - if (qemu_mode) { - - /* afl-qemu-trace takes care of converting AFL_PRELOAD. */ - - } else if (frida_mode) { - - afl_preload = getenv("AFL_PRELOAD"); - u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so"); - if (afl_preload) { - - frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary); - - } else { - - frida_afl_preload = alloc_printf("%s", frida_binary); - - } - - ck_free(frida_binary); - - setenv("LD_PRELOAD", frida_afl_preload, 1); -#ifdef __APPLE__ - setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1); -#endif - - } else { - - /* CoreSight mode uses the default behavior. */ - - setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1); -#ifdef __APPLE__ - setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1); -#endif - - } - - } else if (frida_mode) { - - u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so"); - setenv("LD_PRELOAD", frida_binary, 1); -#ifdef __APPLE__ - setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1); -#endif - ck_free(frida_binary); - - } - - if (frida_afl_preload) { ck_free(frida_afl_preload); } + afl_fsrv_setup_preload(&fsrv, argv[0]); } @@ -936,10 +883,9 @@ int main(int argc, char **argv_orig, char **envp) { case 'O': /* FRIDA mode */ - if (frida_mode) { FATAL("Multiple -O options not supported"); } + if (fsrv.frida_mode) { FATAL("Multiple -O options not supported"); } - frida_mode = 1; - fsrv.frida_mode = frida_mode; + fsrv.frida_mode = true; setenv("AFL_FRIDA_INST_SEED", "1", 1); break; diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index b5fec704..5bf300a3 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -320,6 +320,38 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) { } +void afl_fsrv_setup_preload(afl_forkserver_t *fsrv, char *argv0) { + + /* afl-qemu-trace takes care of converting AFL_PRELOAD. */ + if (fsrv->qemu_mode) return; + + u8 *afl_preload = getenv("AFL_PRELOAD"); + u8 *preload_path = NULL; + u8 *frida_binary = NULL; + if (fsrv->frida_mode) + frida_binary = find_afl_binary(argv0, "afl-frida-trace.so"); + + if (afl_preload && frida_binary) + preload_path = alloc_printf("%s:%s", afl_preload, frida_binary); + else if (afl_preload) + preload_path = ck_strdup(afl_preload); + else if (frida_binary) + preload_path = ck_strdup(frida_binary); + + ck_free(frida_binary); + + if (preload_path) { + + setenv("LD_PRELOAD", preload_path, 1); +#ifdef __APPLE__ + setenv("DYLD_INSERT_LIBRARIES", preload_path, 1); +#endif + ck_free(preload_path); + + } + +} + /* Wrapper for select() and read(), reading a 32 bit var. Returns the time passed to read. If the wait times out, returns timeout_ms + 1; diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 5d3cc71a..e3c114f5 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -255,7 +255,8 @@ inline u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) { * on rare cases it fall backs to the slow path: classify_counts() first, then * return has_new_bits(). */ -inline u8 has_new_bits_unclassified(afl_state_t *afl, u8 *virgin_map) { +static inline u8 has_new_bits_unclassified(afl_state_t *afl, u8 *virgin_map, + bool *classified) { /* Handle the hot path first: no new coverage */ u8 *end = afl->fsrv.trace_bits + afl->fsrv.map_size; @@ -272,6 +273,7 @@ inline u8 has_new_bits_unclassified(afl_state_t *afl, u8 *virgin_map) { #endif /* ^WORD_SIZE_64 */ classify_counts(&afl->fsrv); + *classified = true; return has_new_bits(afl, virgin_map); } @@ -470,6 +472,46 @@ void write_crash_readme(afl_state_t *afl) { } +static inline void classify_if_necessary(afl_state_t *afl, bool *classified) { + + if (*classified) return; + classify_counts(&afl->fsrv); + *classified = true; + +} + +static inline void calculate_cksum_if_necessary(afl_state_t *afl, u64 *cksum, + bool *cksumed, + bool *classified) { + + if (*cksumed) return; + classify_if_necessary(afl, classified); + *cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); + *cksumed = true; + +} + +static inline void calculate_new_bits_if_necessary(afl_state_t *afl, + u8 *new_bits, + bool *bits_counted, + bool *classified) { + + if (*bits_counted) return; + + if (*classified) { + + *new_bits = has_new_bits(afl, afl->virgin_bits); + + } else { + + *new_bits = has_new_bits_unclassified(afl, afl->virgin_bits, classified); + + } + + *bits_counted = true; + +} + /* Check if the result of an execve() during routine fuzzing is interesting, save or queue the input test case for further analysis if so. Returns 1 if entry is saved, 0 otherwise. */ @@ -498,13 +540,15 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem, u8 fn[PATH_MAX]; u8 *queue_fn = ""; - u8 new_bits = 0, keeping = 0, res, is_timeout = 0, need_hash = 1; - u8 classified = 0; + u8 keeping = 0, res, is_timeout = 0; u8 san_fault = 0, san_idx = 0, feed_san = 0; s32 fd; - u64 cksum = 0; u32 cksum_simplified = 0, cksum_unique = 0; + bool classified = false, bits_counted = false, cksumed = false; + u8 new_bits = 0; /* valid if bits_counted is true */ + u64 cksum = 0; /* valid if cksumed is true */ + afl->san_case_status = 0; /* Update path frequency. */ @@ -513,11 +557,7 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem, only be used for special schedules */ if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) { - classify_counts(&afl->fsrv); - classified = 1; - need_hash = 0; - - cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); + calculate_cksum_if_necessary(afl, &cksum, &cksumed, &classified); /* Saturated increment */ if (likely(afl->n_fuzz[cksum % N_FUZZ_SIZE] < 0xFFFFFFFF)) @@ -551,17 +591,9 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem, if (unlikely(afl->san_binary_length) && unlikely(afl->san_abstraction == COVERAGE_INCREASE)) { - if (classified) { - - /* We could have classified the bits in SAND with COVERAGE_INCREASE */ - new_bits = has_new_bits(afl, afl->virgin_bits); - - } else { - - new_bits = has_new_bits_unclassified(afl, afl->virgin_bits); - classified = 1; - - } + /* Check if the input increase the coverage */ + calculate_new_bits_if_necessary(afl, &new_bits, &bits_counted, + &classified); if (unlikely(new_bits)) { feed_san = 1; } @@ -570,15 +602,9 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem, if (unlikely(afl->san_binary_length) && likely(afl->san_abstraction == UNIQUE_TRACE)) { - // If schedule is not FAST..RARE, we need to classify counts here // Note: SAND was evaluated under FAST schedule but should also work // with other scedules. - if (!classified) { - - classify_counts(&afl->fsrv); - classified = 1; - - } + classify_if_necessary(afl, &classified); cksum_unique = hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); @@ -638,23 +664,7 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem, /* Keep only if there are new bits in the map, add to queue for future fuzzing, etc. */ - if (!unlikely(afl->san_abstraction == COVERAGE_INCREASE && feed_san)) { - - /* If we are in coverage increasing abstraction and have fed input to - sanitizers, we are sure it has new bits.*/ - if (classified) { - - /* We could have classified the bits in SAND with UNIQUE_TRACE */ - new_bits = has_new_bits(afl, afl->virgin_bits); - - } else { - - new_bits = has_new_bits_unclassified(afl, afl->virgin_bits); - classified = 1; - - } - - } + calculate_new_bits_if_necessary(afl, &new_bits, &bits_counted, &classified); if (likely(!new_bits)) { @@ -677,6 +687,11 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem, save_to_queue: + /* these calculations are necessary because some code flow may jump here via + goto */ + calculate_cksum_if_necessary(afl, &cksum, &cksumed, &classified); + calculate_new_bits_if_necessary(afl, &new_bits, &bits_counted, &classified); + #ifndef SIMPLE_FILES if (!afl->afl_env.afl_sha1_filenames) { @@ -758,6 +773,8 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem, #endif + afl->queue_top->exec_cksum = cksum; + if (new_bits == 2) { afl->queue_top->has_new_cov = 1; @@ -765,17 +782,8 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem, } - if (unlikely(need_hash && new_bits)) { - - /* due to classify counts we have to recalculate the checksum */ - afl->queue_top->exec_cksum = - hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); - need_hash = 0; - - } - /* For AFLFast schedules we update the new queue entry */ - if (likely(cksum)) { + if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) { afl->queue_top->n_fuzz_entry = cksum % N_FUZZ_SIZE; afl->n_fuzz[afl->queue_top->n_fuzz_entry] = 1; @@ -874,12 +882,9 @@ may_save_fault: } new_fault = fuzz_run_target(afl, &afl->fsrv, afl->hang_tmout); - if (!classified) { - - classify_counts(&afl->fsrv); - classified = 1; - - } + classified = false; + bits_counted = false; + cksumed = false; /* A corner case that one user reported bumping into: increasing the timeout actually uncovers a crash. Make sure we don't discard it if diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 2488f142..a6a70c59 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -495,36 +495,41 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, afl->afl_env.afl_post_process_keep_original = 1; /* we need a dummy run if this is LTO + cmplog */ - if (unlikely(afl->shm.cmplog_mode)) { + /* + if (unlikely(afl->shm.cmplog_mode)) { - (void)write_to_testcase(afl, (void **)&use_mem, q->len, 1); + (void)write_to_testcase(afl, (void **)&use_mem, q->len, 1); - fault = fuzz_run_target(afl, &afl->fsrv, use_tmout); + fault = fuzz_run_target(afl, &afl->fsrv, use_tmout); - /* afl->stop_soon is set by the handler for Ctrl+C. When it's pressed, - we want to bail out quickly. */ + // afl->stop_soon is set by the handler for Ctrl+C. When it's pressed, + // we want to bail out quickly. - if (afl->stop_soon || fault != afl->crash_mode) { goto abort_calibration; } + if (afl->stop_soon || fault != afl->crash_mode) { goto abort_calibration; - if (!afl->non_instrumented_mode && !afl->stage_cur && - !count_bytes(afl, afl->fsrv.trace_bits)) { + } - fault = FSRV_RUN_NOINST; - goto abort_calibration; + if (!afl->non_instrumented_mode && + !count_bytes(afl, afl->fsrv.trace_bits)) { + + fault = FSRV_RUN_NOINST; + goto abort_calibration; + + } + + #ifdef INTROSPECTION + if (unlikely(!q->bitsmap_size)) { q->bitsmap_size = afl->bitsmap_size; } + #endif } -#ifdef INTROSPECTION - if (unlikely(!q->bitsmap_size)) q->bitsmap_size = afl->bitsmap_size; -#endif - - } + */ if (q->exec_cksum) { memcpy(afl->first_trace, afl->fsrv.trace_bits, afl->fsrv.map_size); hnb = has_new_bits(afl, afl->virgin_bits); - if (hnb > new_bits) { new_bits = hnb; } + if (unlikely(hnb > new_bits)) { new_bits = hnb; } } @@ -553,7 +558,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, if (afl->stop_soon || fault != afl->crash_mode) { goto abort_calibration; } - if (!afl->non_instrumented_mode && !afl->stage_cur && + if (!afl->non_instrumented_mode && !count_bytes(afl, afl->fsrv.trace_bits)) { fault = FSRV_RUN_NOINST; @@ -562,17 +567,19 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, } #ifdef INTROSPECTION - if (unlikely(!q->bitsmap_size)) q->bitsmap_size = afl->bitsmap_size; + if (unlikely(!q->bitsmap_size)) { q->bitsmap_size = afl->bitsmap_size; } #endif classify_counts(&afl->fsrv); cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); - if (q->exec_cksum != cksum) { + + if (unlikely(q->exec_cksum != cksum)) { hnb = has_new_bits(afl, afl->virgin_bits); - if (hnb > new_bits) { new_bits = hnb; } - if (q->exec_cksum) { + if (unlikely(hnb > new_bits)) { new_bits = hnb; } + + if (likely(q->exec_cksum)) { u32 i; diff --git a/src/afl-showmap.c b/src/afl-showmap.c index bec328f4..bd0594dc 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -714,61 +714,8 @@ static void handle_stop_sig(int sig) { static void set_up_environment(afl_forkserver_t *fsrv, char **argv) { - char *afl_preload; - char *frida_afl_preload = NULL; - set_sanitizer_defaults(); - - if (get_afl_env("AFL_PRELOAD")) { - - if (fsrv->qemu_mode) { - - /* afl-qemu-trace takes care of converting AFL_PRELOAD. */ - - } else if (fsrv->frida_mode) { - - afl_preload = getenv("AFL_PRELOAD"); - u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so"); - if (afl_preload) { - - frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary); - - } else { - - frida_afl_preload = alloc_printf("%s", frida_binary); - - } - - ck_free(frida_binary); - - setenv("LD_PRELOAD", frida_afl_preload, 1); -#ifdef __APPLE__ - setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1); -#endif - - } else { - - /* CoreSight mode uses the default behavior. */ - - setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1); -#ifdef __APPLE__ - setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1); -#endif - - } - - } else if (fsrv->frida_mode) { - - u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so"); - setenv("LD_PRELOAD", frida_binary, 1); -#ifdef __APPLE__ - setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1); -#endif - ck_free(frida_binary); - - } - - if (frida_afl_preload) { ck_free(frida_afl_preload); } + afl_fsrv_setup_preload(fsrv, argv[0]); } diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 894924cd..60f0c84f 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -899,9 +899,7 @@ static void handle_stop_sig(int sig) { static void set_up_environment(afl_forkserver_t *fsrv, char **argv) { - u8 *x; - char *afl_preload; - char *frida_afl_preload = NULL; + u8 *x; fsrv->dev_null_fd = open("/dev/null", O_RDWR); if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); } @@ -945,57 +943,7 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) { } set_sanitizer_defaults(); - - if (get_afl_env("AFL_PRELOAD")) { - - if (fsrv->qemu_mode) { - - /* afl-qemu-trace takes care of converting AFL_PRELOAD. */ - - } else if (fsrv->frida_mode) { - - afl_preload = getenv("AFL_PRELOAD"); - u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so"); - if (afl_preload) { - - frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary); - - } else { - - frida_afl_preload = alloc_printf("%s", frida_binary); - - } - - ck_free(frida_binary); - - setenv("LD_PRELOAD", frida_afl_preload, 1); -#ifdef __APPLE__ - setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1); -#endif - - } else { - - /* CoreSight mode uses the default behavior. */ - - setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1); -#ifdef __APPLE__ - setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1); -#endif - - } - - } else if (fsrv->frida_mode) { - - u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so"); - setenv("LD_PRELOAD", frida_binary, 1); -#ifdef __APPLE__ - setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1); -#endif - ck_free(frida_binary); - - } - - if (frida_afl_preload) { ck_free(frida_afl_preload); } + afl_fsrv_setup_preload(fsrv, argv[0]); }