diff options
author | Subhojeet Mukherjee, PhD <subhojeet.m@gmail.com> | 2024-07-01 05:43:45 +0000 |
---|---|---|
committer | Subhojeet Mukherjee, PhD <subhojeet.m@gmail.com> | 2024-07-01 05:52:06 +0000 |
commit | b169629dbd1cd0b78b541c7fa8eccf6a6a7394b1 (patch) | |
tree | 4a1108a4ffe96db28a31b5fcda1b49c65c806551 /qemu_mode/hooking_bridge/src/patching.c | |
parent | a7f928ac31bd75d91f93631790d95a86d13e134f (diff) | |
download | afl++-b169629dbd1cd0b78b541c7fa8eccf6a6a7394b1.tar.gz |
Fresh commit with all -- post revertion due to unicornafl update
Diffstat (limited to 'qemu_mode/hooking_bridge/src/patching.c')
-rw-r--r-- | qemu_mode/hooking_bridge/src/patching.c | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/qemu_mode/hooking_bridge/src/patching.c b/qemu_mode/hooking_bridge/src/patching.c new file mode 100644 index 00000000..123ad99d --- /dev/null +++ b/qemu_mode/hooking_bridge/src/patching.c @@ -0,0 +1,173 @@ +#include <stdlib.h> +#include <stdio.h> +#include <dlfcn.h> +#include <glib.h> +#include "common.h" +#include "exports.h" + +void *handle; +struct conf *config; +struct conf *(*configure)(); +GByteArray *out; +void *cpu; +char cbuf[100]; + +// region GDB Imports +#pragma region GDB Imports +void cpu_single_step(void *cpu, int enabled); +int get_sstep_flags(void); +void gdb_accept_init(int fd); +int gdb_breakpoint_insert(int type, unsigned long long addr, + unsigned long long len); +int gdb_breakpoint_remove(int type, unsigned long long addr, + unsigned long long len); +void *qemu_get_cpu(int index); +int target_memory_rw_debug(void *cpu, unsigned long long addr, void *ptr, + unsigned long long len, char is_write); +int gdb_read_register(void *cs, GByteArray *mem_buf, int n); +int gdb_write_register(void *cs, char *mem_buf, int n); +void gdb_set_cpu_pc(unsigned long long pc); +void gdb_continue(void); +#pragma endregion GDB Imports + +// region API +int r_mem(unsigned long long addr, unsigned long long len, void *dest) { + + return target_memory_rw_debug(cpu, addr, dest, len, 0); + +} + +int w_mem(unsigned long long addr, unsigned long long len, void *src) { + + return target_memory_rw_debug(cpu, addr, src, len, 1); + +} + +int r_reg(unsigned char reg, void *dest) { + + g_byte_array_steal(out, NULL); + int op = gdb_read_register(cpu, out, reg); + memcpy(dest, out->data, out->len); + return op; + +} + +int w_reg(unsigned char reg, char *src) { + + return gdb_write_register(cpu, src, reg); + +} + +// region Breakpoint handling +char single_stepped; +unsigned long long gen_addr; +struct ret *(*hook)(); +struct ret *returned; +// Defined and imported gdbstub.c +void set_signal_callback(void (*cb)(int)); +// Breakpoints are set here +void patch_block_trans_cb(struct qemu_plugin_tb *tb) { + + unsigned long long addr; + addr = qemu_plugin_tb_vaddr(tb); + + if (addr == config->entry_addr) { + + // NOTE This means we cannot put a BP in the first basic block + gdb_accept_init(-1); + for (int i = 0; i < config->num_hooks; i++) { + + gdb_breakpoint_insert(0, config->hooks[i], 1); + + } + + } + +} + +void handle_signal_callback(int sig) { + + if (single_stepped) { + + single_stepped = 0; + gdb_breakpoint_insert(0, gen_addr, 1); + cpu_single_step(cpu, 0); + gdb_continue(); + return; + + } + + r_reg(config->IP_reg_num, cbuf); + gen_addr = *(unsigned long long *)cbuf; + + sprintf(cbuf, "hook_%016llx", gen_addr); + // TODO maybe find a way to put the hook function pointers in the TCG data + // structure instead of this dlsym call + *(unsigned long long **)(&hook) = dlsym(handle, cbuf); + if (!hook) { + + exit(-1); + + } + + returned = hook(); + + if (returned->remove_bp || + (returned->addr == + gen_addr)) { //* force removal of bp in returning to the same address, + //otherwise hook will be called again + gdb_breakpoint_remove(0, gen_addr, 1); + + } + + if (returned->addr == gen_addr) { + + single_stepped = 1; + cpu_single_step(cpu, get_sstep_flags()); + + } else { + + //* no need to rexecute the IP instruction + gdb_set_cpu_pc(returned->addr); + + } + + gdb_continue(); + +} + +// region Constructor/Destructor +void patch_finish_cb(void *userdata) { + + g_byte_array_free(out, 1); + dlclose(handle); + +} + +void patch_vpu_init_cb(unsigned int vcpu_index) { + + cpu = qemu_get_cpu(vcpu_index); + +} + +void patch_init(char *hook_lib) { + + // TODO make OS agnostic, remove dlopen + handle = dlopen(hook_lib, RTLD_NOW); + if (!handle) { + + fprintf(stderr, "DLOPEN Error: %s\n", dlerror()); + exit(-1); + + } + + single_stepped = 0; + + *(void **)(&configure) = dlsym(handle, "configure"); + config = configure(); + + set_signal_callback(handle_signal_callback); + out = g_byte_array_new(); + +} + |