mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-16 20:08:07 +00:00
AFL_ENTRYPOINT instruction granularity
This commit is contained in:
@ -56,6 +56,7 @@
|
|||||||
|
|
||||||
* qbdi_mode: fuzz android native libraries via QBDI framework
|
* qbdi_mode: fuzz android native libraries via QBDI framework
|
||||||
|
|
||||||
|
* The new CmpLog instrumentation for LLVM and QEMU inspired by [Redqueen](https://www.syssec.ruhr-uni-bochum.de/media/emma/veroeffentlichungen/2018/12/17/NDSS19-Redqueen.pdf)
|
||||||
|
|
||||||
A more thorough list is available in the PATCHES file.
|
A more thorough list is available in the PATCHES file.
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
|
|||||||
- AFL_PERSISTENT_HOOK callback module for persistent QEMU
|
- AFL_PERSISTENT_HOOK callback module for persistent QEMU
|
||||||
(see examples/qemu_persistent_hook)
|
(see examples/qemu_persistent_hook)
|
||||||
- added qemu_mode/README.persistent.md documentation
|
- added qemu_mode/README.persistent.md documentation
|
||||||
|
- AFL_ENTRYPOINT noew has instruction granularity
|
||||||
- afl-cmin is now a sh script (invoking awk) instead of bash for portability
|
- afl-cmin is now a sh script (invoking awk) instead of bash for portability
|
||||||
the original script is still present as afl-cmin.bash
|
the original script is still present as afl-cmin.bash
|
||||||
- afl-showmap: -i dir option now allows processing multiple inputs using the
|
- afl-showmap: -i dir option now allows processing multiple inputs using the
|
||||||
|
@ -66,8 +66,7 @@ the deferred initialization.
|
|||||||
This can be enabled setting the environment variable AFL_ENTRYPOINT which allows
|
This can be enabled setting the environment variable AFL_ENTRYPOINT which allows
|
||||||
to move the forkserver to a different part, e.g. just before the file is
|
to move the forkserver to a different part, e.g. just before the file is
|
||||||
opened (e.g. way after command line parsing and config file loading, etc.)
|
opened (e.g. way after command line parsing and config file loading, etc.)
|
||||||
which can be a huge speed improvement. Note that the specified address
|
which can be a huge speed improvement.
|
||||||
must be an address of a basic block.
|
|
||||||
|
|
||||||
## 4) Bonus feature #2: persistent mode
|
## 4) Bonus feature #2: persistent mode
|
||||||
|
|
||||||
|
@ -158,6 +158,9 @@ patch -p1 <../patches/i386-ops_sse.diff || exit 1
|
|||||||
patch -p1 <../patches/i386-fpu_helper.diff || exit 1
|
patch -p1 <../patches/i386-fpu_helper.diff || exit 1
|
||||||
patch -p1 <../patches/softfloat.diff || exit 1
|
patch -p1 <../patches/softfloat.diff || exit 1
|
||||||
patch -p1 <../patches/configure.diff || exit 1
|
patch -p1 <../patches/configure.diff || exit 1
|
||||||
|
patch -p1 <../patches/tcg-runtime.diff || exit 1
|
||||||
|
patch -p1 <../patches/tcg-runtime-head.diff || exit 1
|
||||||
|
patch -p1 <../patches/translator.diff || exit 1
|
||||||
|
|
||||||
echo "[+] Patching done."
|
echo "[+] Patching done."
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ typedef void (*afl_persistent_hook_fn)(uint64_t *regs, uint64_t guest_base);
|
|||||||
|
|
||||||
extern unsigned char *afl_area_ptr;
|
extern unsigned char *afl_area_ptr;
|
||||||
extern unsigned int afl_inst_rms;
|
extern unsigned int afl_inst_rms;
|
||||||
extern abi_ulong afl_start_code, afl_end_code;
|
extern abi_ulong afl_entry_point, afl_start_code, afl_end_code;
|
||||||
extern abi_ulong afl_persistent_addr;
|
extern abi_ulong afl_persistent_addr;
|
||||||
extern abi_ulong afl_persistent_ret_addr;
|
extern abi_ulong afl_persistent_ret_addr;
|
||||||
extern u8 afl_compcov_level;
|
extern u8 afl_compcov_level;
|
||||||
@ -88,6 +88,9 @@ extern __thread abi_ulong afl_prev_loc;
|
|||||||
extern struct cmp_map *__afl_cmp_map;
|
extern struct cmp_map *__afl_cmp_map;
|
||||||
extern __thread u32 __afl_cmp_counter;
|
extern __thread u32 __afl_cmp_counter;
|
||||||
|
|
||||||
|
void afl_setup(void);
|
||||||
|
void afl_forkserver(CPUState *cpu);
|
||||||
|
|
||||||
void afl_debug_dump_saved_regs();
|
void afl_debug_dump_saved_regs();
|
||||||
|
|
||||||
void afl_persistent_loop();
|
void afl_persistent_loop();
|
||||||
|
@ -42,22 +42,6 @@
|
|||||||
* VARIOUS AUXILIARY STUFF *
|
* VARIOUS AUXILIARY STUFF *
|
||||||
***************************/
|
***************************/
|
||||||
|
|
||||||
/* This snippet kicks in when the instruction pointer is positioned at
|
|
||||||
_start and does the usual forkserver stuff, not very different from
|
|
||||||
regular instrumentation injected via afl-as.h. */
|
|
||||||
|
|
||||||
#define AFL_QEMU_CPU_SNIPPET2 \
|
|
||||||
do { \
|
|
||||||
\
|
|
||||||
if (itb->pc == afl_entry_point) { \
|
|
||||||
\
|
|
||||||
afl_setup(); \
|
|
||||||
afl_forkserver(cpu); \
|
|
||||||
\
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/* We use one additional file descriptor to relay "needs translation"
|
/* We use one additional file descriptor to relay "needs translation"
|
||||||
messages between the child and the fork server. */
|
messages between the child and the fork server. */
|
||||||
|
|
||||||
@ -107,9 +91,6 @@ unsigned int afl_inst_rms = MAP_SIZE; /* Exported for afl_gen_trace */
|
|||||||
|
|
||||||
/* Function declarations. */
|
/* Function declarations. */
|
||||||
|
|
||||||
static void afl_setup(void);
|
|
||||||
static void afl_forkserver(CPUState *);
|
|
||||||
|
|
||||||
static void afl_wait_tsl(CPUState *, int);
|
static void afl_wait_tsl(CPUState *, int);
|
||||||
static void afl_request_tsl(target_ulong, target_ulong, uint32_t, uint32_t,
|
static void afl_request_tsl(target_ulong, target_ulong, uint32_t, uint32_t,
|
||||||
TranslationBlock *, int);
|
TranslationBlock *, int);
|
||||||
@ -155,7 +136,7 @@ static inline void tb_add_jump(TranslationBlock *tb, int n,
|
|||||||
|
|
||||||
/* Set up SHM region and initialize other stuff. */
|
/* Set up SHM region and initialize other stuff. */
|
||||||
|
|
||||||
static void afl_setup(void) {
|
void afl_setup(void) {
|
||||||
|
|
||||||
char *id_str = getenv(SHM_ENV_VAR), *inst_r = getenv("AFL_INST_RATIO");
|
char *id_str = getenv(SHM_ENV_VAR), *inst_r = getenv("AFL_INST_RATIO");
|
||||||
|
|
||||||
@ -310,7 +291,7 @@ static void print_mappings(void) {
|
|||||||
|
|
||||||
/* Fork server logic, invoked once we hit _start. */
|
/* Fork server logic, invoked once we hit _start. */
|
||||||
|
|
||||||
static void afl_forkserver(CPUState *cpu) {
|
void afl_forkserver(CPUState *cpu) {
|
||||||
|
|
||||||
static unsigned char tmp[4];
|
static unsigned char tmp[4];
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
|
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
|
||||||
index 870027d4..841ba557 100644
|
index 870027d4..0bc87dfc 100644
|
||||||
--- a/accel/tcg/cpu-exec.c
|
--- a/accel/tcg/cpu-exec.c
|
||||||
+++ b/accel/tcg/cpu-exec.c
|
+++ b/accel/tcg/cpu-exec.c
|
||||||
@@ -36,6 +36,8 @@
|
@@ -36,6 +36,8 @@
|
||||||
@ -11,16 +11,7 @@ index 870027d4..841ba557 100644
|
|||||||
/* -icount align implementation. */
|
/* -icount align implementation. */
|
||||||
|
|
||||||
typedef struct SyncClocks {
|
typedef struct SyncClocks {
|
||||||
@@ -144,6 +146,8 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, TranslationBlock *itb)
|
@@ -397,11 +399,13 @@ static inline TranslationBlock *tb_find(CPUState *cpu,
|
||||||
int tb_exit;
|
|
||||||
uint8_t *tb_ptr = itb->tc.ptr;
|
|
||||||
|
|
||||||
+ AFL_QEMU_CPU_SNIPPET2;
|
|
||||||
+
|
|
||||||
qemu_log_mask_and_addr(CPU_LOG_EXEC, itb->pc,
|
|
||||||
"Trace %d: %p ["
|
|
||||||
TARGET_FMT_lx "/" TARGET_FMT_lx "/%#x] %s\n",
|
|
||||||
@@ -397,11 +401,13 @@ static inline TranslationBlock *tb_find(CPUState *cpu,
|
|
||||||
TranslationBlock *tb;
|
TranslationBlock *tb;
|
||||||
target_ulong cs_base, pc;
|
target_ulong cs_base, pc;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
@ -34,7 +25,7 @@ index 870027d4..841ba557 100644
|
|||||||
mmap_unlock();
|
mmap_unlock();
|
||||||
/* We add the TB in the virtual pc hash table for the fast lookup */
|
/* We add the TB in the virtual pc hash table for the fast lookup */
|
||||||
atomic_set(&cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)], tb);
|
atomic_set(&cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)], tb);
|
||||||
@@ -418,6 +424,10 @@ static inline TranslationBlock *tb_find(CPUState *cpu,
|
@@ -418,6 +422,10 @@ static inline TranslationBlock *tb_find(CPUState *cpu,
|
||||||
/* See if we can patch the calling TB. */
|
/* See if we can patch the calling TB. */
|
||||||
if (last_tb) {
|
if (last_tb) {
|
||||||
tb_add_jump(last_tb, tb_exit, tb);
|
tb_add_jump(last_tb, tb_exit, tb);
|
||||||
|
10
qemu_mode/patches/tcg-runtime-head.diff
Normal file
10
qemu_mode/patches/tcg-runtime-head.diff
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
diff --git a/accel/tcg/tcg-runtime.h b/accel/tcg/tcg-runtime.h
|
||||||
|
index 1bd39d13..944997ee 100644
|
||||||
|
--- a/accel/tcg/tcg-runtime.h
|
||||||
|
+++ b/accel/tcg/tcg-runtime.h
|
||||||
|
@@ -260,3 +260,5 @@ DEF_HELPER_FLAGS_4(gvec_leu8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||||
|
DEF_HELPER_FLAGS_4(gvec_leu16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||||
|
DEF_HELPER_FLAGS_4(gvec_leu32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||||
|
DEF_HELPER_FLAGS_4(gvec_leu64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||||
|
+
|
||||||
|
+DEF_HELPER_FLAGS_1(afl_entry_routine, TCG_CALL_NO_RWG, void, env)
|
24
qemu_mode/patches/tcg-runtime.diff
Normal file
24
qemu_mode/patches/tcg-runtime.diff
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
diff --git a/accel/tcg/tcg-runtime.c b/accel/tcg/tcg-runtime.c
|
||||||
|
index d0d44844..46154af1 100644
|
||||||
|
--- a/accel/tcg/tcg-runtime.c
|
||||||
|
+++ b/accel/tcg/tcg-runtime.c
|
||||||
|
@@ -31,6 +31,8 @@
|
||||||
|
#include "disas/disas.h"
|
||||||
|
#include "exec/log.h"
|
||||||
|
|
||||||
|
+#include "../../../patches/afl-qemu-common.h"
|
||||||
|
+
|
||||||
|
/* 32-bit helpers */
|
||||||
|
|
||||||
|
int32_t HELPER(div_i32)(int32_t arg1, int32_t arg2)
|
||||||
|
@@ -167,3 +169,10 @@ void HELPER(exit_atomic)(CPUArchState *env)
|
||||||
|
{
|
||||||
|
cpu_loop_exit_atomic(ENV_GET_CPU(env), GETPC());
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+void HELPER(afl_entry_routine)(CPUArchState *env) {
|
||||||
|
+
|
||||||
|
+ afl_forkserver(ENV_GET_CPU(env));
|
||||||
|
+
|
||||||
|
+}
|
25
qemu_mode/patches/translator.diff
Normal file
25
qemu_mode/patches/translator.diff
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
|
||||||
|
index afd0a49e..773ea712 100644
|
||||||
|
--- a/accel/tcg/translator.c
|
||||||
|
+++ b/accel/tcg/translator.c
|
||||||
|
@@ -18,6 +18,8 @@
|
||||||
|
#include "exec/log.h"
|
||||||
|
#include "exec/translator.h"
|
||||||
|
|
||||||
|
+#include "../../../patches/afl-qemu-common.h"
|
||||||
|
+
|
||||||
|
/* Pairs with tcg_clear_temp_count.
|
||||||
|
To be called by #TranslatorOps.{translate_insn,tb_stop} if
|
||||||
|
(1) the target is sufficiently clean to support reporting,
|
||||||
|
@@ -92,6 +94,11 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ if (db->pc_next == afl_entry_point) {
|
||||||
|
+ afl_setup();
|
||||||
|
+ gen_helper_afl_entry_routine(cpu_env);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/* Disassemble one instruction. The translate_insn hook should
|
||||||
|
update db->pc_next and db->is_jmp to indicate what should be
|
Reference in New Issue
Block a user