diff options
| author | van Hauser <vh@thc.org> | 2021-05-10 13:57:47 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-05-10 13:57:47 +0200 |
| commit | 8b7a7b29c60f11cdf6226b3e418e87a5c3f5caac (patch) | |
| tree | 6ce9d90644f161d21d802e9cbe48eb38467684e9 /frida_mode/src/instrument | |
| parent | d0225c2c4d465968660a08c93857fed354e539b1 (diff) | |
| download | afl++-8b7a7b29c60f11cdf6226b3e418e87a5c3f5caac.tar.gz | |
Push to stable (#895)
* sync (#886)
* Create FUNDING.yml
* Update FUNDING.yml
* moved custom_mutator examples
* unicorn speedtest makefile cleanup
* fixed example location
* fix qdbi
* update util readme
* Frida persistent (#880)
* Added x64 support for persistent mode (function call only), in-memory teest cases and complog
* Review changes, fix NeverZero and code to parse the .text section of the main executable. Excluded ranges TBC
* Various minor fixes and finished support for AFL_INST_LIBS
* Review changes
Co-authored-by: Your Name <you@example.com>
* nits
* fix frida mode
* Integer overflow/underflow fixes in libdislocator (#889)
* libdislocator: fixing integer overflow in 'max_mem' variable and setting 'max_mem' type to 'size_t'
* libdislocator: fixing potential integer underflow in 'total_mem' variable due to its different values in different threads
* Bumped warnings up to the max and fixed remaining issues (#890)
Co-authored-by: Your Name <you@example.com>
* nits
* frida mode - support non-pie
* nits
* nit
* update grammar mutator
* Fixes for aarch64, OSX and other minor issues (#891)
Co-authored-by: Your Name <you@example.com>
* nits
* nits
* fix PCGUARD, build aflpp_driver with fPIC
* Added representative fuzzbench test and test for libxml (#893)
* Added representative fuzzbench test and test for libxml
* Added support for building FRIDA from source with FRIDA_SOURCE=1
Co-authored-by: Your Name <you@example.com>
* nits
* update changelog
* typos
* fixed potential double free in custom trim (#881)
* error handling, freeing mem
* frida: complog -> cmplog
* fix statsd writing
* let aflpp_qemu_driver_hook.so build fail gracefully
* fix stdin trimming
* Support for AFL_ENTRYPOINT (#898)
Co-authored-by: Your Name <you@example.com>
* remove the input file .cur_input at the end of the fuzzing, if AFL_TMPDIR is used
* reverse push (#901)
* Create FUNDING.yml
* Update FUNDING.yml
* disable QEMU static pie
Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
* clarify that no modifications are required.
* add new test for frida_mode (please review)
* typos
* fix persistent mode (64-bit)
* set ARCH for linux intel 32-bit for frida-gum-devkit
* prepare for 32-bit support (later)
* not on qemu 3 anymore
* unicorn mips fixes
* instrumentation further move to C++11 (#900)
* unicorn fixes
* more unicorn fixes
* Fix memory errors when trim causes testcase growth (#881) (#903)
* Revert "fixed potential double free in custom trim (#881)"
This reverts commit e9d2f72382cab75832721d859c3e731da071435d.
* Revert "fix custom trim for increasing data"
This reverts commit 86a8ef168dda766d2f25f15c15c4d3ecf21d0667.
* Fix memory errors when trim causes testcase growth
Modify trim_case_custom to avoid writing into in_buf because
some custom mutators can cause the testcase to grow rather than
shrink.
Instead of modifying in_buf directly, we write the update out
to the disk when trimming is complete, and then the caller is
responsible for refreshing the in-memory buffer from the file.
This is still a bit sketchy because it does need to modify q->len in
order to notify the upper layers that something changed, and it could
end up telling upper layer code that the q->len is *bigger* than
the buffer (q->testcase_buf) that contains it, which is asking
for trouble down the line somewhere...
* Fix an unlikely situation
Put back some `unlikely()` calls that were in
the e9d2f72382cab75832721d859c3e731da071435d commit that was
reverted.
* typo
* Exit on time (#904)
* Variable AFL_EXIT_ON_TIME description has been added.
Variables AFL_EXIT_ON_TIME and afl_exit_on_time has been added.
afl->exit_on_time variable initialization has been added.
The asignment of a value to the afl->afl_env.afl_exit_on_time variable from
environment variables has been added.
Code to exit on timeout if new path not found has been added.
* Type of afl_exit_on_time variable has been changed.
Variable exit_on_time has been added to the afl_state_t structure.
* Command `export AFL_EXIT_WHEN_DONE=1` has been added.
* Millisecond to second conversion has been added.
Call get_cur_time() has been added.
* Revert to using the saved current time value.
* Useless check has been removed.
* fix new path to custom-mutators
* ensure crashes/README.txt exists
* fix
* Changes to bump FRIDA version and to clone FRIDA repo in to build directory rather than use a submodule as the FRIDA build scripts don't like it (#906)
Co-authored-by: Your Name <you@example.com>
* Fix numeric overflow in cmplog implementation (#907)
Co-authored-by: Your Name <you@example.com>
* testcase fixes for unicorn
* remove merge conflict artifacts
* fix afl-plot
* Changes to remove binaries from frida_mode (#913)
Co-authored-by: Your Name <you@example.com>
* Frida cmplog fail fast (#914)
* Changes to remove binaries from frida_mode
* Changes to make cmplog fail fast
Co-authored-by: Your Name <you@example.com>
* afl-plot: relative time
* arch linux and mac os support for afl-system-config
* typo
* code-format
* update documentation
Co-authored-by: Dominik Maier <domenukk@gmail.com>
Co-authored-by: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com>
Co-authored-by: Your Name <you@example.com>
Co-authored-by: Dmitry Zheregelya <zheregelya.d@gmail.com>
Co-authored-by: hexcoder <hexcoder-@users.noreply.github.com>
Co-authored-by: hexcoder- <heiko@hexco.de>
Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
Co-authored-by: David CARLIER <devnexen@gmail.com>
Co-authored-by: realmadsci <71108352+realmadsci@users.noreply.github.com>
Co-authored-by: Roman M. Iudichev <SecNotice@ya.ru>
Diffstat (limited to 'frida_mode/src/instrument')
| -rw-r--r-- | frida_mode/src/instrument/instrument.c | 155 | ||||
| -rw-r--r-- | frida_mode/src/instrument/instrument_arm32.c | 23 | ||||
| -rw-r--r-- | frida_mode/src/instrument/instrument_arm64.c | 97 | ||||
| -rw-r--r-- | frida_mode/src/instrument/instrument_x64.c | 93 | ||||
| -rw-r--r-- | frida_mode/src/instrument/instrument_x86.c | 23 |
5 files changed, 391 insertions, 0 deletions
diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c new file mode 100644 index 00000000..971f80c0 --- /dev/null +++ b/frida_mode/src/instrument/instrument.c @@ -0,0 +1,155 @@ +#include <unistd.h> + +#include "frida-gum.h" + +#include "config.h" +#include "debug.h" + +#include "entry.h" +#include "frida_cmplog.h" +#include "instrument.h" +#include "persistent.h" +#include "prefetch.h" +#include "ranges.h" +#include "stalker.h" +#include "util.h" + +static gboolean tracing = false; +static gboolean optimize = false; +static GumStalkerTransformer *transformer = NULL; + +__thread uint64_t previous_pc = 0; + +__attribute__((hot)) static void on_basic_block(GumCpuContext *context, + gpointer user_data) { + + UNUSED_PARAMETER(context); + /* + * This function is performance critical as it is called to instrument every + * basic block. By moving our print buffer to a global, we avoid it affecting + * the critical path with additional stack adjustments if tracing is not + * enabled. If tracing is enabled, then we're printing a load of diagnostic + * information so this overhead is unlikely to be noticeable. + */ + static char buffer[200]; + int len; + guint64 current_pc = (guint64)user_data; + uint8_t * cursor; + uint64_t value; + if (unlikely(tracing)) { + + /* Avoid any functions which may cause an allocation since the target app + * may already be running inside malloc and it isn't designed to be + * re-entrant on a single thread */ + len = snprintf(buffer, sizeof(buffer), + "current_pc: 0x%016" G_GINT64_MODIFIER + "x, previous_pc: 0x%016" G_GINT64_MODIFIER "x\n", + current_pc, previous_pc); + + IGNORED_RERURN(write(STDOUT_FILENO, buffer, len + 1)); + + } + + current_pc = (current_pc >> 4) ^ (current_pc << 8); + current_pc &= MAP_SIZE - 1; + + cursor = &__afl_area_ptr[current_pc ^ previous_pc]; + value = *cursor; + + if (value == 0xff) { + + value = 1; + + } else { + + value++; + + } + + *cursor = value; + previous_pc = current_pc >> 1; + +} + +static void instr_basic_block(GumStalkerIterator *iterator, + GumStalkerOutput *output, gpointer user_data) { + + UNUSED_PARAMETER(user_data); + + const cs_insn *instr; + gboolean begin = TRUE; + while (gum_stalker_iterator_next(iterator, &instr)) { + + if (instr->address == entry_start) { entry_prologue(iterator, output); } + if (instr->address == persistent_start) { persistent_prologue(output); } + + if (begin) { + + prefetch_write((void *)instr->address); + if (!range_is_excluded((void *)instr->address)) { + + if (optimize) { + + instrument_coverage_optimize(instr, output); + + } else { + + gum_stalker_iterator_put_callout(iterator, on_basic_block, + (gpointer)instr->address, NULL); + + } + + } + + begin = FALSE; + + } + + if (!range_is_excluded((void *)instr->address)) { + + cmplog_instrument(instr, iterator); + + } + + gum_stalker_iterator_keep(iterator); + + } + +} + +void instrument_init(void) { + + optimize = (getenv("AFL_FRIDA_INST_NO_OPTIMIZE") == NULL); + tracing = (getenv("AFL_FRIDA_INST_TRACE") != NULL); + + if (!instrument_is_coverage_optimize_supported()) optimize = false; + + OKF("Instrumentation - optimize [%c]", optimize ? 'X' : ' '); + OKF("Instrumentation - tracing [%c]", tracing ? 'X' : ' '); + + if (tracing && optimize) { + + FATAL("AFL_FRIDA_INST_OPTIMIZE and AFL_FRIDA_INST_TRACE are incompatible"); + + } + + if (__afl_map_size != 0x10000) { + + FATAL("Bad map size: 0x%08x", __afl_map_size); + + } + + transformer = + gum_stalker_transformer_make_from_callback(instr_basic_block, NULL, NULL); + + cmplog_init(); + +} + +GumStalkerTransformer *instrument_get_transformer(void) { + + if (transformer == NULL) { FATAL("Instrumentation not initialized"); } + return transformer; + +} + diff --git a/frida_mode/src/instrument/instrument_arm32.c b/frida_mode/src/instrument/instrument_arm32.c new file mode 100644 index 00000000..c2d720a7 --- /dev/null +++ b/frida_mode/src/instrument/instrument_arm32.c @@ -0,0 +1,23 @@ +#include "frida-gum.h" + +#include "debug.h" + +#include "instrument.h" + +#if defined(__arm__) + +gboolean instrument_is_coverage_optimize_supported(void) { + + return false; + +} + +void instrument_coverage_optimize(const cs_insn * instr, + GumStalkerOutput *output) { + + FATAL("Optimized coverage not supported on this architecture"); + +} + +#endif + diff --git a/frida_mode/src/instrument/instrument_arm64.c b/frida_mode/src/instrument/instrument_arm64.c new file mode 100644 index 00000000..fa3afb48 --- /dev/null +++ b/frida_mode/src/instrument/instrument_arm64.c @@ -0,0 +1,97 @@ +#include "frida-gum.h" + +#include "config.h" +#include "debug.h" + +#include "instrument.h" + +#if defined(__aarch64__) + +static GumAddress current_log_impl = GUM_ADDRESS(0); + +static const guint8 afl_log_code[] = { + + // __afl_area_ptr[current_pc ^ previous_pc]++; + // previous_pc = current_pc >> 1; + 0xE1, 0x0B, 0xBF, 0xA9, // stp x1, x2, [sp, -0x10]! + 0xE3, 0x13, 0xBF, 0xA9, // stp x3, x4, [sp, -0x10]! + + // x0 = current_pc + 0xe1, 0x01, 0x00, 0x58, // ldr x1, #0x3c, =&__afl_area_ptr + 0x21, 0x00, 0x40, 0xf9, // ldr x1, [x1] (=__afl_area_ptr) + + 0xe2, 0x01, 0x00, 0x58, // ldr x2, #0x3c, =&previous_pc + 0x42, 0x00, 0x40, 0xf9, // ldr x2, [x2] (=previous_pc) + + // __afl_area_ptr[current_pc ^ previous_pc]++; + 0x42, 0x00, 0x00, 0xca, // eor x2, x2, x0 + 0x23, 0x68, 0x62, 0xf8, // ldr x3, [x1, x2] + 0x63, 0x04, 0x00, 0x91, // add x3, x3, #1 + 0x63, 0x00, 0x1f, 0x9a, // adc x3, x3, xzr + 0x23, 0x68, 0x22, 0xf8, // str x3, [x1, x2] + + // previous_pc = current_pc >> 1; + 0xe0, 0x07, 0x40, 0x8b, // add x0, xzr, x0, LSR #1 + 0xe2, 0x00, 0x00, 0x58, // ldr x2, #0x1c, =&previous_pc + 0x40, 0x00, 0x00, 0xf9, // str x0, [x2] + + 0xE3, 0x13, 0xc1, 0xA8, // ldp x3, x4, [sp], #0x10 + 0xE1, 0x0B, 0xc1, 0xA8, // ldp x1, x2, [sp], #0x10 + 0xC0, 0x03, 0x5F, 0xD6, // ret + + // &afl_area_ptr_ptr + // &afl_prev_loc_ptr + +}; + +gboolean instrument_is_coverage_optimize_supported(void) { + + return true; + +} + +void instrument_coverage_optimize(const cs_insn * instr, + GumStalkerOutput *output) { + + guint64 current_pc = instr->address; + guint64 area_offset = (current_pc >> 4) ^ (current_pc << 8); + area_offset &= MAP_SIZE - 1; + GumArm64Writer *cw = output->writer.arm64; + + if (current_log_impl == 0 || + !gum_arm64_writer_can_branch_directly_between(cw, cw->pc, + current_log_impl) || + !gum_arm64_writer_can_branch_directly_between(cw, cw->pc + 128, + current_log_impl)) { + + gconstpointer after_log_impl = cw->code + 1; + + gum_arm64_writer_put_b_label(cw, after_log_impl); + + current_log_impl = cw->pc; + gum_arm64_writer_put_bytes(cw, afl_log_code, sizeof(afl_log_code)); + + uint8_t **afl_area_ptr_ptr = &__afl_area_ptr; + uint64_t *afl_prev_loc_ptr = &previous_pc; + gum_arm64_writer_put_bytes(cw, (const guint8 *)&afl_area_ptr_ptr, + sizeof(afl_area_ptr_ptr)); + gum_arm64_writer_put_bytes(cw, (const guint8 *)&afl_prev_loc_ptr, + sizeof(afl_prev_loc_ptr)); + + gum_arm64_writer_put_label(cw, after_log_impl); + + } + + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_LR, ARM64_REG_X0, ARM64_REG_SP, -(16 + GUM_RED_ZONE_SIZE), + GUM_INDEX_PRE_ADJUST); + gum_arm64_writer_put_ldr_reg_u64(cw, ARM64_REG_X0, area_offset); + gum_arm64_writer_put_bl_imm(cw, current_log_impl); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_LR, ARM64_REG_X0, ARM64_REG_SP, 16 + GUM_RED_ZONE_SIZE, + GUM_INDEX_POST_ADJUST); + +} + +#endif + diff --git a/frida_mode/src/instrument/instrument_x64.c b/frida_mode/src/instrument/instrument_x64.c new file mode 100644 index 00000000..901f3bd0 --- /dev/null +++ b/frida_mode/src/instrument/instrument_x64.c @@ -0,0 +1,93 @@ +#include "frida-gum.h" + +#include "config.h" + +#include "instrument.h" + +#if defined(__x86_64__) + +static GumAddress current_log_impl = GUM_ADDRESS(0); + +static const guint8 afl_log_code[] = { + + // 0xcc, + + 0x9c, /* pushfq */ + 0x51, /* push rcx */ + 0x52, /* push rdx */ + + 0x48, 0x8b, 0x0d, 0x28, + 0x00, 0x00, 0x00, /* mov rcx, sym.&previous_pc */ + 0x48, 0x8b, 0x11, /* mov rdx, qword [rcx] */ + 0x48, 0x31, 0xfa, /* xor rdx, rdi */ + + 0x48, 0x03, 0x15, 0x13, + 0x00, 0x00, 0x00, /* add rdx, sym._afl_area_ptr_ptr */ + + 0x80, 0x02, 0x01, /* add byte ptr [rdx], 1 */ + 0x80, 0x12, 0x00, /* adc byte ptr [rdx], 0 */ + 0x48, 0xd1, 0xef, /* shr rdi, 1 */ + 0x48, 0x89, 0x39, /* mov qword [rcx], rdi */ + + 0x5a, /* pop rdx */ + 0x59, /* pop rcx */ + 0x9d, /* popfq */ + + 0xc3, /* ret */ + 0x90, 0x90, 0x90 /* nop pad */ + + /* Read-only data goes here: */ + /* uint8_t* __afl_area_ptr */ + /* uint64_t* &previous_pc */ + +}; + +gboolean instrument_is_coverage_optimize_supported(void) { + + return true; + +} + +void instrument_coverage_optimize(const cs_insn * instr, + GumStalkerOutput *output) { + + guint64 current_pc = instr->address; + guint64 area_offset = (current_pc >> 4) ^ (current_pc << 8); + area_offset &= MAP_SIZE - 1; + GumX86Writer *cw = output->writer.x86; + + if (current_log_impl == 0 || + !gum_x86_writer_can_branch_directly_between(cw->pc, current_log_impl) || + !gum_x86_writer_can_branch_directly_between(cw->pc + 128, + current_log_impl)) { + + gconstpointer after_log_impl = cw->code + 1; + + gum_x86_writer_put_jmp_near_label(cw, after_log_impl); + + current_log_impl = cw->pc; + gum_x86_writer_put_bytes(cw, afl_log_code, sizeof(afl_log_code)); + + uint64_t *afl_prev_loc_ptr = &previous_pc; + gum_x86_writer_put_bytes(cw, (const guint8 *)&__afl_area_ptr, + sizeof(__afl_area_ptr)); + gum_x86_writer_put_bytes(cw, (const guint8 *)&afl_prev_loc_ptr, + sizeof(afl_prev_loc_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, area_offset); + gum_x86_writer_put_call_address(cw, 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); + +} + +#endif + diff --git a/frida_mode/src/instrument/instrument_x86.c b/frida_mode/src/instrument/instrument_x86.c new file mode 100644 index 00000000..5b8cbbba --- /dev/null +++ b/frida_mode/src/instrument/instrument_x86.c @@ -0,0 +1,23 @@ +#include "frida-gum.h" + +#include "debug.h" + +#include "instrument.h" + +#if defined(__i386__) + +gboolean instrument_is_coverage_optimize_supported(void) { + + return false; + +} + +void instrument_coverage_optimize(const cs_insn * instr, + GumStalkerOutput *output) { + + FATAL("Optimized coverage not supported on this architecture"); + +} + +#endif + |
