mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-14 11:08:06 +00:00
shared mem input for qemu persistent hook
This commit is contained in:
@ -35,16 +35,25 @@ enum {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void afl_persistent_hook(uint64_t *regs, uint64_t guest_base) {
|
void afl_persistent_hook(uint64_t *regs, uint64_t guest_base,
|
||||||
|
uint8_t* input_buf, uint32_t input_len) {
|
||||||
|
|
||||||
// In this example the register RDI is pointing to the memory location
|
// In this example the register RDI is pointing to the memory location
|
||||||
// of the target buffer, and the length of the input is in RSI.
|
// of the target buffer, and the length of the input is in RSI.
|
||||||
// This can be seen with a debugger, e.g. gdb (and "disass main")
|
// This can be seen with a debugger, e.g. gdb (and "disass main")
|
||||||
|
|
||||||
printf("reading into %p\n", regs[R_EDI]);
|
printf("placing input into %p\n", regs[R_EDI]);
|
||||||
size_t r = read(0, g2h(regs[R_EDI]), 1024);
|
|
||||||
regs[R_ESI] = r;
|
if (input_len > 1024)
|
||||||
printf("read %ld bytes\n", r);
|
input_len = 1024;
|
||||||
|
memcpy(g2h(regs[R_EDI]), input_buf, input_len);
|
||||||
|
regs[R_ESI] = input_len;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int afl_persistent_hook_init(void) {
|
||||||
|
|
||||||
|
// 1 for shared memory input (faster), 0 for normal input (you have to use read(), input_buf will be NULL)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -63,7 +63,10 @@
|
|||||||
#define INC_AFL_AREA(loc) afl_area_ptr[loc]++
|
#define INC_AFL_AREA(loc) afl_area_ptr[loc]++
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef void (*afl_persistent_hook_fn)(uint64_t *regs, uint64_t guest_base);
|
typedef void (*afl_persistent_hook_fn)(uint64_t *regs,
|
||||||
|
uint64_t guest_base,
|
||||||
|
uint8_t* input_buf,
|
||||||
|
uint32_t input_buf_len);
|
||||||
|
|
||||||
/* Declared in afl-qemu-cpu-inl.h */
|
/* Declared in afl-qemu-cpu-inl.h */
|
||||||
|
|
||||||
@ -81,6 +84,10 @@ extern unsigned char persistent_save_gpr;
|
|||||||
extern uint64_t persistent_saved_gpr[AFL_REGS_NUM];
|
extern uint64_t persistent_saved_gpr[AFL_REGS_NUM];
|
||||||
extern int persisent_retaddr_offset;
|
extern int persisent_retaddr_offset;
|
||||||
|
|
||||||
|
extern u8 *shared_buf;
|
||||||
|
extern u32 shared_buf_len;
|
||||||
|
extern u8 sharedmem_fuzzing;
|
||||||
|
|
||||||
extern afl_persistent_hook_fn afl_persistent_hook_ptr;
|
extern afl_persistent_hook_fn afl_persistent_hook_ptr;
|
||||||
|
|
||||||
extern __thread abi_ulong afl_prev_loc;
|
extern __thread abi_ulong afl_prev_loc;
|
||||||
|
@ -83,6 +83,10 @@ unsigned char persistent_save_gpr;
|
|||||||
uint64_t persistent_saved_gpr[AFL_REGS_NUM];
|
uint64_t persistent_saved_gpr[AFL_REGS_NUM];
|
||||||
int persisent_retaddr_offset;
|
int persisent_retaddr_offset;
|
||||||
|
|
||||||
|
u8 *shared_buf;
|
||||||
|
u32 shared_buf_len;
|
||||||
|
u8 sharedmem_fuzzing;
|
||||||
|
|
||||||
afl_persistent_hook_fn afl_persistent_hook_ptr;
|
afl_persistent_hook_fn afl_persistent_hook_ptr;
|
||||||
|
|
||||||
/* Instrumentation ratio: */
|
/* Instrumentation ratio: */
|
||||||
@ -128,6 +132,7 @@ static inline TranslationBlock *tb_find(CPUState *, TranslationBlock *, int,
|
|||||||
static inline void tb_add_jump(TranslationBlock *tb, int n,
|
static inline void tb_add_jump(TranslationBlock *tb, int n,
|
||||||
TranslationBlock *tb_next);
|
TranslationBlock *tb_next);
|
||||||
int open_self_maps(void *cpu_env, int fd);
|
int open_self_maps(void *cpu_env, int fd);
|
||||||
|
static void afl_map_shm_fuzz(void);
|
||||||
|
|
||||||
/*************************
|
/*************************
|
||||||
* ACTUAL IMPLEMENTATION *
|
* ACTUAL IMPLEMENTATION *
|
||||||
@ -135,6 +140,36 @@ int open_self_maps(void *cpu_env, int fd);
|
|||||||
|
|
||||||
/* Set up SHM region and initialize other stuff. */
|
/* Set up SHM region and initialize other stuff. */
|
||||||
|
|
||||||
|
static void afl_map_shm_fuzz(void) {
|
||||||
|
|
||||||
|
char *id_str = getenv(SHM_FUZZ_ENV_VAR);
|
||||||
|
|
||||||
|
if (id_str) {
|
||||||
|
|
||||||
|
u32 shm_id = atoi(id_str);
|
||||||
|
shared_buf = shmat(shm_id, NULL, 0);
|
||||||
|
|
||||||
|
/* Whooooops. */
|
||||||
|
|
||||||
|
if (shared_buf == (void *)-1) {
|
||||||
|
|
||||||
|
fprintf(stderr, "[AFL] ERROR: could not access fuzzing shared memory\n");
|
||||||
|
exit(1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getenv("AFL_DEBUG"))
|
||||||
|
fprintf(stderr, "[AFL] DEBUG: successfully got fuzzing shared memory\n");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
fprintf(stderr, "[AFL] ERROR: variable for fuzzing shared memory is not set\n");
|
||||||
|
exit(1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
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");
|
||||||
@ -247,6 +282,11 @@ void afl_setup(void) {
|
|||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int (*afl_persistent_hook_init_ptr)(void) = dlsym(plib,
|
||||||
|
"afl_persistent_hook_init");
|
||||||
|
if (afl_persistent_hook_init_ptr)
|
||||||
|
sharedmem_fuzzing = afl_persistent_hook_init_ptr();
|
||||||
|
|
||||||
afl_persistent_hook_ptr = dlsym(plib, "afl_persistent_hook");
|
afl_persistent_hook_ptr = dlsym(plib, "afl_persistent_hook");
|
||||||
if (!afl_persistent_hook_ptr) {
|
if (!afl_persistent_hook_ptr) {
|
||||||
@ -262,7 +302,7 @@ void afl_setup(void) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getenv("AFL_QEMU_PERSISTENT_RETADDR_OFFSET"))
|
if (getenv("AFL_QEMU_PERSISTENT_RETADDR_OFFSET"))
|
||||||
persisent_retaddr_offset =
|
persisent_retaddr_offset =
|
||||||
strtoll(getenv("AFL_QEMU_PERSISTENT_RETADDR_OFFSET"), NULL, 0);
|
strtoll(getenv("AFL_QEMU_PERSISTENT_RETADDR_OFFSET"), NULL, 0);
|
||||||
@ -278,7 +318,7 @@ void afl_setup(void) {
|
|||||||
|
|
||||||
void afl_forkserver(CPUState *cpu) {
|
void afl_forkserver(CPUState *cpu) {
|
||||||
|
|
||||||
u32 map_size = 0;
|
//u32 map_size = 0;
|
||||||
unsigned char tmp[4] = {0};
|
unsigned char tmp[4] = {0};
|
||||||
|
|
||||||
if (forkserver_installed == 1) return;
|
if (forkserver_installed == 1) return;
|
||||||
@ -291,15 +331,15 @@ void afl_forkserver(CPUState *cpu) {
|
|||||||
pid_t child_pid;
|
pid_t child_pid;
|
||||||
int t_fd[2];
|
int t_fd[2];
|
||||||
u8 child_stopped = 0;
|
u8 child_stopped = 0;
|
||||||
|
u32 was_killed;
|
||||||
|
int status;
|
||||||
|
|
||||||
// if in the future qemu has non-collding coverage then switch MAP_SIZE
|
|
||||||
// with the max ID value
|
// with the max ID value
|
||||||
if (MAP_SIZE <= 0x800000) {
|
if (MAP_SIZE <= FS_OPT_MAX_MAPSIZE)
|
||||||
|
status |= (FS_OPT_SET_MAPSIZE(MAP_SIZE) | FS_OPT_MAPSIZE);
|
||||||
map_size = (FS_OPT_ENABLED | FS_OPT_MAPSIZE | FS_OPT_SET_MAPSIZE(MAP_SIZE));
|
if (sharedmem_fuzzing != 0) status |= FS_OPT_SHDMEM_FUZZ;
|
||||||
memcpy(tmp, &map_size, 4);
|
if (status) status |= (FS_OPT_ENABLED);
|
||||||
|
memcpy(tmp, &status, 4);
|
||||||
}
|
|
||||||
|
|
||||||
/* Tell the parent that we're alive. If the parent doesn't want
|
/* Tell the parent that we're alive. If the parent doesn't want
|
||||||
to talk, assume that we're not running in forkserver mode. */
|
to talk, assume that we're not running in forkserver mode. */
|
||||||
@ -309,17 +349,34 @@ void afl_forkserver(CPUState *cpu) {
|
|||||||
afl_forksrv_pid = getpid();
|
afl_forksrv_pid = getpid();
|
||||||
|
|
||||||
int first_run = 1;
|
int first_run = 1;
|
||||||
|
|
||||||
|
if (sharedmem_fuzzing) {
|
||||||
|
|
||||||
|
if (read(FORKSRV_FD, &was_killed, 4) != 4) exit(2);
|
||||||
|
|
||||||
|
if ((was_killed & (0xffffffff & (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ))) ==
|
||||||
|
(FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ))
|
||||||
|
afl_map_shm_fuzz();
|
||||||
|
else {
|
||||||
|
|
||||||
|
fprintf(stderr, "[AFL] ERROR: afl-fuzz is old and does not support"
|
||||||
|
" shmem input");
|
||||||
|
exit(1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* All right, let's await orders... */
|
/* All right, let's await orders... */
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
int status;
|
|
||||||
u32 was_killed;
|
|
||||||
|
|
||||||
/* Whoops, parent dead? */
|
/* Whoops, parent dead? */
|
||||||
|
|
||||||
if (read(FORKSRV_FD, &was_killed, 4) != 4) exit(2);
|
if (read(FORKSRV_FD, &was_killed, 4) != 4) exit(2);
|
||||||
|
|
||||||
|
shared_buf_len = (was_killed >> 8);
|
||||||
|
was_killed = (was_killed & 0xff);
|
||||||
|
|
||||||
/* If we stopped the child in persistent mode, but there was a race
|
/* If we stopped the child in persistent mode, but there was a race
|
||||||
condition and afl-fuzz already issued SIGKILL, write off the old
|
condition and afl-fuzz already issued SIGKILL, write off the old
|
||||||
@ -402,6 +459,7 @@ void afl_forkserver(CPUState *cpu) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* A simplified persistent mode handler, used as explained in
|
/* A simplified persistent mode handler, used as explained in
|
||||||
* llvm_mode/README.md. */
|
* llvm_mode/README.md. */
|
||||||
|
|
||||||
|
@ -161,7 +161,8 @@ static void log_x86_sp_content(void) {
|
|||||||
|
|
||||||
static void callback_to_persistent_hook(void) {
|
static void callback_to_persistent_hook(void) {
|
||||||
|
|
||||||
afl_persistent_hook_ptr(persistent_saved_gpr, guest_base);
|
afl_persistent_hook_ptr(persistent_saved_gpr, guest_base, shared_buf,
|
||||||
|
shared_buf_len);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -556,6 +556,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
if (afl->fsrv.qemu_mode) { FATAL("Multiple -Q options not supported"); }
|
if (afl->fsrv.qemu_mode) { FATAL("Multiple -Q options not supported"); }
|
||||||
afl->fsrv.qemu_mode = 1;
|
afl->fsrv.qemu_mode = 1;
|
||||||
|
afl->shmem_testcase_mode = 1;
|
||||||
|
|
||||||
if (!mem_limit_given) { afl->fsrv.mem_limit = MEM_LIMIT_QEMU; }
|
if (!mem_limit_given) { afl->fsrv.mem_limit = MEM_LIMIT_QEMU; }
|
||||||
|
|
||||||
@ -583,6 +584,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
if (afl->use_wine) { FATAL("Multiple -W options not supported"); }
|
if (afl->use_wine) { FATAL("Multiple -W options not supported"); }
|
||||||
afl->fsrv.qemu_mode = 1;
|
afl->fsrv.qemu_mode = 1;
|
||||||
afl->use_wine = 1;
|
afl->use_wine = 1;
|
||||||
|
afl->shmem_testcase_mode = 1;
|
||||||
|
|
||||||
if (!mem_limit_given) { afl->fsrv.mem_limit = 0; }
|
if (!mem_limit_given) { afl->fsrv.mem_limit = 0; }
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user