diff --git a/afl_transforms/tools/zax/zuntracer.cpp b/afl_transforms/tools/zax/zuntracer.cpp index 817f2cd5574ed0cee9aeec8682bb708abe809aa0..d83fd885904201b7293bcb386357d8a847b0bdc7 100644 --- a/afl_transforms/tools/zax/zuntracer.cpp +++ b/afl_transforms/tools/zax/zuntracer.cpp @@ -21,6 +21,33 @@ void ZUntracer_t::afl_instrument_bb(Instruction_t *p_inst, const bool p_redZoneH { assert(p_inst); + const auto trace_map_fixed_addr = getenv("ZAFL_TRACE_MAP_FIXED_ADDRESS"); + const auto do_fixed_addr_optimization = (trace_map_fixed_addr!=nullptr); + + if (do_fixed_addr_optimization) + _afl_instrument_bb_fixed(p_inst, trace_map_fixed_addr); + else + _afl_instrument_bb(p_inst, p_redZoneHint); +} + +void ZUntracer_t::_afl_instrument_bb_fixed(Instruction_t *p_inst, char* p_tracemap_addr) +{ + // 1st instruction in block record is the new entry point of the block (p_inst) + // 2nd instruction in block record is where the instruction at the old entry point is now at (orig) + const auto blockid = get_blockid(); + BBRecord_t block_record; + block_record.push_back(p_inst); + + // e.g.: mov BYTE [ 0x10000 + blockid ], 0x1 + const auto s = string("mov BYTE [") + p_tracemap_addr + "+" + to_string(blockid) + "], 0x1"; + const auto orig = insertAssemblyBefore(p_inst, s); + block_record.push_back(orig); + + m_modifiedBlocks[blockid] = block_record; +} + +void ZUntracer_t::_afl_instrument_bb(Instruction_t *p_inst, const bool p_redZoneHint) +{ /* Original afl instrumentation: block_id = <random>; diff --git a/afl_transforms/tools/zax/zuntracer.hpp b/afl_transforms/tools/zax/zuntracer.hpp index 88226b203fe7ff969d5f6af23323815e3b4c5460..fd88051fbf1b4b46ebc4418f31629a56c3448766 100644 --- a/afl_transforms/tools/zax/zuntracer.hpp +++ b/afl_transforms/tools/zax/zuntracer.hpp @@ -11,20 +11,24 @@ namespace Zafl // Block-level instrumentation for Untracer class ZUntracer_t : public Zax_t { -public: - ZUntracer_t() = delete; - ZUntracer_t(const ZUntracer_t&) = delete; - ZUntracer_t(IRDB_SDK::pqxxDB_t &p_dbinterface, IRDB_SDK::FileIR_t *p_variantIR, string p_entry, set<string> p_exits, bool p_use_stars=false, bool p_autozafl=false, bool p_verbose=false); - virtual ~ZUntracer_t() {}; - virtual int execute(); - -protected: - virtual zafl_blockid_t get_blockid(const unsigned p_maxid = 0xFFFF); - virtual void afl_instrument_bb(Instruction_t *p_inst, const bool p_hasLeafAnnotation, const bool p_collafl_optimization=false); - virtual set<libIRDB::BasicBlock_t*> getBlocksToInstrument(libIRDB::ControlFlowGraph_t &cfg); - -private: - zafl_blockid_t m_blockid; + public: + ZUntracer_t() = delete; + ZUntracer_t(const ZUntracer_t&) = delete; + ZUntracer_t(IRDB_SDK::pqxxDB_t &p_dbinterface, IRDB_SDK::FileIR_t *p_variantIR, string p_entry, set<string> p_exits, bool p_use_stars=false, bool p_autozafl=false, bool p_verbose=false); + virtual ~ZUntracer_t() {}; + virtual int execute(); + + protected: + virtual zafl_blockid_t get_blockid(const unsigned p_maxid = 0xFFFF); + virtual void afl_instrument_bb(Instruction_t *p_inst, const bool p_hasLeafAnnotation, const bool p_collafl_optimization=false); + virtual set<libIRDB::BasicBlock_t*> getBlocksToInstrument(libIRDB::ControlFlowGraph_t &cfg); + + private: + void _afl_instrument_bb_fixed(Instruction_t *p_inst, char* p_tracemap_addr); + void _afl_instrument_bb(Instruction_t *p_inst, const bool p_redZoneHint); + + private: + zafl_blockid_t m_blockid; }; } diff --git a/bin/zafl.sh b/bin/zafl.sh index 9ba6b03eefab8e841fa2fd0cedf747008c5a6db0..e1430a430aff42b0a6726d3e5274b87be94004d1 100755 --- a/bin/zafl.sh +++ b/bin/zafl.sh @@ -30,6 +30,8 @@ usage() echo " -c, --enable-breakup-critical-edges Breakup critical edges" echo " -C, --disable-breakup-critical-edges Do not breakup critical edges" echo " -f, --fork-server-only Fork server only" + echo " -m, --enable-fixed-map Use fixed address for tracing map" + echo " -M, --disable-fixed-map Disable fixed address tracing map (default)" echo } @@ -42,6 +44,10 @@ me=$(whoami) tmp_dir=/tmp/${me}/$$ mkdir -p $tmp_dir +# by default, use fixed address for map +trace_map_address="0x10000" +ZAFL_TM_ENV="" + cleanup() { if [ ! -z "$tmp_dir" ]; then @@ -143,6 +149,20 @@ parse_args() log_warning "Fork Server Only mode: no block-level instrumentation will be performed" shift ;; + -m | --enable-fixed-map) + shift + case $1 in + 0x*) + trace_map_address="$1" + shift + ;; + esac + ZAFL_TM_ENV="ZAFL_TRACE_MAP_FIXED_ADDRESS=$trace_map_address" + ;; + -M | --disable-fixed-map) + ZAFL_TM_ENV="" + shift + ;; -*|--*=) # unsupported flags echo "Error: Unsupported flag $1" >&2 exit 1 @@ -249,7 +269,16 @@ fi log_msg "Transforming input binary $input_binary into $output_zafl_binary" #cmd="$PSZ $input_binary $output_zafl_binary $ida_or_rida_opt -c move_globals=on -c zax=on -o move_globals:--elftables-only -o zipr:--traceplacement:on $stars_opt $zax_opt $verbose_opt $options $other_args" -cmd="$PSZ $input_binary $output_zafl_binary $ida_or_rida_opt -c move_globals=on -c zax=on -o move_globals:--elftables-only $stars_opt $zax_opt $verbose_opt $options $other_args" + +cmd="$ZAFL_TM_ENV $PSZ $input_binary $output_zafl_binary $ida_or_rida_opt -c move_globals=on -c zax=on -o move_globals:--elftables-only $stars_opt $zax_opt $verbose_opt $options $other_args" + +if [ ! -z "$ZAFL_TM_ENV" ]; then + log_msg "Trace map will be expected at fixed address" + if [ -z $ZAFL_TRACE_MAP_FIXED_ADDRESS ]; then + log_warning "When running afl-fuzz, make sure that the environment variable ZAFL_TRACE_MAP_FIXED_ADDRESS is exported and set properly to (otherwise the instrumented binary will crash):" + log_warning "export $ZAFL_TM_ENV" + fi +fi log_msg "Issuing command: $cmd" eval $cmd diff --git a/test/ls.zuntracer/test_ls.sh b/test/ls.zuntracer/test_ls.sh index 3eb7e6d4541d75a473ebef0a00c88577341f0a04..eb4b6ef93844b18061a1014f12a57df1d64a50b0 100755 --- a/test/ls.zuntracer/test_ls.sh +++ b/test/ls.zuntracer/test_ls.sh @@ -1,4 +1,4 @@ -AFL_TIMEOUT=30 +AFL_TIMEOUT=15 session=/tmp/tmp.ls.$$ TMP_FILE_1="${session}/ls.tmp.$$" @@ -34,7 +34,7 @@ build_zuntracer() { ls_zafl=$1 shift - zafl.sh `which ls` $ls_zafl --untracer --tempdir analysis.${ls_zafl} + zafl.sh `which ls` $ls_zafl --untracer --tempdir analysis.${ls_zafl} $* if [ ! $? -eq 0 ]; then log_error "$ls_zafl: unable to generate zafl version" else @@ -102,18 +102,25 @@ build_zuntracer ls.untracer.critical_edge -c test_zuntracer ./ls.untracer.critical_edge -lt # zuntracer, do break critical edges, optimize graph -build_zuntracer ls.untracer.critical_edge.graph -c -g +build_zuntracer ls.untracer.critical_edge.graph -c -g -M test_zuntracer ./ls.untracer.critical_edge.graph -lt log_message "Fuzz zuntracer (basic block coverage) for $AFL_TIMEOUT seconds" fuzz_with_zafl ./ls.untracer.no_critical_edge -lt log_message "Fuzz zuntracer (break critical edges) for $AFL_TIMEOUT seconds" -fuzz_with_zafl ./ls.untracer.critical_edge -lt +fuzz_with_zafl ./ls.untracer.critical_edge -lt log_message "Fuzz zuntracer (break critical edges + graph optimization) for $AFL_TIMEOUT seconds" fuzz_with_zafl ./ls.untracer.critical_edge.graph -lt +build_zuntracer ls.untracer.fixed -m +test_zuntracer ./ls.untracer.fixed -lt +build_zuntracer ls.untracer.fixed.0x10000 -m 0x10000 +test_zuntracer ./ls.untracer.fixed.0x10000 -lt + +fuzz_with_zafl ./ls.untracer.fixed.0x10000 -lt + log_success "all tests passed: zafl/zuntracer instrumentation operational on ls" cleanup