diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 59d32d2ef1..05bf2ceec9 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -49,7 +49,7 @@ #include "nyx/hypercall/hypercall.h" #include "nyx/synchronization.h" #include "nyx/debug.h" -#include "nyx/state.h" +#include "nyx/state/state.h" #include "nyx/interface.h" #include "nyx/fast_vm_reload_sync.h" #include "nyx/snapshot/memory/backend/nyx_dirty_ring.h" @@ -2866,11 +2866,6 @@ int kvm_device_access(int fd, int group, uint64_t attr, return err; } -#ifdef QEMU_NYX -int kvm_has_vapic(void){ - return !kvm_check_extension(kvm_state, KVM_CAP_VAPIC); -} -#endif bool kvm_has_sync_mmu(void) { diff --git a/hw/char/serial.c b/hw/char/serial.c index a5034ae4ef..23737c56dd 100644 --- a/hw/char/serial.c +++ b/hw/char/serial.c @@ -35,7 +35,7 @@ #include "qemu/error-report.h" #include "trace.h" #ifdef QEMU_NYX -#include "nyx/state.h" +#include "nyx/state/state.h" #endif //#define DEBUG_SERIAL diff --git a/memory.c b/memory.c index f741b142a8..2bd35b6262 100644 --- a/memory.c +++ b/memory.c @@ -36,7 +36,7 @@ #include "migration/vmstate.h" #ifdef QEMU_NYX -#include "nyx/state.h" +#include "nyx/state/state.h" #include "nyx/fast_vm_reload.h" #endif diff --git a/nyx/Makefile.objs b/nyx/Makefile.objs index 197f9121c6..5400116161 100644 --- a/nyx/Makefile.objs +++ b/nyx/Makefile.objs @@ -3,10 +3,9 @@ memory_access.o \ interface.o \ fast_vm_reload.o \ fast_vm_reload_sync.o \ -printk.o synchronization.o \ +synchronization.o \ page_cache.o \ kvm_nested.o \ -state.o \ debug.o \ auxiliary_buffer.o \ mmh3.o \ @@ -31,5 +30,7 @@ snapshot/memory/backend/nyx_dirty_ring.o \ hypercall/hypercall.o \ hypercall/configuration.o \ hypercall/debug.o \ +state/state.o \ +state/snapshot_state.o \ pt.o diff --git a/nyx/auxiliary_buffer.c b/nyx/auxiliary_buffer.c index 72f25924a3..46e784032d 100644 --- a/nyx/auxiliary_buffer.c +++ b/nyx/auxiliary_buffer.c @@ -23,7 +23,7 @@ along with QEMU-PT. If not, see . #include #include #include -#include "nyx/state.h" +#include "nyx/state/state.h" #include "nyx/debug.h" /* experimental feature (currently broken) @@ -161,15 +161,11 @@ void check_auxiliary_config_buffer(auxilary_buffer_t* auxilary_buffer, auxilary_ } void set_crash_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer){ - VOLATILE_WRITE_8(auxilary_buffer->result.crash_found, 1); -} - -void set_asan_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer){ - VOLATILE_WRITE_8(auxilary_buffer->result.asan_found, 1); + VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_crash); } void set_timeout_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer){ - VOLATILE_WRITE_8(auxilary_buffer->result.timeout_found, 1); + VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_timeout); } void set_reload_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer){ @@ -180,65 +176,32 @@ void set_pt_overflow_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer) VOLATILE_WRITE_8(auxilary_buffer->result.pt_overflow, 1); } -void set_exec_done_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer, uint8_t sec, uint32_t usec){ +void set_exec_done_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer, uint8_t sec, uint32_t usec, uint32_t num_dirty_pages){ VOLATILE_WRITE_8(auxilary_buffer->result.exec_done, 1); - VOLATILE_WRITE_8(auxilary_buffer->result.runtime_sec, sec); + VOLATILE_WRITE_32(auxilary_buffer->result.runtime_sec, sec); VOLATILE_WRITE_32(auxilary_buffer->result.runtime_usec, usec); + VOLATILE_WRITE_32(auxilary_buffer->result.dirty_pages, num_dirty_pages); } -void flush_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer){ - memset(&auxilary_buffer->result.hprintf, 0x0, sizeof(auxilary_buffer_result_t)-2); - - - //memset(&(auxilary_buffer->result) + offsetof(auxilary_buffer_result_t, hprintf), 0x0, sizeof(auxilary_buffer_result_t) - offsetof(auxilary_buffer_result_t, hprintf)); - - /* - VOLATILE_WRITE_8(auxilary_buffer->result.exec_done, 0); - VOLATILE_WRITE_8(auxilary_buffer->result.hprintf, 0); - - - VOLATILE_WRITE_8(auxilary_buffer->result.crash_found, 0); - VOLATILE_WRITE_8(auxilary_buffer->result.asan_found, 0); - VOLATILE_WRITE_8(auxilary_buffer->result.timeout_found, 0); - VOLATILE_WRITE_8(auxilary_buffer->result.reloaded, 0); - VOLATILE_WRITE_8(auxilary_buffer->result.pt_overflow, 0); - - VOLATILE_WRITE_8(auxilary_buffer->result.runtime_sec, 0); - VOLATILE_WRITE_32(auxilary_buffer->result.runtime_usec, 0); - - VOLATILE_WRITE_8(auxilary_buffer->result.page_not_found, 0); - VOLATILE_WRITE_64(auxilary_buffer->result.page_addr, 0); - - VOLATILE_WRITE_8(auxilary_buffer->result.payload_buffer_write_attempt_found, 0); - - VOLATILE_WRITE_32(auxilary_buffer->result.dirty_pages, 0); - VOLATILE_WRITE_32(auxilary_buffer->result.pt_trace_size, 0); - */ - -} void set_hprintf_auxiliary_buffer(auxilary_buffer_t* auxilary_buffer, char* msg, uint32_t len){ VOLATILE_WRITE_16(auxilary_buffer->misc.len, MIN(len, MISC_SIZE-2)); volatile_memcpy((void*)&auxilary_buffer->misc.data, (void*)msg, (size_t)MIN(len, MISC_SIZE-2)); - VOLATILE_WRITE_8(auxilary_buffer->result.hprintf, 1); + VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_hprintf); } void set_crash_reason_auxiliary_buffer(auxilary_buffer_t* auxilary_buffer, char* msg, uint32_t len){ VOLATILE_WRITE_16(auxilary_buffer->misc.len, MIN(len, MISC_SIZE-2)); volatile_memcpy((void*)&auxilary_buffer->misc.data, (void*)msg, (size_t) MIN(len, MISC_SIZE-2)); - VOLATILE_WRITE_8(auxilary_buffer->result.crash_found, 1); + VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_crash); } void set_abort_reason_auxiliary_buffer(auxilary_buffer_t* auxilary_buffer, char* msg, uint32_t len){ VOLATILE_WRITE_16(auxilary_buffer->misc.len, MIN(len, MISC_SIZE-2)); volatile_memcpy((void*)&auxilary_buffer->misc.data, (void*)msg, (size_t) MIN(len, MISC_SIZE-2)); - VOLATILE_WRITE_8(auxilary_buffer->result.abort, 1); -} - -void flush_hprintf_auxiliary_buffer(auxilary_buffer_t* auxilary_buffer){ - VOLATILE_WRITE_8(auxilary_buffer->result.hprintf, 0); + VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_aborted); } void set_state_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer, uint8_t state){ @@ -255,14 +218,18 @@ void set_page_not_found_result_buffer(auxilary_buffer_t* auxilary_buffer, uint64 VOLATILE_WRITE_64(auxilary_buffer->result.page_addr, page_addr); } +void reset_page_not_found_result_buffer(auxilary_buffer_t* auxilary_buffer){ + VOLATILE_WRITE_8(auxilary_buffer->result.page_not_found, 0); +} + void set_success_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer, uint8_t success){ - VOLATILE_WRITE_8(auxilary_buffer->result.success, success); + VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_success); } void set_payload_buffer_write_reason_auxiliary_buffer(auxilary_buffer_t* auxilary_buffer, char* msg, uint32_t len){ VOLATILE_WRITE_16(auxilary_buffer->misc.len, MIN(len, MISC_SIZE-2)); volatile_memcpy((void*)&auxilary_buffer->misc.data, (void*)msg, (size_t) MIN(len, MISC_SIZE-2)); - VOLATILE_WRITE_8(auxilary_buffer->result.payload_buffer_write_attempt_found, 1); + VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_input_buffer_write); } diff --git a/nyx/auxiliary_buffer.h b/nyx/auxiliary_buffer.h index fbf82a637a..53edb09b2a 100644 --- a/nyx/auxiliary_buffer.h +++ b/nyx/auxiliary_buffer.h @@ -37,6 +37,15 @@ along with QEMU-PT. If not, see . #define ADD_PADDING(max, type) uint8_t type ## _padding [max - sizeof(type)] +enum nyx_result_codes { + rc_success = 0, + rc_crash = 1, + rc_hprintf = 2, + rc_timeout = 3, + rc_input_buffer_write = 4, + rc_aborted = 5, +}; + typedef struct auxilary_buffer_header_s{ uint64_t magic; /* 0x54502d554d4551 */ uint16_t version; @@ -93,40 +102,21 @@ typedef struct auxilary_buffer_result_s{ 3 -> ready to fuzz */ uint8_t state; - /* snapshot extension */ - uint8_t tmp_snapshot_created; - - /* FML */ - uint8_t padding_1; - uint8_t padding_2; - - uint32_t bb_coverage; - - uint8_t padding_3; - uint8_t padding_4; - - uint8_t hprintf; - uint8_t exec_done; - - uint8_t crash_found; - uint8_t asan_found; - - uint8_t timeout_found; + uint8_t exec_done; + uint8_t exec_result_code; uint8_t reloaded; uint8_t pt_overflow; - uint8_t runtime_sec; - uint8_t page_not_found; - uint8_t success; + uint8_t tmp_snapshot_created; /* incremental snapshot extension */ + uint8_t padding_3; - uint32_t runtime_usec; uint64_t page_addr; uint32_t dirty_pages; - uint32_t pt_trace_size; - - uint8_t payload_buffer_write_attempt_found; - uint8_t abort; + uint32_t pt_trace_size; + uint32_t bb_coverage; + uint32_t runtime_usec; + uint32_t runtime_sec; /* more to come */ } __attribute__((packed)) auxilary_buffer_result_t; @@ -158,19 +148,16 @@ typedef struct auxilary_buffer_s{ void init_auxiliary_buffer(auxilary_buffer_t* auxilary_buffer); void check_auxiliary_config_buffer(auxilary_buffer_t* auxilary_buffer, auxilary_buffer_config_t* shadow_config); -void flush_hprintf_auxiliary_buffer(auxilary_buffer_t* auxilary_buffer); - void set_crash_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer); -void set_asan_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer); void set_timeout_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer); void set_reload_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer); void set_pt_overflow_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer); -void flush_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer); -void set_exec_done_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer, uint8_t sec, uint32_t usec); +void set_exec_done_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer, uint8_t sec, uint32_t usec, uint32_t num_dirty_pages); void set_state_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer, uint8_t state); void set_hprintf_auxiliary_buffer(auxilary_buffer_t* auxilary_buffer, char* msg, uint32_t len); void set_page_not_found_result_buffer(auxilary_buffer_t* auxilary_buffer, uint64_t page_addr); +void reset_page_not_found_result_buffer(auxilary_buffer_t* auxilary_buffer); void set_success_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer, uint8_t success); void set_crash_reason_auxiliary_buffer(auxilary_buffer_t* auxilary_buffer, char* msg, uint32_t len); void set_abort_reason_auxiliary_buffer(auxilary_buffer_t* auxilary_buffer, char* msg, uint32_t len); diff --git a/nyx/fast_vm_reload.c b/nyx/fast_vm_reload.c index 50be74bb0e..6981917788 100644 --- a/nyx/fast_vm_reload.c +++ b/nyx/fast_vm_reload.c @@ -47,7 +47,8 @@ along with QEMU-PT. If not, see . #include "nyx/fast_vm_reload.h" #include "nyx/debug.h" -#include "nyx/state.h" +#include "nyx/state/state.h" +#include "nyx/state/snapshot_state.h" #include "sysemu/block-backend.h" #include "block/qapi.h" @@ -125,33 +126,36 @@ static void fast_snapshot_init_operation(fast_reload_t* self, const char* snapsh static void fast_snapshot_restore_operation(fast_reload_t* self){ + uint32_t num_dirty_pages = 0; + switch(mode){ case RELOAD_MEMORY_MODE_DEBUG: - nyx_snapshot_debug_restore(self->shadow_memory_state, self->blocklist, true); + num_dirty_pages += nyx_snapshot_debug_restore(self->shadow_memory_state, self->blocklist, true); break; case RELOAD_MEMORY_MODE_DEBUG_QUIET: - nyx_snapshot_debug_restore(self->shadow_memory_state, self->blocklist, false); + num_dirty_pages += nyx_snapshot_debug_restore(self->shadow_memory_state, self->blocklist, false); break; case RELOAD_MEMORY_MODE_FDL: - nyx_snapshot_nyx_fdl_restore(self->fdl_state, self->shadow_memory_state, self->blocklist); + num_dirty_pages += nyx_snapshot_nyx_fdl_restore(self->fdl_state, self->shadow_memory_state, self->blocklist); break; case RELOAD_MEMORY_MODE_FDL_DEBUG: - nyx_snapshot_nyx_fdl_restore(self->fdl_state, self->shadow_memory_state, self->blocklist); - nyx_snapshot_debug_restore(self->shadow_memory_state, self->blocklist, true); + num_dirty_pages += nyx_snapshot_nyx_fdl_restore(self->fdl_state, self->shadow_memory_state, self->blocklist); + num_dirty_pages += nyx_snapshot_debug_restore(self->shadow_memory_state, self->blocklist, true); break; case RELOAD_MEMORY_MODE_DIRTY_RING: - nyx_snapshot_nyx_dirty_ring_restore(self->dirty_ring_state, self->shadow_memory_state, self->blocklist); + num_dirty_pages += nyx_snapshot_nyx_dirty_ring_restore(self->dirty_ring_state, self->shadow_memory_state, self->blocklist); break; case RELOAD_MEMORY_MODE_DIRTY_RING_DEBUG: - nyx_snapshot_nyx_dirty_ring_restore(self->dirty_ring_state, self->shadow_memory_state, self->blocklist); - nyx_snapshot_debug_restore(self->shadow_memory_state, self->blocklist, true); + num_dirty_pages += nyx_snapshot_nyx_dirty_ring_restore(self->dirty_ring_state, self->shadow_memory_state, self->blocklist); + num_dirty_pages += nyx_snapshot_debug_restore(self->shadow_memory_state, self->blocklist, true); //assert(false); //sleep(1); break; } - nyx_snapshot_user_fdl_restore(self->fdl_user_state, self->shadow_memory_state, self->blocklist); + num_dirty_pages += nyx_snapshot_user_fdl_restore(self->fdl_user_state, self->shadow_memory_state, self->blocklist); //nyx_device_state_post_restore(self->device_state); + GET_GLOBAL_STATE()->num_dirty_pages = num_dirty_pages; } static inline void fast_snapshot_pre_create_incremental_operation(fast_reload_t* self){ @@ -279,7 +283,7 @@ inline static void wait_for_snapshot(const char* folder){ free(lock_file); } -void fast_reload_serialize_to_file(fast_reload_t* self, const char* folder){ +void fast_reload_serialize_to_file(fast_reload_t* self, const char* folder, bool is_pre_snapshot){ //printf("================ %s => %s =============\n", __func__, folder); @@ -299,7 +303,7 @@ void fast_reload_serialize_to_file(fast_reload_t* self, const char* folder){ nyx_block_snapshot_serialize(self->block_state, folder); /* NYX's state */ - dump_global_state(folder); + serialize_state(folder, is_pre_snapshot); /* finalize snapshot */ unlock_snapshot(folder); @@ -332,7 +336,7 @@ static void fast_reload_create_from_snapshot(fast_reload_t* self, const char* fo rcu_read_unlock(); if(!pre_snapshot){ - load_global_state(folder); + deserialize_state(folder); } cpu_synchronize_all_post_init(); @@ -480,10 +484,7 @@ void fast_reload_create_tmp_snapshot(fast_reload_t* self){ fast_snapshot_pre_create_incremental_operation(self); if(!self->bitmap_copy){ - if(GET_GLOBAL_STATE()->shared_bitmap_size+GET_GLOBAL_STATE()->shared_ijon_bitmap_size){ - assert(GET_GLOBAL_STATE()->shared_bitmap_size+GET_GLOBAL_STATE()->shared_ijon_bitmap_size); - self->bitmap_copy = malloc(GET_GLOBAL_STATE()->shared_bitmap_size+GET_GLOBAL_STATE()->shared_ijon_bitmap_size); - } + self->bitmap_copy = new_coverage_bitmaps(); } coverage_bitmap_copy_to_buffer(self->bitmap_copy); diff --git a/nyx/fast_vm_reload.h b/nyx/fast_vm_reload.h index 0c829377e4..00333c6f24 100644 --- a/nyx/fast_vm_reload.h +++ b/nyx/fast_vm_reload.h @@ -35,6 +35,7 @@ along with QEMU-PT. If not, see . #include "nyx/snapshot/block/nyx_block_snapshot.h" #include "nyx/snapshot/memory/backend/nyx_dirty_ring.h" +#include "nyx/helpers.h" typedef enum FastReloadMemoryMode { @@ -82,7 +83,7 @@ typedef struct fast_reload_s{ bool incremental_snapshot_enabled; /* copy of the fuzzing bitmap & ijon state buffer */ - void* bitmap_copy; + nyx_coverage_bitmap_copy_t* bitmap_copy; @@ -104,7 +105,7 @@ void fast_reload_create_from_file_pre_image(fast_reload_t* self, const char* fol void fast_reload_create_in_memory(fast_reload_t* self); -void fast_reload_serialize_to_file(fast_reload_t* self, const char* folder); +void fast_reload_serialize_to_file(fast_reload_t* self, const char* folder, bool is_pre_snapshot); void fast_reload_restore(fast_reload_t* self); diff --git a/nyx/fast_vm_reload_sync.c b/nyx/fast_vm_reload_sync.c index 02c93c5201..7e3780b5a8 100644 --- a/nyx/fast_vm_reload_sync.c +++ b/nyx/fast_vm_reload_sync.c @@ -11,7 +11,7 @@ #include "sysemu/kvm_int.h" #include "sysemu/kvm.h" #include "sysemu/runstate.h" -#include "nyx/state.h" +#include "nyx/state/state.h" #include "nyx/fast_vm_reload.h" #include "nyx/debug.h" #include "nyx/kvm_nested.h" @@ -127,7 +127,7 @@ static inline void create_root_snapshot(void){ debug_printf("===> GET_GLOBAL_STATE()->fast_reload_mode: FALSE\n"); /* store the current state as a snapshot folder */ fast_reload_create_in_memory(get_fast_reload_snapshot()); - fast_reload_serialize_to_file(get_fast_reload_snapshot(), GET_GLOBAL_STATE()->fast_reload_path); + fast_reload_serialize_to_file(get_fast_reload_snapshot(), GET_GLOBAL_STATE()->fast_reload_path, false); } } else{ @@ -149,7 +149,7 @@ static inline void perform_task_no_block_mode(fast_vm_reload_sync_t* self, FastR vm_stop(RUN_STATE_SAVE_VM); //fast_reload_create_to_file(get_fast_reload_snapshot(), GET_GLOBAL_STATE()->fast_reload_pre_path, true); fast_reload_create_in_memory(get_fast_reload_snapshot()); - fast_reload_serialize_to_file(get_fast_reload_snapshot(), GET_GLOBAL_STATE()->fast_reload_pre_path); + fast_reload_serialize_to_file(get_fast_reload_snapshot(), GET_GLOBAL_STATE()->fast_reload_pre_path, true); qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); qemu_mutex_unlock_iothread(); @@ -218,7 +218,7 @@ static inline void perform_task_block_mode(fast_vm_reload_sync_t* self, FastRelo vm_stop(RUN_STATE_SAVE_VM); //fast_reload_create_to_file(get_fast_reload_snapshot(), GET_GLOBAL_STATE()->fast_reload_pre_path, true); fast_reload_create_in_memory(get_fast_reload_snapshot()); - fast_reload_serialize_to_file(get_fast_reload_snapshot(), GET_GLOBAL_STATE()->fast_reload_pre_path); + fast_reload_serialize_to_file(get_fast_reload_snapshot(), GET_GLOBAL_STATE()->fast_reload_pre_path, true); qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); return; /* return here to skip the vm_start call */ case REQUEST_SAVE_SNAPSHOT_ROOT_FIX_RIP: diff --git a/nyx/helpers.c b/nyx/helpers.c index 6892a0a12b..a24be89e1c 100644 --- a/nyx/helpers.c +++ b/nyx/helpers.c @@ -10,9 +10,15 @@ #include "qemu/main-loop.h" #include "sysemu/kvm_int.h" #include "sysemu/kvm.h" -#include "nyx/state.h" +#include "nyx/state/state.h" #include "nyx/memory_access.h" #include "nyx/debug.h" +#include "nyx/helpers.h" + +void nyx_abort(char* msg){ + set_abort_reason_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer, msg, strlen(msg)); + synchronization_lock(); +} uint64_t get_rip(CPUState *cpu){ kvm_arch_get_registers(cpu); @@ -33,26 +39,49 @@ int get_capstone_mode(int word_width_in_bits){ } } +nyx_coverage_bitmap_copy_t* new_coverage_bitmaps(void){ + nyx_coverage_bitmap_copy_t* bitmaps = malloc(sizeof(nyx_coverage_bitmap_copy_t)); + memset(bitmaps, 0, sizeof(nyx_coverage_bitmap_copy_t)); + + assert(GET_GLOBAL_STATE()->shared_bitmap_size); + bitmaps->coverage_bitmap = malloc(GET_GLOBAL_STATE()->shared_bitmap_size); + + assert(GET_GLOBAL_STATE()->shared_ijon_bitmap_size); + bitmaps->ijon_bitmap_buffer = malloc(GET_GLOBAL_STATE()->shared_ijon_bitmap_size); + + return bitmaps; +} + void coverage_bitmap_reset(void){ if(GET_GLOBAL_STATE()->shared_bitmap_ptr){ - //fprintf(stderr, "%s: %lx %lx\n", __func__, coverage_bitmap, coverage_bitmap_size); - memset(GET_GLOBAL_STATE()->shared_bitmap_ptr, 0x00, GET_GLOBAL_STATE()->shared_bitmap_size + GET_GLOBAL_STATE()->shared_ijon_bitmap_size); + memset(GET_GLOBAL_STATE()->shared_bitmap_ptr, 0x00, GET_GLOBAL_STATE()->shared_bitmap_real_size); + } + if (GET_GLOBAL_STATE()->shared_ijon_bitmap_ptr && GET_GLOBAL_STATE()->shared_ijon_bitmap_size){ + memset(GET_GLOBAL_STATE()->shared_ijon_bitmap_ptr, 0x00, GET_GLOBAL_STATE()->shared_ijon_bitmap_size); } } -void coverage_bitmap_copy_to_buffer(void* buffer){ +void coverage_bitmap_copy_to_buffer(nyx_coverage_bitmap_copy_t* buffer){ + if(GET_GLOBAL_STATE()->shared_bitmap_ptr){ - memcpy(buffer, GET_GLOBAL_STATE()->shared_bitmap_ptr, GET_GLOBAL_STATE()->shared_bitmap_size + GET_GLOBAL_STATE()->shared_ijon_bitmap_size); + memcpy(buffer->coverage_bitmap, GET_GLOBAL_STATE()->shared_bitmap_ptr, GET_GLOBAL_STATE()->shared_bitmap_real_size); + } + if (GET_GLOBAL_STATE()->shared_ijon_bitmap_ptr){ + memcpy(buffer->ijon_bitmap_buffer, GET_GLOBAL_STATE()->shared_ijon_bitmap_ptr, GET_GLOBAL_STATE()->shared_ijon_bitmap_size); } } -void coverage_bitmap_copy_from_buffer(void* buffer){ +void coverage_bitmap_copy_from_buffer(nyx_coverage_bitmap_copy_t* buffer){ + if(GET_GLOBAL_STATE()->shared_bitmap_ptr){ - memcpy(GET_GLOBAL_STATE()->shared_bitmap_ptr, buffer, GET_GLOBAL_STATE()->shared_bitmap_size + GET_GLOBAL_STATE()->shared_ijon_bitmap_size); + memcpy(GET_GLOBAL_STATE()->shared_bitmap_ptr, buffer->coverage_bitmap, GET_GLOBAL_STATE()->shared_bitmap_real_size); + } + if (GET_GLOBAL_STATE()->shared_ijon_bitmap_ptr){ + memcpy(GET_GLOBAL_STATE()->shared_ijon_bitmap_ptr, buffer->ijon_bitmap_buffer, GET_GLOBAL_STATE()->shared_ijon_bitmap_size); } } -void apply_capabilities(CPUState *cpu){ +bool apply_capabilities(CPUState *cpu){ //X86CPU *cpux86 = X86_CPU(cpu); //CPUX86State *env = &cpux86->env; @@ -74,7 +103,8 @@ void apply_capabilities(CPUState *cpu){ debug_printf("--------------------------\n"); if(GET_GLOBAL_STATE()->cap_compile_time_tracing_buffer_vaddr&0xfff){ - fprintf(stderr, "[QEMU-Nyx] Warning: guest's trace bitmap v_addr (0x%lx) is not page aligned!\n", GET_GLOBAL_STATE()->cap_compile_time_tracing_buffer_vaddr); + fprintf(stderr, "[QEMU-Nyx] Error: guest's trace bitmap v_addr (0x%lx) is not page aligned!\n", GET_GLOBAL_STATE()->cap_compile_time_tracing_buffer_vaddr); + return false; } for(uint64_t i = 0; i < GET_GLOBAL_STATE()->shared_bitmap_size; i += 0x1000){ @@ -84,18 +114,20 @@ void apply_capabilities(CPUState *cpu){ } if(GET_GLOBAL_STATE()->cap_ijon_tracing){ - debug_fprintf(stderr, "%s: agent trace buffer at vaddr: %lx\n", __func__, GET_GLOBAL_STATE()->cap_ijon_tracing_buffer_vaddr); + debug_printf(stderr, "%s: agent trace buffer at vaddr: %lx\n", __func__, GET_GLOBAL_STATE()->cap_ijon_tracing_buffer_vaddr); if(GET_GLOBAL_STATE()->cap_ijon_tracing_buffer_vaddr&0xfff){ - fprintf(stderr, "[QEMU-Nyx] Warning: guest's ijon buffer v_addr (0x%lx) is not page aligned!\n", GET_GLOBAL_STATE()->cap_ijon_tracing_buffer_vaddr); + fprintf(stderr, "[QEMU-Nyx] Error: guest's ijon buffer v_addr (0x%lx) is not page aligned!\n", GET_GLOBAL_STATE()->cap_ijon_tracing_buffer_vaddr); + return false; } kvm_arch_get_registers_fast(cpu); for(uint64_t i = 0; i < GET_GLOBAL_STATE()->shared_ijon_bitmap_size; i += 0x1000){ - assert(remap_slot(GET_GLOBAL_STATE()->cap_ijon_tracing_buffer_vaddr + i, (GET_GLOBAL_STATE()->shared_bitmap_size+i)/0x1000, cpu, GET_GLOBAL_STATE()->shared_bitmap_fd, GET_GLOBAL_STATE()->shared_bitmap_size+GET_GLOBAL_STATE()->shared_ijon_bitmap_size, true, GET_GLOBAL_STATE()->cap_cr3)); + assert(remap_slot(GET_GLOBAL_STATE()->cap_ijon_tracing_buffer_vaddr + i, i/0x1000, cpu, GET_GLOBAL_STATE()->shared_ijon_bitmap_fd, GET_GLOBAL_STATE()->shared_ijon_bitmap_size+GET_GLOBAL_STATE()->shared_ijon_bitmap_size, true, GET_GLOBAL_STATE()->cap_cr3)); } set_cap_agent_ijon_trace_bitmap(GET_GLOBAL_STATE()->auxilary_buffer, true); } + return true; } bool folder_exits(const char* path){ diff --git a/nyx/helpers.h b/nyx/helpers.h index 1cd6d744f3..81eaf23610 100644 --- a/nyx/helpers.h +++ b/nyx/helpers.h @@ -3,13 +3,22 @@ #include "qemu/osdep.h" uint64_t get_rip(CPUState *cpu); + +typedef struct nyx_coverage_bitmap_copy_s{ + void* coverage_bitmap; + void* ijon_bitmap_buffer; +}nyx_coverage_bitmap_copy_t; + +void nyx_abort(char* msg); + +nyx_coverage_bitmap_copy_t* new_coverage_bitmaps(void); void coverage_bitmap_reset(void); -void coverage_bitmap_copy_to_buffer(void* buffer); -void coverage_bitmap_copy_from_buffer(void* buffer); +void coverage_bitmap_copy_to_buffer(nyx_coverage_bitmap_copy_t* buffer); +void coverage_bitmap_copy_from_buffer(nyx_coverage_bitmap_copy_t* buffer); int get_capstone_mode(int word_width_in_bits); -void apply_capabilities(CPUState *cpu); +bool apply_capabilities(CPUState *cpu); bool folder_exits(const char* path); bool file_exits(const char* path); diff --git a/nyx/hypercall/configuration.c b/nyx/hypercall/configuration.c index 038767eb79..e2cb8b0a17 100644 --- a/nyx/hypercall/configuration.c +++ b/nyx/hypercall/configuration.c @@ -1,7 +1,8 @@ #include "qemu/osdep.h" -#include "nyx/state.h" +#include "nyx/state/state.h" #include "nyx/hypercall/configuration.h" #include "nyx/memory_access.h" +#include "nyx/helpers.h" void handle_hypercall_kafl_get_host_config(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){ uint64_t vaddr = hypercall_arg; @@ -17,6 +18,20 @@ void handle_hypercall_kafl_get_host_config(struct kvm_run *run, CPUState *cpu, u write_virtual_memory(vaddr, (uint8_t*)&config, sizeof(host_config_t), cpu); } +static void resize_coverage_bitmap(uint32_t new_bitmap_size){ + uint32_t new_bitmap_shm_size = new_bitmap_size; + + if (new_bitmap_shm_size % 64 > 0) { + new_bitmap_shm_size = ((new_bitmap_shm_size + 64) >> 6) << 6; + } + + GET_GLOBAL_STATE()->shared_bitmap_real_size = new_bitmap_shm_size; + resize_shared_memory(new_bitmap_shm_size, &GET_GLOBAL_STATE()->shared_bitmap_size, &GET_GLOBAL_STATE()->shared_bitmap_ptr, GET_GLOBAL_STATE()->shared_bitmap_fd); + + /* pass the actual bitmap buffer size to the front-end */ + GET_GLOBAL_STATE()->auxilary_buffer->capabilites.agent_coverage_bitmap_size = new_bitmap_size; +} + void handle_hypercall_kafl_set_agent_config(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){ uint64_t vaddr = hypercall_arg; agent_config_t config; @@ -60,12 +75,14 @@ void handle_hypercall_kafl_set_agent_config(struct kvm_run *run, CPUState *cpu, if (config.coverage_bitmap_size){ resize_coverage_bitmap(config.coverage_bitmap_size); } - + if (config.input_buffer_size){ - resize_payload_buffer(config.coverage_bitmap_size); + resize_payload_buffer(config.input_buffer_size); } - apply_capabilities(cpu); + if(apply_capabilities(cpu) == false){ + nyx_abort((char*)"applying agent configuration failed..."); + } if(getenv("DUMP_PAYLOAD_MODE")){ config.dump_payloads = 1; diff --git a/nyx/hypercall/debug.c b/nyx/hypercall/debug.c index a146f58258..38eb2b48ae 100644 --- a/nyx/hypercall/debug.c +++ b/nyx/hypercall/debug.c @@ -2,7 +2,7 @@ #include #include "nyx/synchronization.h" #include "nyx/fast_vm_reload.h" -#include "nyx/state.h" +#include "nyx/state/state.h" #include "nyx/hypercall/debug.h" //#define NYX_ENABLE_DEBUG_HYPERCALLS diff --git a/nyx/hypercall/hypercall.c b/nyx/hypercall/hypercall.c index 8d97601d5d..c50e75a96a 100644 --- a/nyx/hypercall/hypercall.c +++ b/nyx/hypercall/hypercall.c @@ -30,8 +30,6 @@ along with QEMU-PT. If not, see . #include "sysemu/kvm_int.h" #include "sysemu/runstate.h" -#include "sysemu/cpus.h" - #include "sysemu/kvm_int.h" #include "sysemu/kvm.h" #include "sysemu/cpus.h" @@ -43,12 +41,11 @@ along with QEMU-PT. If not, see . #include "nyx/hypercall/hypercall.h" #include "nyx/memory_access.h" #include "nyx/interface.h" -#include "nyx/printk.h" #include "nyx/debug.h" #include "nyx/synchronization.h" #include "nyx/fast_vm_reload.h" #include "nyx/kvm_nested.h" -#include "nyx/state.h" +#include "nyx/state/state.h" #include "sysemu/runstate.h" #include "nyx/helpers.h" #include "nyx/nested_hypercalls.h" @@ -59,8 +56,8 @@ along with QEMU-PT. If not, see . #include "nyx/hypercall/debug.h" //#define DEBUG_HPRINTF +#define HPRINTF_SIZE 0x1000 -bool notifiers_enabled = false; bool hypercall_enabled = false; char hprintf_buffer[HPRINTF_SIZE]; @@ -115,10 +112,10 @@ bool handle_hypercall_kafl_next_payload(struct kvm_run *run, CPUState *cpu, uint //pt_reset_bitmap(); if (GET_GLOBAL_STATE()->pt_trace_mode){ - fprintf(stderr, "[QEMU-Nyx] coverage mode: Intel-PT (KVM-Nyx and libxdc)\n"); + printf("[QEMU-Nyx] coverage mode: Intel-PT (KVM-Nyx and libxdc)\n"); } else{ - fprintf(stderr, "[QEMU-Nyx] coverage mode: compile-time instrumentation\n"); + printf("[QEMU-Nyx] coverage mode: compile-time instrumentation\n"); } coverage_bitmap_reset(); @@ -312,13 +309,6 @@ static void handle_hypercall_kafl_range_submit(struct kvm_run *run, CPUState *cp } -static void handle_hypercall_get_program(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){ - fprintf(stderr, "[QEMU-Nyx] Error: This hypercall (HYPERCALL_KAFL_GET_PAYLOAD) is deprecated -> use ./hget instead!\n"); - set_abort_reason_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer, (char*)"Deprecated hypercall called...", strlen("Deprecated hypercall called...")); - synchronization_lock(); -} - - static void release_print_once(CPUState *cpu){ if(release_print_once_bool){ release_print_once_bool = false; @@ -351,7 +341,7 @@ void handle_hypercall_kafl_mtf(struct kvm_run *run, CPUState *cpu, uint64_t hype //assert(false); kvm_arch_get_registers_fast(cpu); - debug_fprintf(stderr, "%s --> %lx\n", __func__, get_rip(cpu)); + fprintf(stderr, "%s --> %lx\n", __func__, get_rip(cpu)); kvm_vcpu_ioctl(cpu, KVM_VMX_PT_DISABLE_MTF); @@ -417,18 +407,7 @@ static void handle_hypercall_kafl_cr3(struct kvm_run *run, CPUState *cpu, uint64 static void handle_hypercall_kafl_submit_panic(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){ if(hypercall_enabled){ QEMU_PT_PRINTF(CORE_PREFIX, "Panic address:\t%lx", hypercall_arg); - if(notifiers_enabled){ - write_virtual_memory(hypercall_arg, (uint8_t*)PANIC_PAYLOAD, PAYLOAD_BUFFER_SIZE, cpu); - } - } -} - -static void handle_hypercall_kafl_submit_kasan(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){ - if(hypercall_enabled){ - QEMU_PT_PRINTF(CORE_PREFIX, "kASAN address:\t%lx", hypercall_arg); - if(notifiers_enabled){ - write_virtual_memory(hypercall_arg, (uint8_t*)KASAN_PAYLOAD, PAYLOAD_BUFFER_SIZE, cpu); - } + write_virtual_memory(hypercall_arg, (uint8_t*)PANIC_PAYLOAD, PAYLOAD_BUFFER_SIZE, cpu); } } @@ -475,9 +454,7 @@ static void handle_hypercall_kafl_panic(struct kvm_run *run, CPUState *cpu, uint } synchronization_lock_crash_found(); } else{ - #define AGENT_HAS_CRASHED_REPORT "Agent has crashed before initializing the fuzzing loop..." - set_abort_reason_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer, (char*)AGENT_HAS_CRASHED_REPORT, strlen(AGENT_HAS_CRASHED_REPORT)); - synchronization_lock(); + nyx_abort((char*)"Agent has crashed before initializing the fuzzing loop..."); } } } @@ -541,61 +518,15 @@ static void handle_hypercall_kafl_panic_extended(struct kvm_run *run, CPUState * read_virtual_memory(hypercall_arg, (uint8_t*)hprintf_buffer, HPRINTF_SIZE, cpu); char* report = NULL; assert(asprintf(&report, "Agent has crashed before initializing the fuzzing loop: %s", hprintf_buffer) != -1); - - set_abort_reason_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer, report, strlen(report)); - synchronization_lock(); + nyx_abort(report); } } - -static void handle_hypercall_kafl_kasan(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){ - if(hypercall_enabled){ -#ifdef PANIC_DEBUG - if(hypercall_arg){ - QEMU_PT_PRINTF(CORE_PREFIX, "ASan notification in user mode!"); - } else{ - QEMU_PT_PRINTF(CORE_PREFIX, "ASan notification in kernel mode!"); - } -#endif - if(fast_reload_snapshot_exists(get_fast_reload_snapshot())){ - synchronization_lock_asan_found(); - //synchronization_stop_vm_kasan(cpu); - } else{ - QEMU_PT_PRINTF(CORE_PREFIX, "KASAN detected during initialization of stage 1 or stage 2 loader"); - //hypercall_snd_char(KAFL_PROTO_KASAN); - QEMU_PT_PRINTF_DEBUG("Protocol - SEND: KAFL_PROTO_KASAN"); - - } - } -} - - -/* -static uint64_t get_rsp(CPUState *cpu){ - kvm_arch_get_registers(cpu); - X86CPU *x86_cpu = X86_CPU(cpu); - CPUX86State *env = &x86_cpu->env; - kvm_cpu_synchronize_state(cpu); - return env->regs[4]; -} -*/ - static void handle_hypercall_kafl_lock(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){ if(!GET_GLOBAL_STATE()->fast_reload_pre_image){ QEMU_PT_PRINTF(CORE_PREFIX, "Skipping pre image creation (hint: set pre=on) ..."); return; - -/* - - fast_reload_create_in_memory(get_fast_reload_snapshot(), true); - -qemu_mutex_lock_iothread(); - fast_reload_restore(get_fast_reload_snapshot()); - - qemu_mutex_unlock_iothread(); - */ - //return; } QEMU_PT_PRINTF(CORE_PREFIX, "Creating pre image snapshot <%s> ...", GET_GLOBAL_STATE()->fast_reload_pre_path); @@ -604,16 +535,6 @@ qemu_mutex_lock_iothread(); request_fast_vm_reload(GET_GLOBAL_STATE()->reload_state, REQUEST_SAVE_SNAPSHOT_PRE); } -static void handle_hypercall_kafl_info(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){ - fprintf(stderr, "[QEMU-Nyx] Error: This hypercall (HYPERCALL_KAFL_INFO) is deprecated -> use hprintf() & ./habort instead!\n"); - set_abort_reason_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer, (char*)"Deprecated hypercall called...", strlen("Deprecated hypercall called...")); - synchronization_lock(); -} - -void enable_notifies(void){ - notifiers_enabled = true; -} - static void handle_hypercall_kafl_printf(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){ read_virtual_memory(hypercall_arg, (uint8_t*)hprintf_buffer, HPRINTF_SIZE, cpu); #ifdef DEBUG_HPRINTF @@ -624,26 +545,6 @@ static void handle_hypercall_kafl_printf(struct kvm_run *run, CPUState *cpu, uin #endif } - -static void handle_hypercall_kafl_printk(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){ - if(!notifiers_enabled){ - if (hypercall_enabled && GET_GLOBAL_STATE()->enable_hprintf){ - if(kafl_linux_printk(cpu)){ - handle_hypercall_kafl_panic(run, cpu, (uint64_t)run->hypercall.args[0]); - } - } - } -} - -static void handle_hypercall_kafl_printk_addr(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){ - if(!notifiers_enabled){ - debug_printf("%s\n", __func__); - debug_printf("%lx\n", hypercall_arg); - write_virtual_memory(hypercall_arg, (uint8_t*)PRINTK_PAYLOAD, PRINTK_PAYLOAD_SIZE, cpu); - debug_printf("Done\n"); - } -} - static void handle_hypercall_kafl_user_range_advise(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){ kAFL_ranges* buf = malloc(sizeof(kAFL_ranges)); @@ -831,9 +732,11 @@ int handle_kafl_hypercall(struct kvm_run *run, CPUState *cpu, uint64_t hypercall ret = 0; break; case KVM_EXIT_KAFL_GET_PROGRAM: - //timeout_reload_pending = false; - //fprintf(stderr, "KVM_EXIT_KAFL_GET_PROGRAM\n"); - handle_hypercall_get_program(run, cpu, arg); + nyx_abort((char*)"Deprecated hypercall called (HYPERCALL_KAFL_GET_PROGRAM)..."); + ret = 0; + break; + case KVM_EXIT_KAFL_GET_ARGV: + nyx_abort((char*)"Deprecated hypercall called (HYPERCALL_KAFL_GET_ARGV)..."); ret = 0; break; case KVM_EXIT_KAFL_RELEASE: @@ -855,9 +758,7 @@ int handle_kafl_hypercall(struct kvm_run *run, CPUState *cpu, uint64_t hypercall ret = 0; break; case KVM_EXIT_KAFL_SUBMIT_KASAN: - //timeout_reload_pending = false; - //fprintf(stderr, "KVM_EXIT_KAFL_SUBMIT_KASAN\n"); - handle_hypercall_kafl_submit_kasan(run, cpu, arg); + nyx_abort((char*)"Deprecated hypercall called (HYPERCALL_SUBMIT_KASAN)..."); ret = 0; break; case KVM_EXIT_KAFL_PANIC: @@ -867,9 +768,7 @@ int handle_kafl_hypercall(struct kvm_run *run, CPUState *cpu, uint64_t hypercall ret = 0; break; case KVM_EXIT_KAFL_KASAN: - //timeout_reload_pending = false; - //fprintf(stderr, "KVM_EXIT_KAFL_KASAN\n"); - handle_hypercall_kafl_kasan(run, cpu, arg); + nyx_abort((char*)"Deprecated hypercall called (HYPERCALL_KAFL_KASAN)..."); ret = 0; break; case KVM_EXIT_KAFL_LOCK: @@ -879,9 +778,7 @@ int handle_kafl_hypercall(struct kvm_run *run, CPUState *cpu, uint64_t hypercall ret = 0; break; case KVM_EXIT_KAFL_INFO: - //timeout_reload_pending = false; - //fprintf(stderr, "KVM_EXIT_KAFL_INFO\n"); - handle_hypercall_kafl_info(run, cpu, arg); + nyx_abort((char*)"Deprecated hypercall called (HYPERCALL_KAFL_INFO)..."); ret = 0; break; case KVM_EXIT_KAFL_NEXT_PAYLOAD: @@ -897,13 +794,11 @@ int handle_kafl_hypercall(struct kvm_run *run, CPUState *cpu, uint64_t hypercall ret = 0; break; case KVM_EXIT_KAFL_PRINTK_ADDR: - //timeout_reload_pending = false; - handle_hypercall_kafl_printk_addr(run, cpu, arg); + nyx_abort((char*)"Deprecated hypercall called (KVM_EXIT_KAFL_PRINTK_ADDR)..."); ret = 0; break; case KVM_EXIT_KAFL_PRINTK: - //timeout_reload_pending = false; - handle_hypercall_kafl_printk(run, cpu, arg); + nyx_abort((char*)"Deprecated hypercall called (KVM_EXIT_KAFL_PRINTK)..."); ret = 0; break; diff --git a/nyx/hypercall/hypercall.h b/nyx/hypercall/hypercall.h index 29dc87daab..c9cb788846 100644 --- a/nyx/hypercall/hypercall.h +++ b/nyx/hypercall/hypercall.h @@ -22,7 +22,6 @@ along with QEMU-PT. If not, see . #pragma once #define PAYLOAD_BUFFER_SIZE 26 -#define PRINTK_PAYLOAD_SIZE 4 #define KAFL_MODE_64 0 #define KAFL_MODE_32 1 @@ -100,7 +99,6 @@ void handle_hypercall_kafl_page_dump_bp(struct kvm_run *run, CPUState *cpu, uint void hprintf(char* msg); -void enable_notifies(void); bool handle_hypercall_kafl_next_payload(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg); void hypercall_reset_hprintf_counter(void); diff --git a/nyx/interface.c b/nyx/interface.c index f55ddf3f03..96b5f7f71f 100644 --- a/nyx/interface.c +++ b/nyx/interface.c @@ -48,7 +48,7 @@ along with QEMU-PT. If not, see . #include "nyx/snapshot/devices/state_reallocation.h" #include "nyx/memory_access.h" #include -#include "nyx/state.h" +#include "nyx/state/state.h" #include "nyx/sharedir.h" #include "nyx/helpers.h" @@ -85,10 +85,9 @@ typedef struct nyx_interface_state { char* filter_bitmap[4]; char* ip_filter[4][2]; - uint64_t bitmap_size; + uint32_t bitmap_size; + uint32_t input_buffer_size; - bool debug_mode; /* support for hprintf */ - bool notifier; bool dump_pt_trace; bool redqueen; @@ -183,6 +182,7 @@ static void nyx_guest_setup_bitmap(nyx_interface_state *s, char* filename, uint3 GET_GLOBAL_STATE()->shared_bitmap_ptr = (void*)ptr; GET_GLOBAL_STATE()->shared_bitmap_fd = fd; GET_GLOBAL_STATE()->shared_bitmap_size = bitmap_size; + GET_GLOBAL_STATE()->shared_bitmap_real_size = bitmap_size; } @@ -197,12 +197,9 @@ static void nyx_guest_setup_ijon_buffer(nyx_interface_state *s, char* filename){ assert(DEFAULT_NYX_IJON_BITMAP_SIZE == st.st_size); ptr = mmap(0, DEFAULT_NYX_IJON_BITMAP_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); - /* - GET_GLOBAL_STATE()->shared_bitmap_ptr = (void*)ptr; - GET_GLOBAL_STATE()->shared_bitmap_fd = fd; - GET_GLOBAL_STATE()->shared_bitmap_size = bitmap_size-DEFAULT_NYX_IJON_BITMAP_SIZE; + GET_GLOBAL_STATE()->shared_ijon_bitmap_ptr = (void*)ptr; + GET_GLOBAL_STATE()->shared_ijon_bitmap_fd = fd; GET_GLOBAL_STATE()->shared_ijon_bitmap_size = DEFAULT_NYX_IJON_BITMAP_SIZE; - */ } static bool verify_workdir_state(nyx_interface_state *s, Error **errp){ @@ -238,7 +235,7 @@ static bool verify_workdir_state(nyx_interface_state *s, Error **errp){ return false; } else { - nyx_create_payload_buffer(s, PAYLOAD_SIZE, tmp, errp); + nyx_create_payload_buffer(s, s->input_buffer_size, tmp, errp); } free(tmp); @@ -304,8 +301,8 @@ static bool verify_workdir_state(nyx_interface_state *s, Error **errp){ if(s->dump_pt_trace){ assert(asprintf(&tmp, "%s/pt_trace_dump_%d", workdir, id) != -1); - pt_open_pt_trace_file(tmp); - free(tmp); + pt_open_pt_trace_file(tmp); + free(tmp); } @@ -391,8 +388,6 @@ static void nyx_realize(DeviceState *dev, Error **errp){ s->bitmap_size = DEFAULT_NYX_BITMAP_SIZE; } - assert((uint32_t)s->bitmap_size > (0x1000 + DEFAULT_NYX_IJON_BITMAP_SIZE)); - assert((((uint32_t)s->bitmap_size-DEFAULT_NYX_IJON_BITMAP_SIZE) & (((uint32_t)s->bitmap_size-DEFAULT_NYX_IJON_BITMAP_SIZE) - 1)) == 0 ); if(s->worker_id == 0xFFFF){ fprintf(stderr, "[QEMU-Nyx] Error: Invalid worker id...\n"); @@ -421,14 +416,6 @@ static void nyx_realize(DeviceState *dev, Error **errp){ } check_available_ipt_ranges(s); - - if(s->debug_mode){ - GET_GLOBAL_STATE()->enable_hprintf = true; - } - - if(s->notifier){ - enable_notifies(); - } pt_setup_enable_hypercalls(); init_crash_handler(); @@ -458,9 +445,8 @@ static Property nyx_interface_properties[] = { DEFINE_PROP_STRING("ip3_b", nyx_interface_state, ip_filter[3][1]), - DEFINE_PROP_UINT64("bitmap_size", nyx_interface_state, bitmap_size, DEFAULT_NYX_BITMAP_SIZE), - DEFINE_PROP_BOOL("debug_mode", nyx_interface_state, debug_mode, false), - DEFINE_PROP_BOOL("crash_notifier", nyx_interface_state, notifier, true), + DEFINE_PROP_UINT32("bitmap_size", nyx_interface_state, bitmap_size, DEFAULT_NYX_BITMAP_SIZE), + DEFINE_PROP_UINT32("input_buffer_size", nyx_interface_state, input_buffer_size, DEFAULT_NYX_BITMAP_SIZE), DEFINE_PROP_BOOL("dump_pt_trace", nyx_interface_state, dump_pt_trace, false), diff --git a/nyx/interface.h b/nyx/interface.h index 54a93172c4..e75e22d90a 100644 --- a/nyx/interface.h +++ b/nyx/interface.h @@ -23,15 +23,10 @@ along with QEMU-PT. If not, see . #define INTERFACE_H /* 64k bitmap + 4k ijon buffer */ -#define DEFAULT_NYX_IJON_BITMAP_SIZE 0x1000 -#define DEFAULT_NYX_BITMAP_SIZE 0x10000 + DEFAULT_NYX_IJON_BITMAP_SIZE -#define DEFAULT_EDGE_FILTER_SIZE 0x1000000 +#define DEFAULT_NYX_IJON_BITMAP_SIZE 0x1000 /* fixed size buffer for IJON -> 4k */ +#define DEFAULT_NYX_BITMAP_SIZE 0x10000 /* default bitmap size => 64k */ -#define PAYLOAD_SIZE (128 << 10) /* 128KB Payload Data */ -#define HPRINTF_SIZE 0x1000 /* 4KB hprintf Data */ - - -#define NYX_INTERFACE_PING 'x' +#define NYX_INTERFACE_PING 'x' bool interface_send_char(char val); diff --git a/nyx/kvm_nested.c b/nyx/kvm_nested.c index 521c44f234..f42a0dce47 100644 --- a/nyx/kvm_nested.c +++ b/nyx/kvm_nested.c @@ -4,7 +4,7 @@ #include "nyx/debug.h" #include "exec/ram_addr.h" #include "qemu/rcu_queue.h" -#include "nyx/state.h" +#include "nyx/state/state.h" #include "sysemu/kvm.h" #include "pt.h" diff --git a/nyx/memory_access.c b/nyx/memory_access.c index 48c9c8f219..08adee0bc7 100644 --- a/nyx/memory_access.c +++ b/nyx/memory_access.c @@ -30,7 +30,7 @@ along with QEMU-PT. If not, see . #include "debug.h" #include "nyx/fast_vm_reload.h" #include "exec/gdbstub.h" -#include "nyx/state.h" +#include "nyx/state/state.h" #include "sysemu/kvm.h" #include "nyx/helpers.h" @@ -200,7 +200,7 @@ bool remap_slot(uint64_t addr, uint32_t slot, CPUState *cpu, int fd, uint64_t sh if(virtual){ phys_addr = get_paging_phys_addr(cpu, cr3, (addr & x86_64_PAGE_MASK)); - if(phys_addr == (uint64_t)-1){ + if(phys_addr == INVALID_ADDRESS){ fprintf(stderr, "[QEMU-Nyx] Error: failed to translate v_addr (0x%lx) to p_addr!\n", addr); fprintf(stderr, "[QEMU-Nyx] Check if the buffer is present in the guest's memory...\n"); exit(1); @@ -259,22 +259,37 @@ bool remap_payload_slot_protected(uint64_t phys_addr, uint32_t slot, CPUState *c return true; } -void resize_coverage_bitmap(uint32_t new_size){ - assert(GET_GLOBAL_STATE()->shared_bitmap_fd && GET_GLOBAL_STATE()->shared_bitmap_size); - fprintf(stderr, "shared_bitmap_size -> %x - new_size: %x\n", GET_GLOBAL_STATE()->shared_bitmap_size, new_size); - assert(GET_GLOBAL_STATE()->shared_bitmap_size <= (new_size+0x1000) && !(new_size & 0xFFF)); +void resize_shared_memory(uint32_t new_size, uint32_t* shm_size, void** shm_ptr, int fd){ + assert(fd && *shm_size); + + /* check if the new_size is a multiple of PAGE_SIZE */ + if(new_size & (PAGE_SIZE-1)){ + new_size = (new_size & ~(PAGE_SIZE-1)) + PAGE_SIZE; + } + + if(*shm_size >= new_size){ + /* no need no resize the buffer -> early exit */ + return; + } + assert(!GET_GLOBAL_STATE()->pt_trace_mode); assert(!GET_GLOBAL_STATE()->in_fuzzing_mode); - assert(ftruncate(GET_GLOBAL_STATE()->shared_bitmap_fd, new_size+0x1000) == 0); + assert(ftruncate(fd, new_size) == 0); - printf("MUNMAP: %d\n", GET_GLOBAL_STATE()->shared_bitmap_size); - munmap((void*)GET_GLOBAL_STATE()->shared_bitmap_ptr , GET_GLOBAL_STATE()->shared_bitmap_size+0x1000); - GET_GLOBAL_STATE()->shared_bitmap_ptr = (void*)mmap(0, new_size+0x1000, PROT_READ|PROT_WRITE, MAP_SHARED, GET_GLOBAL_STATE()->shared_bitmap_fd, 0);; - - GET_GLOBAL_STATE()->shared_bitmap_size = new_size; - GET_GLOBAL_STATE()->auxilary_buffer->capabilites.agent_coverage_bitmap_size = new_size; + if(shm_ptr){ + munmap(*shm_ptr , *shm_size); + *shm_ptr = (void*)mmap(0, new_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + assert(*shm_ptr != MAP_FAILED); + } + else{ + fprintf(stderr, "=> shm_ptr is NULL\n"); + abort(); + } + *shm_size = new_size; } + + void resize_payload_buffer(uint32_t new_size){ assert(GET_GLOBAL_STATE()->shared_payload_buffer_fd && GET_GLOBAL_STATE()->shared_payload_buffer_size); assert(GET_GLOBAL_STATE()->shared_payload_buffer_size < new_size && !(new_size & 0xFFF)); @@ -302,7 +317,7 @@ bool remap_payload_buffer(uint64_t virt_guest_addr, CPUState *cpu){ QLIST_FOREACH_RCU(block, &ram_list.blocks, next) { if(!memcmp(block->idstr, "pc.ram", 6)){ //printf("MMUNMAP: %d\n", munmap((void*)(((uint64_t)block->host) + phys_addr), x86_64_PAGE_SIZE)); - if(munmap((void*)(((uint64_t)block->host) + phys_addr), x86_64_PAGE_SIZE) == -1){ + if(munmap((void*)(((uint64_t)block->host) + phys_addr), x86_64_PAGE_SIZE) == -1){ fprintf(stderr, "munmap failed!\n"); //exit(1); assert(false); @@ -351,7 +366,7 @@ bool write_virtual_memory(uint64_t address, uint8_t* data, uint32_t size, CPUSta attrs = MEMTXATTRS_UNSPECIFIED; phys_addr = cpu_get_phys_page_attrs_debug(cpu, (address & x86_64_PAGE_MASK), &attrs); - if (phys_addr == -1){ + if (phys_addr == INVALID_ADDRESS){ QEMU_PT_PRINTF(MEM_PREFIX, "phys_addr == -1:\t%lx", address); return false; } @@ -680,12 +695,17 @@ void print_48_paging2(uint64_t cr3){ } -static uint64_t* load_page_table(uint64_t page_table_address, uint64_t* paging_entries_buffer, uint8_t level, bool read_from_snapshot){ +static uint64_t* load_page_table(uint64_t page_table_address, uint64_t* paging_entries_buffer, uint8_t level, bool read_from_snapshot, bool *success){ + if(page_table_address == INVALID_ADDRESS){ + *success = false; + } + if (read_from_snapshot){ - read_snapshot_memory(get_fast_reload_snapshot(), page_table_address, (uint8_t *) paging_entries_buffer, PPAGE_SIZE); + *success = read_snapshot_memory(get_fast_reload_snapshot(), page_table_address, (uint8_t *) paging_entries_buffer, PPAGE_SIZE); } else{ cpu_physical_memory_rw(page_table_address, (uint8_t *) paging_entries_buffer, PPAGE_SIZE, false); + *success = true; /* fix this */ } return paging_entries_buffer; } @@ -702,8 +722,14 @@ static uint64_t get_48_paging_phys_addr(uint64_t cr3, uint64_t addr, bool read_f uint64_t* paging_entries_buffer_ptr = NULL; uint64_t page_table_address = 0; + bool success = false; + page_table_address = (cr3&PAGETABLE_MASK); - paging_entries_buffer_ptr = load_page_table(page_table_address, paging_entries_buffer, 0, read_from_snapshot); + paging_entries_buffer_ptr = load_page_table(page_table_address, paging_entries_buffer, 0, read_from_snapshot, &success); + + if (unlikely(success == false)){ + goto fail; + } if(paging_entries_buffer_ptr[pml_4_index]){ address_identifier_4 = ((uint64_t)pml_4_index) << PLEVEL_1_SHIFT; @@ -713,7 +739,11 @@ static uint64_t get_48_paging_phys_addr(uint64_t cr3, uint64_t addr, bool read_f if(CHECK_BIT(paging_entries_buffer_ptr[pml_4_index], 0)){ /* otherwise swapped out */ page_table_address = (paging_entries_buffer_ptr[pml_4_index]&PAGETABLE_MASK); - paging_entries_buffer_ptr = load_page_table(page_table_address, paging_entries_buffer, 1, read_from_snapshot); + paging_entries_buffer_ptr = load_page_table(page_table_address, paging_entries_buffer, 1, read_from_snapshot, &success); + + if (unlikely(success == false)){ + goto fail; + } if(paging_entries_buffer_ptr[pml_3_index]){ @@ -726,7 +756,11 @@ static uint64_t get_48_paging_phys_addr(uint64_t cr3, uint64_t addr, bool read_f else{ page_table_address = (paging_entries_buffer_ptr[pml_3_index]&PAGETABLE_MASK); - paging_entries_buffer_ptr = load_page_table(page_table_address, paging_entries_buffer, 2, read_from_snapshot); + paging_entries_buffer_ptr = load_page_table(page_table_address, paging_entries_buffer, 2, read_from_snapshot, &success); + + if (unlikely(success == false)){ + goto fail; + } if(paging_entries_buffer_ptr[pml_2_index]){ if (CHECK_BIT(paging_entries_buffer_ptr[pml_2_index], 0)){ /* otherwise swapped out */ @@ -737,7 +771,11 @@ static uint64_t get_48_paging_phys_addr(uint64_t cr3, uint64_t addr, bool read_f else{ page_table_address = (paging_entries_buffer_ptr[pml_2_index]&PAGETABLE_MASK); - paging_entries_buffer_ptr = load_page_table(page_table_address, paging_entries_buffer, 3, read_from_snapshot); + paging_entries_buffer_ptr = load_page_table(page_table_address, paging_entries_buffer, 3, read_from_snapshot, &success); + + if (unlikely(success == false)){ + goto fail; + } if(paging_entries_buffer_ptr[pml_1_index]){ if (CHECK_BIT(paging_entries_buffer_ptr[pml_1_index], 0)){ @@ -753,6 +791,8 @@ static uint64_t get_48_paging_phys_addr(uint64_t cr3, uint64_t addr, bool read_f } } } + + fail: return INVALID_ADDRESS; } @@ -839,15 +879,21 @@ bool is_addr_mapped_cr3_snapshot(uint64_t address, CPUState *cpu, uint64_t cr3){ bool dump_page_cr3_snapshot(uint64_t address, uint8_t* data, CPUState *cpu, uint64_t cr3){ fast_reload_t* snapshot = get_fast_reload_snapshot(); - return read_snapshot_memory(snapshot, get_paging_phys_addr_snapshot(cpu, cr3, address), data, PPAGE_SIZE); + uint64_t phys_addr = get_paging_phys_addr_snapshot(cpu, cr3, address); + if(phys_addr == INVALID_ADDRESS){ + return false; + } + else{ + return read_snapshot_memory(snapshot, phys_addr, data, PPAGE_SIZE); + } } bool dump_page_cr3_ht(uint64_t address, uint8_t* data, CPUState *cpu, uint64_t cr3){ hwaddr phys_addr = (hwaddr) get_paging_phys_addr(cpu, cr3, address); int asidx = cpu_asidx_from_attrs(cpu, MEMTXATTRS_UNSPECIFIED); - if(phys_addr == 0xffffffffffffffffULL || address_space_rw(cpu_get_address_space(cpu, asidx), phys_addr, MEMTXATTRS_UNSPECIFIED, data, 0x1000, 0)){ - if(phys_addr != 0xffffffffffffffffULL){ + if(phys_addr == INVALID_ADDRESS || address_space_rw(cpu_get_address_space(cpu, asidx), phys_addr, MEMTXATTRS_UNSPECIFIED, data, 0x1000, 0)){ + if(phys_addr != INVALID_ADDRESS){ fprintf(stderr, "%s: Warning, read failed:\t%lx (%lx)\n", __func__, address, phys_addr); } return false; diff --git a/nyx/memory_access.h b/nyx/memory_access.h index bdc0c39dbd..37c4ac0fd7 100644 --- a/nyx/memory_access.h +++ b/nyx/memory_access.h @@ -67,7 +67,7 @@ void print_48_paging2(uint64_t cr3); bool dump_page_ht(uint64_t address, uint8_t* data, CPUState *cpu); -void resize_coverage_bitmap(uint32_t new_size); +void resize_shared_memory(uint32_t new_size, uint32_t* shm_size, void** shm_ptr, int fd); void resize_payload_buffer(uint32_t new_size); #endif diff --git a/nyx/nested_hypercalls.c b/nyx/nested_hypercalls.c index 0600ab832b..23ccb4d93e 100644 --- a/nyx/nested_hypercalls.c +++ b/nyx/nested_hypercalls.c @@ -5,7 +5,7 @@ #include "debug.h" #include "nested_hypercalls.h" #include "interface.h" -#include "state.h" +#include "state/state.h" #include "pt.h" #include "sysemu/sysemu.h" #include "sysemu/kvm.h" diff --git a/nyx/page_cache.c b/nyx/page_cache.c index de64b05fbb..fcb9aa2f3f 100644 --- a/nyx/page_cache.c +++ b/nyx/page_cache.c @@ -17,7 +17,7 @@ #include "memory_access.h" #include "fast_vm_reload.h" #include "kvm_nested.h" -#include "nyx/state.h" +#include "nyx/state/state.h" #endif @@ -106,7 +106,7 @@ static bool append_page(page_cache_t* self, uint64_t page, uint64_t cr3){ if(!dump_page_cr3_ht(page, self->page_data+(PAGE_SIZE*self->num_pages), self->cpu, GET_GLOBAL_STATE()->parent_cr3)){ if(!dump_page_cr3_snapshot(page, self->page_data+(PAGE_SIZE*self->num_pages), self->cpu, GET_GLOBAL_STATE()->parent_cr3)){ - fprintf(stderr, "FAILED DUMP PROCESS of PAGE %lx\n", page); + //fprintf(stderr, "FAILED DUMP PROCESS of PAGE %lx\n", page); //memset(self->page_data+(PAGE_SIZE*self->num_pages), 0xff, PAGE_SIZE); munmap(self->page_data, (self->num_pages+1)*PAGE_SIZE); @@ -255,7 +255,7 @@ static bool update_page_cache(page_cache_t* self, uint64_t page, khiter_t* k){ kh_value(self->lookup, *k) = (self->num_pages-1)*PAGE_SIZE; } else{ - fprintf(stderr, "Fail!!!!\n"); + //fprintf(stderr, "Fail!!!!\n"); page_cache_unlock(self); return false; /* diff --git a/nyx/patcher.c b/nyx/patcher.c index f1897ac094..7cb7998849 100644 --- a/nyx/patcher.c +++ b/nyx/patcher.c @@ -2,7 +2,7 @@ #include "nyx/memory_access.h" #include "nyx/disassembler.h" #include "debug.h" -#include "nyx/state.h" +#include "nyx/state/state.h" uint8_t cmp_patch_data[] = { 0x38, 0xC0, [2 ... MAX_INSTRUCTION_SIZE]=0x90 }; // CMP AL,AL; NOP, NOP ... const uint8_t *cmp_patch = &cmp_patch_data[0]; diff --git a/nyx/printk.c b/nyx/printk.c deleted file mode 100644 index 7f0256ed18..0000000000 --- a/nyx/printk.c +++ /dev/null @@ -1,104 +0,0 @@ -#include "qemu/osdep.h" -#include -#include "qemu-common.h" -#include "nyx/memory_access.h" -#include "nyx/hypercall/hypercall.h" -#include "nyx/printk.h" - -enum reg_types{RAX, RCX, RDX, RBX, RSP, RBP, RSI, RDI, R8, R9, R10, R11, R12, R13, R14, R15, RIP}; - -uint8_t types[] = {RSI, RDX, RCX, R8, R9} ; -/* calling convention: RDI, RSI, RDX, RCX, R8, R9 */ - -/* https://www.kernel.org/doc/Documentation/printk-formats.txt :-( */ - -bool kafl_linux_printk(CPUState *cpu){ - X86CPU *x86_cpu = X86_CPU(cpu); - CPUX86State *env = &x86_cpu->env; - - char printk_buf[0x1000]; - - uint8_t rsp_buf[0x1000]; - uint8_t rdi_buf[0x1000]; - uint8_t rsi_buf[0x1000]; - uint8_t rdx_buf[0x1000]; - uint8_t rcx_buf[0x1000]; - uint8_t r8_buf[0x1000]; - uint8_t r9_buf[0x1000]; - - read_virtual_memory((uint64_t)env->regs[RSP], (uint8_t*)rsp_buf, 0x1000, cpu); - read_virtual_memory((uint64_t)env->regs[RDI], (uint8_t*)rdi_buf, 0x1000, cpu); - - uint8_t* buf[] = {rsi_buf, rdx_buf, rcx_buf, r8_buf, r9_buf}; - - - - for(uint16_t i = 0, type = 0; i < 0x1000 && rdi_buf[i] != '\x00'; i++){ - - if(i > 1 && rdi_buf[i-2] == '%' && rdi_buf[i-1] != '%'){ - - if(rdi_buf[i-1] == 's' || rdi_buf[i-1] == 'p' || rdi_buf[i-1] == '.'){ - - - if(rdi_buf[i] == 'B'){ - rdi_buf[i-1] = 'l'; - rdi_buf[i] = 'x'; - buf[type] = (uint8_t*)env->regs[types[type]]; - } - - else if(rdi_buf[i-1] == 'p' && rdi_buf[i] == 'V'){ - rdi_buf[i-1] = 's'; - rdi_buf[i] = ' '; - read_virtual_memory((uint64_t)env->regs[types[type]], (uint8_t*)buf[type], 0x1000, cpu); - uint64_t tmp = *((uint64_t*)buf[type]); - read_virtual_memory(tmp, (uint8_t*)buf[type], 0x1000, cpu); - - } - else if(rdi_buf[i-1] == 'p'){ - rdi_buf[i-1] = 'l'; - memmove(rdi_buf+i+1, rdi_buf+i, 0x1000-i-1); - rdi_buf[i] = 'x'; - buf[type] = (uint8_t*)env->regs[types[type]]; - - } - else { - read_virtual_memory((uint64_t)env->regs[types[type]], (uint8_t*)buf[type], 0x1000, cpu); - } - } - else{ - buf[type] = (uint8_t*)env->regs[types[type]]; - } - - type++; - - - if(type > 4){ - rdi_buf[i] = '\n'; - rdi_buf[i+1] = '\x00'; - break; - } - } - - } - - snprintf(printk_buf, 0x1000, (char*)rdi_buf, buf[0], buf[1], buf[2], buf[3], buf[4]); - - if(printk_buf[0] == 0x1){ - //printf("%s", rdi_buf+2); - //hprintf(printk_buf+2); - //printf("%s", printk_buf+2); - if(!strncmp(printk_buf+2, "---[ end Kernel panic", 21)){ - return true; - } - } - else { - //printf("%s", rdi_buf); - //hprintf(printk_buf); - //printf("%s", printk_buf); - if(!strncmp(printk_buf, "---[ end Kernel panic", 21)){ - return true; - } - } - return false; - -} \ No newline at end of file diff --git a/nyx/printk.h b/nyx/printk.h deleted file mode 100644 index 9fac4721db..0000000000 --- a/nyx/printk.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - -Copyright (C) 2017 Sergej Schumilo - -This file is part of QEMU-PT (kAFL). - -QEMU-PT is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -QEMU-PT is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with QEMU-PT. If not, see . - -*/ - -#ifndef PRINTK_H -#define PRINTK_H - -bool kafl_linux_printk(CPUState *cpu); - - -#endif \ No newline at end of file diff --git a/nyx/pt.c b/nyx/pt.c index 66a07eb899..abaa8cb35c 100644 --- a/nyx/pt.c +++ b/nyx/pt.c @@ -38,7 +38,7 @@ along with QEMU-PT. If not, see . #include "nyx/redqueen_patch.h" #include "nyx/patcher.h" #include "nyx/page_cache.h" -#include "nyx/state.h" +#include "nyx/state/state.h" #include #include "nyx/helpers.h" @@ -145,7 +145,7 @@ void pt_dump(CPUState *cpu, int bytes){ cpu->intel_pt_run_trashed = true; break; case decoder_page_fault: - fprintf(stderr, "Page not found => 0x%lx\n", libxdc_get_page_fault_addr(GET_GLOBAL_STATE()->decoder)); + //fprintf(stderr, "Page not found => 0x%lx\n", libxdc_get_page_fault_addr(GET_GLOBAL_STATE()->decoder)); GET_GLOBAL_STATE()->decoder_page_fault = true; GET_GLOBAL_STATE()->decoder_page_fault_addr = libxdc_get_page_fault_addr(GET_GLOBAL_STATE()->decoder); break; @@ -157,7 +157,7 @@ void pt_dump(CPUState *cpu, int bytes){ break; } } - } + } } diff --git a/nyx/redqueen.c b/nyx/redqueen.c index 921c1ee1ec..d878013687 100644 --- a/nyx/redqueen.c +++ b/nyx/redqueen.c @@ -28,7 +28,7 @@ along with QEMU-PT. If not, see . #include "patcher.h" #include "debug.h" #include "redqueen_trace.h" -#include "nyx/state.h" +#include "nyx/state/state.h" #include #include diff --git a/nyx/snapshot/block/block_cow.c b/nyx/snapshot/block/block_cow.c index ecded94277..dab91421f0 100644 --- a/nyx/snapshot/block/block_cow.c +++ b/nyx/snapshot/block/block_cow.c @@ -3,7 +3,7 @@ #include #include "nyx/snapshot/block/block_cow.h" #include "sysemu/block-backend.h" -#include "nyx/state.h" +#include "nyx/state/state.h" //#define COW_CACHE_DEBUG diff --git a/nyx/snapshot/block/nyx_block_snapshot.c b/nyx/snapshot/block/nyx_block_snapshot.c index e2a0fd897c..caad18f5eb 100644 --- a/nyx/snapshot/block/nyx_block_snapshot.c +++ b/nyx/snapshot/block/nyx_block_snapshot.c @@ -11,7 +11,7 @@ #include "nyx/snapshot/block/nyx_block_snapshot.h" #include "nyx/debug.h" -#include "nyx/state.h" +#include "nyx/state/state.h" typedef struct fast_reload_cow_entry_s{ uint32_t id; diff --git a/nyx/snapshot/memory/backend/nyx_debug.c b/nyx/snapshot/memory/backend/nyx_debug.c index 726b011755..224bff27c7 100644 --- a/nyx/snapshot/memory/backend/nyx_debug.c +++ b/nyx/snapshot/memory/backend/nyx_debug.c @@ -29,7 +29,9 @@ void nyx_snapshot_debug_enable(fast_reload_t* self){ } /* restore operation */ -void nyx_snapshot_debug_restore(shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist, bool verbose){ +uint32_t nyx_snapshot_debug_restore(shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist, bool verbose){ + uint32_t num_dirty_pages = 0; + void* current_region = NULL; int counter = 0; for(uint8_t i = 0; i < shadow_memory_state->ram_regions_num; i++){ @@ -59,6 +61,7 @@ void nyx_snapshot_debug_restore(shadow_memory_t* shadow_memory_state, snapshot_p } memcpy(host_addr, snapshot_addr, TARGET_PAGE_SIZE); + num_dirty_pages++; } } } @@ -67,6 +70,7 @@ void nyx_snapshot_debug_restore(shadow_memory_t* shadow_memory_state, snapshot_p if(verbose){ printf("TOTAL: %d\n", counter); } + return num_dirty_pages; } void nyx_snapshot_debug_save_root_pages(shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist, bool verbose){ diff --git a/nyx/snapshot/memory/backend/nyx_debug.h b/nyx/snapshot/memory/backend/nyx_debug.h index de4682be42..653d4ee1a0 100644 --- a/nyx/snapshot/memory/backend/nyx_debug.h +++ b/nyx/snapshot/memory/backend/nyx_debug.h @@ -5,6 +5,6 @@ void nyx_snapshot_debug_pre_init(void); void nyx_snapshot_debug_init(fast_reload_t* self); void nyx_snapshot_debug_enable(fast_reload_t* self); -void nyx_snapshot_debug_restore(shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist, bool verbose); +uint32_t nyx_snapshot_debug_restore(shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist, bool verbose); void nyx_snapshot_debug_set(fast_reload_t* self); void nyx_snapshot_debug_save_root_pages(shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist, bool verbose); diff --git a/nyx/snapshot/memory/backend/nyx_dirty_ring.c b/nyx/snapshot/memory/backend/nyx_dirty_ring.c index 39e245307b..296d7b47a1 100644 --- a/nyx/snapshot/memory/backend/nyx_dirty_ring.c +++ b/nyx/snapshot/memory/backend/nyx_dirty_ring.c @@ -242,7 +242,8 @@ nyx_dirty_ring_t* nyx_dirty_ring_init(shadow_memory_t* shadow_memory){ return self; } -static void restore_memory(nyx_dirty_ring_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist){ +static uint32_t restore_memory(nyx_dirty_ring_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist){ + uint32_t num_dirty_pages = 0; void* host_addr = NULL; void* snapshot_addr = NULL; uint64_t physical_addr = 0; @@ -272,13 +273,15 @@ static void restore_memory(nyx_dirty_ring_t* self, shadow_memory_t* shadow_memor snapshot_addr = shadow_memory_state->ram_regions[kvm_region_slot->region_id].snapshot_region_ptr + entry_offset_addr; } - memcpy(host_addr, snapshot_addr, TARGET_PAGE_SIZE); + memcpy(host_addr, snapshot_addr, TARGET_PAGE_SIZE); clear_bit(gfn, (void*)kvm_region_slot->bitmap); + num_dirty_pages++; } kvm_region_slot->stack_ptr = 0; } } + return num_dirty_pages; } static void save_root_pages(nyx_dirty_ring_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist){ @@ -318,8 +321,7 @@ static void save_root_pages(nyx_dirty_ring_t* self, shadow_memory_t* shadow_memo //entry = &ring->dirty_gfns[ring->reset_index & (ring->size - 1)]; -void nyx_snapshot_nyx_dirty_ring_restore(nyx_dirty_ring_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist){ - +uint32_t nyx_snapshot_nyx_dirty_ring_restore(nyx_dirty_ring_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist){ /* static int perf_counter = 0; @@ -330,8 +332,8 @@ void nyx_snapshot_nyx_dirty_ring_restore(nyx_dirty_ring_t* self, shadow_memory_t perf_counter++; */ - dirty_ring_flush_and_collect(self, shadow_memory_state, blocklist, kvm_get_vm_fd(kvm_state)); - restore_memory(self, shadow_memory_state, blocklist); + dirty_ring_flush_and_collect(self, shadow_memory_state, blocklist, kvm_get_vm_fd(kvm_state)); + return restore_memory(self, shadow_memory_state, blocklist); } void nyx_snapshot_nyx_dirty_ring_save_root_pages(nyx_dirty_ring_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist){ diff --git a/nyx/snapshot/memory/backend/nyx_dirty_ring.h b/nyx/snapshot/memory/backend/nyx_dirty_ring.h index d0fb7c89bb..fa9fab40a3 100644 --- a/nyx/snapshot/memory/backend/nyx_dirty_ring.h +++ b/nyx/snapshot/memory/backend/nyx_dirty_ring.h @@ -36,7 +36,7 @@ void nyx_dirty_ring_pre_init(int kvm_fd, int vm_fd); nyx_dirty_ring_t* nyx_dirty_ring_init(shadow_memory_t* shadow_memory); -void nyx_snapshot_nyx_dirty_ring_restore(nyx_dirty_ring_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist); +uint32_t nyx_snapshot_nyx_dirty_ring_restore(nyx_dirty_ring_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist); void nyx_snapshot_nyx_dirty_ring_save_root_pages(nyx_dirty_ring_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist); void nyx_snapshot_nyx_dirty_ring_flush(void); diff --git a/nyx/snapshot/memory/backend/nyx_fdl.c b/nyx/snapshot/memory/backend/nyx_fdl.c index b1b21c2a69..31649a3348 100644 --- a/nyx/snapshot/memory/backend/nyx_fdl.c +++ b/nyx/snapshot/memory/backend/nyx_fdl.c @@ -98,8 +98,9 @@ nyx_fdl_t* nyx_fdl_init(shadow_memory_t* shadow_memory){ #define MEMSET_BITMAP #ifdef MEMSET_BITMAP -static void nyx_snapshot_nyx_fdl_restore_new(nyx_fdl_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist){ +static uint32_t nyx_snapshot_nyx_fdl_restore_new(nyx_fdl_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist){ + uint32_t num_dirty_pages = 0; void* current_region = NULL; struct fdl_result result; @@ -142,24 +143,26 @@ static void nyx_snapshot_nyx_fdl_restore_new(nyx_fdl_t* self, shadow_memory_t* s clear_bit(entry_offset_addr>>12, (void*)self->entry[i].bitmap); memcpy(host_addr, snapshot_addr, TARGET_PAGE_SIZE); + num_dirty_pages++; } } #ifdef RESET_VRAM //nyx_snapshot_nyx_fdl_restore_vram(self, shadow_memory_state); #endif + return num_dirty_pages; } #endif /* restore operation */ -void nyx_snapshot_nyx_fdl_restore(nyx_fdl_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist){ +uint32_t nyx_snapshot_nyx_fdl_restore(nyx_fdl_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist){ /* not sure which one is faster -> benchmark ASAP */ #ifdef MEMSET_BITMAP - nyx_snapshot_nyx_fdl_restore_new(self, shadow_memory_state, blocklist); + return nyx_snapshot_nyx_fdl_restore_new(self, shadow_memory_state, blocklist); #else - nyx_snapshot_nyx_fdl_restore_old(self, shadow_memory_state, blocklist); + return nyx_snapshot_nyx_fdl_restore_old(self, shadow_memory_state, blocklist); #endif } diff --git a/nyx/snapshot/memory/backend/nyx_fdl.h b/nyx/snapshot/memory/backend/nyx_fdl.h index fc9b7b55ba..be81fdcc5c 100644 --- a/nyx/snapshot/memory/backend/nyx_fdl.h +++ b/nyx/snapshot/memory/backend/nyx_fdl.h @@ -54,6 +54,6 @@ typedef struct nyx_fdl_s{ }nyx_fdl_t; nyx_fdl_t* nyx_fdl_init(shadow_memory_t* self); -void nyx_snapshot_nyx_fdl_restore(nyx_fdl_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist); +uint32_t nyx_snapshot_nyx_fdl_restore(nyx_fdl_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist); void nyx_snapshot_nyx_fdl_save_root_pages(nyx_fdl_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist); diff --git a/nyx/snapshot/memory/nyx_fdl_user.c b/nyx/snapshot/memory/nyx_fdl_user.c index fec247d1bc..db6aee78c8 100644 --- a/nyx/snapshot/memory/nyx_fdl_user.c +++ b/nyx/snapshot/memory/nyx_fdl_user.c @@ -51,7 +51,8 @@ static void nyx_snapshot_user_fdl_reset(nyx_fdl_user_t* self){ } /* reset operation */ -void nyx_snapshot_user_fdl_restore(nyx_fdl_user_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist){ +uint32_t nyx_snapshot_user_fdl_restore(nyx_fdl_user_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist){ + uint32_t num_dirty_pages = 0; if(self){ void* current_region = NULL; @@ -85,6 +86,7 @@ void nyx_snapshot_user_fdl_restore(nyx_fdl_user_t* self, shadow_memory_t* shadow #endif clear_bit(entry_offset_addr>>12, (void*)self->entry[i].bitmap); memcpy(host_addr, snapshot_addr, TARGET_PAGE_SIZE); + num_dirty_pages++; } } @@ -92,6 +94,7 @@ void nyx_snapshot_user_fdl_restore(nyx_fdl_user_t* self, shadow_memory_t* shadow } nyx_snapshot_user_fdl_reset(self); + return num_dirty_pages; } /* set operation (mark pf as dirty) */ diff --git a/nyx/snapshot/memory/nyx_fdl_user.h b/nyx/snapshot/memory/nyx_fdl_user.h index d20f51837d..391a879aef 100644 --- a/nyx/snapshot/memory/nyx_fdl_user.h +++ b/nyx/snapshot/memory/nyx_fdl_user.h @@ -21,5 +21,5 @@ nyx_fdl_user_t* nyx_fdl_user_init(shadow_memory_t* shadow_memory_state); void nyx_fdl_user_enable(nyx_fdl_user_t* self); void nyx_fdl_user_set(nyx_fdl_user_t* self, shadow_memory_t* shadow_memory_state, nyx_fdl_t* nyx_fdl_state, uint64_t addr, uint64_t length); -void nyx_snapshot_user_fdl_restore(nyx_fdl_user_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist); +uint32_t nyx_snapshot_user_fdl_restore(nyx_fdl_user_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist); void nyx_snapshot_nyx_fdl_user_save_root_pages(nyx_fdl_user_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist); diff --git a/nyx/snapshot/memory/shadow_memory.c b/nyx/snapshot/memory/shadow_memory.c index ec4fba9513..ae84a24a5b 100644 --- a/nyx/snapshot/memory/shadow_memory.c +++ b/nyx/snapshot/memory/shadow_memory.c @@ -395,7 +395,7 @@ void shadow_memory_serialize(shadow_memory_t* self, const char* snapshot_folder) } bool shadow_memory_read_physical_memory(shadow_memory_t* self, uint64_t address, void* ptr, size_t size){ - + assert(size == 0x1000 && (address & 0xFFFULL) == 0); /* remove this limitation later */ if(address < self->memory_size){ diff --git a/nyx/state.c b/nyx/state.c deleted file mode 100644 index cf519218c3..0000000000 --- a/nyx/state.c +++ /dev/null @@ -1,409 +0,0 @@ -/* - -Copyright (C) 2019 Sergej Schumilo - -This file is part of QEMU-PT (HyperTrash / kAFL). - -QEMU-PT is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -QEMU-PT is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with QEMU-PT. If not, see . - -*/ - -#include "nyx/state.h" -#include "nyx/debug.h" -#include "nyx/memory_access.h" -#include "sysemu/kvm.h" -#include "nyx/auxiliary_buffer.h" -#include "nyx/sharedir.h" -#include "nyx/fast_vm_reload_sync.h" -#include "nyx/helpers.h" - -//#define STATE_VERBOSE - -/* global singleton */ -struct state_qemu_pt global_state; - -#define LIBXDC_RELEASE_VERSION_REQUIRED 2 - -void state_init_global(void){ -#ifdef STATE_VERBOSE - fprintf(stderr, "--> %s <--\n", __func__); -#endif - /* safety first */ - assert(libxdc_get_release_version() == LIBXDC_RELEASE_VERSION_REQUIRED); - - global_state.nyx_fdl = false; - - global_state.workdir_path = NULL; - - global_state.fast_reload_enabled = false; - global_state.fast_reload_mode = false; - global_state.fast_reload_path = NULL; - global_state.fast_reload_pre_path = NULL; - global_state.fast_reload_pre_image = false; - - global_state.fast_reload_snapshot = fast_reload_new(); - global_state.reload_state = init_fast_vm_reload_sync(); - - global_state.decoder = NULL; - - global_state.page_cache = NULL; - - global_state.redqueen_enable_pending = false; - global_state.redqueen_disable_pending = false; - global_state.redqueen_instrumentation_mode = 0; - global_state.redqueen_update_blacklist = false; - global_state.patches_enable_pending = false; - global_state.patches_disable_pending = false; - global_state.redqueen_state = NULL; - - for(uint8_t i = 0; i < INTEL_PT_MAX_RANGES; i++){ - global_state.pt_ip_filter_configured[i] = false; - global_state.pt_ip_filter_enabled[i] = false; - global_state.pt_ip_filter_a[i] = 0x0; - global_state.pt_ip_filter_b[i] = 0x0; - } - global_state.pt_c3_filter = 0; - - global_state.enable_hprintf = false; - global_state.parent_cr3 = 0; - global_state.disassembler_word_width = 64; - global_state.nested = false; - global_state.payload_buffer = 0; - global_state.nested_payload_pages = NULL; - global_state.nested_payload_pages_num = 0; - global_state.protect_payload_buffer = 0; - global_state.discard_tmp_snapshot = 0; - global_state.mem_mode = mm_unkown; - - init_timeout_detector(&(global_state.timeout_detector)); - - global_state.in_fuzzing_mode = false; - global_state.in_reload_mode = true; - global_state.shutdown_requested = false; - global_state.cow_cache_full = false; - - global_state.auxilary_buffer = NULL; - memset(&global_state.shadow_config, 0x0, sizeof(auxilary_buffer_config_t)); - - global_state.decoder_page_fault = false; - global_state.decoder_page_fault_addr = 0x0; - - global_state.dump_page = false; - global_state.dump_page_addr = 0x0; - - global_state.in_redqueen_reload_mode = false; - - global_state.pt_trace_mode = true; - global_state.pt_trace_mode_force = false; - - global_state.sharedir = sharedir_new(); - - - global_state.shared_bitmap_fd = 0; - global_state.shared_bitmap_size = 0; - global_state.shared_ijon_bitmap_size = 0; - global_state.shared_payload_buffer_fd = 0; - global_state.shared_payload_buffer_size = 0; - global_state.shared_bitmap_ptr = NULL; - - global_state.pt_trace_size = 0; - global_state.bb_coverage = 0; - - global_state.cap_timeout_detection = 0; - global_state.cap_only_reload_mode = 0; - global_state.cap_compile_time_tracing = 0; - global_state.cap_ijon_tracing = 0; - global_state.cap_cr3 = 0; - global_state.cap_compile_time_tracing_buffer_vaddr = 0; - global_state.cap_ijon_tracing_buffer_vaddr = 0; - - QTAILQ_INIT(&global_state.redqueen_breakpoints); -} - - -fast_reload_t* get_fast_reload_snapshot(void){ - return global_state.fast_reload_snapshot; -} - -void set_fast_reload_mode(bool mode){ - global_state.fast_reload_mode = mode; -} - -void set_fast_reload_path(const char* path){ - assert(global_state.fast_reload_path == NULL); - global_state.fast_reload_path = malloc(strlen(path)+1); - strcpy(global_state.fast_reload_path, path); -} - -void set_fast_reload_pre_path(const char* path){ - assert(global_state.fast_reload_pre_path == NULL); - global_state.fast_reload_pre_path = malloc(strlen(path)+1); - strcpy(global_state.fast_reload_pre_path, path); -} - -void set_fast_reload_pre_image(void){ - assert(global_state.fast_reload_pre_path != NULL); - global_state.fast_reload_pre_image = true; -} - -void enable_fast_reloads(void){ - assert(global_state.fast_reload_path != NULL); - global_state.fast_reload_enabled = true; -} - -void init_page_cache(char* path){ - assert(global_state.page_cache == NULL); - global_state.page_cache = page_cache_new((CPUState *)qemu_get_cpu(0), path); - #ifdef STATE_VERBOSE - debug_printf("\n\nINIT PAGE_CACHE => %s\n", path); - #endif -} - -page_cache_t* get_page_cache(void){ - assert(global_state.page_cache); - return global_state.page_cache; -} - -void init_redqueen_state(void){ - global_state.redqueen_state = new_rq_state((CPUState *)qemu_get_cpu(0), get_page_cache()); -} - - -redqueen_t* get_redqueen_state(void){ - assert(global_state.redqueen_state != NULL); - return global_state.redqueen_state; -} - - -void dump_global_state(const char* filename_prefix){ - debug_printf("%s\n", __func__); - - char* tmp; - - assert(asprintf(&tmp, "%s/global.state", filename_prefix) != -1); - debug_printf("%s\n", tmp); - - FILE *fp = fopen(tmp, "wb"); - if(fp == NULL) { - debug_fprintf(stderr, "[%s] Could not open file %s.\n", __func__, tmp); - assert(false); - //exit(EXIT_FAILURE); - } - - - debug_printf("DUMPING global_state.pt_ip_filter_configured: -\n"); - fwrite(&global_state.pt_ip_filter_configured, sizeof(bool)*4, 1, fp); - - debug_printf("DUMPING global_state.pt_ip_filter_a: -\n"); - fwrite(&global_state.pt_ip_filter_a, sizeof(uint64_t)*4, 1, fp); - - debug_printf("DUMPING global_state.pt_ip_filter_b: -\n"); - fwrite(&global_state.pt_ip_filter_b, sizeof(uint64_t)*4, 1, fp); - - debug_printf("DUMPING global_state.enable_hprintf: %x\n", global_state.enable_hprintf); - fwrite(&global_state.enable_hprintf, sizeof(bool), 1, fp); - debug_printf("DUMPING global_state.parent_cr3: %lx\n", global_state.parent_cr3); - fwrite(&global_state.parent_cr3, sizeof(uint64_t), 1, fp); - - debug_printf("DUMPING global_state.disassembler_word_width: %x\n", global_state.disassembler_word_width); - fwrite(&global_state.disassembler_word_width, sizeof(uint8_t), 1, fp); - debug_printf("DUMPING global_state.fast_reload_pre_image: %x\n", global_state.fast_reload_pre_image); - fwrite(&global_state.fast_reload_pre_image, sizeof(bool), 1, fp); - - debug_printf("DUMPING global_state.mem_mode: %x\n", global_state.mem_mode); - fwrite(&global_state.mem_mode, sizeof(uint8_t), 1, fp); - - debug_printf("DUMPING global_state.pt_trace_mode: %x\n", global_state.pt_trace_mode); - fwrite(&global_state.pt_trace_mode, sizeof(bool), 1, fp); - - debug_printf("DUMPING global_state.nested: %x\n", global_state.nested); - fwrite(&global_state.nested, sizeof(bool), 1, fp); - - if(!global_state.nested){ - debug_printf("DUMPING global_state.payload_buffer: %lx\n", global_state.payload_buffer); - fwrite(&global_state.payload_buffer, sizeof(uint64_t), 1, fp); - - fwrite(&global_state.cap_timeout_detection, sizeof(global_state.cap_timeout_detection), 1, fp); - fwrite(&global_state.cap_only_reload_mode, sizeof(global_state.cap_only_reload_mode), 1, fp); - fwrite(&global_state.cap_compile_time_tracing, sizeof(global_state.cap_compile_time_tracing), 1, fp); - fwrite(&global_state.cap_ijon_tracing, sizeof(global_state.cap_ijon_tracing), 1, fp); - fwrite(&global_state.cap_cr3, sizeof(global_state.cap_cr3), 1, fp); - fwrite(&global_state.cap_compile_time_tracing_buffer_vaddr, sizeof(global_state.cap_compile_time_tracing_buffer_vaddr), 1, fp); - fwrite(&global_state.cap_ijon_tracing_buffer_vaddr, sizeof(global_state.cap_ijon_tracing_buffer_vaddr), 1, fp); - fwrite(&global_state.protect_payload_buffer, sizeof(bool), 1, fp); - } - else{ - assert(global_state.nested_payload_pages != NULL && global_state.nested_payload_pages_num != 0); - debug_printf("DUMPING global_state.nested_payload_pages_num: %x\n", global_state.nested_payload_pages_num); - fwrite(&global_state.nested_payload_pages_num, sizeof(uint32_t), 1, fp); - - if(global_state.nested_payload_pages_num != 0){ - debug_printf("DUMPING global_state.protect_payload_buffer: %x\n", global_state.protect_payload_buffer); - fwrite(&global_state.protect_payload_buffer, sizeof(bool), 1, fp); - } - - for(uint32_t i = 0; i < global_state.nested_payload_pages_num; i++){ - debug_printf("DUMPING global_state.nested_payload_pages[%d]: %lx\n", i, global_state.nested_payload_pages[i]); - fwrite(&global_state.nested_payload_pages[i], sizeof(uint64_t), 1, fp); - } - } - - - fclose(fp); - - free(tmp); -} - -void load_global_state(const char* filename_prefix){ - debug_printf("%s\n", __func__); - - char* tmp; - - assert(asprintf(&tmp, "%s/global.state", filename_prefix) != -1); - debug_printf("%s\n", tmp); - - FILE *fp = fopen(tmp, "rb"); - if(fp == NULL) { - debug_fprintf(stderr, "[%s] Could not open file %s.\n", __func__, tmp); - assert(false); - //exit(EXIT_FAILURE); - } - - - assert(fread(&global_state.pt_ip_filter_configured, sizeof(bool)*4, 1, fp) == 1); - debug_printf("LOADING global_state.pt_ip_filter_configured: -\n"); - - assert(fread(&global_state.pt_ip_filter_a, sizeof(uint64_t)*4, 1, fp) == 1); - debug_printf("LOADING global_state.pt_ip_filter_a: -\n"); - - assert(fread(&global_state.pt_ip_filter_b, sizeof(uint64_t)*4, 1, fp) == 1); - debug_printf("LOADING global_state.pt_ip_filter_b: -\n"); - - assert(fread(&global_state.enable_hprintf, sizeof(bool), 1, fp) == 1); - debug_printf("LOADING global_state.enable_hprintf: %x\n", global_state.enable_hprintf); - - assert(fread(&global_state.parent_cr3, sizeof(uint64_t), 1, fp) == 1); - debug_printf("LOADING global_state.parent_cr3: %lx\n", global_state.parent_cr3); - - assert(fread(&global_state.disassembler_word_width, sizeof(uint8_t), 1, fp) == 1); - debug_printf("LOADING global_state.disassembler_word_width: %x\n", global_state.disassembler_word_width); - - assert(fread(&global_state.fast_reload_pre_image, sizeof(bool), 1, fp) == 1); - debug_printf("LOADING global_state.fast_reload_pre_image: %x\n", global_state.fast_reload_pre_image); - - assert(fread(&global_state.mem_mode, sizeof(uint8_t), 1, fp) == 1); - debug_printf("LOADING global_state.mem_mode: %x\n", global_state.mem_mode); - - assert(fread(&global_state.pt_trace_mode, sizeof(bool), 1, fp) == 1); - debug_printf("LOADING global_state.pt_trace_mode: %x\n", global_state.pt_trace_mode); - - assert(fread(&global_state.nested, sizeof(bool), 1, fp) == 1); - debug_printf("LOADING global_state.nested: %x\n", global_state.nested); - - if(!global_state.nested){ - assert(fread(&global_state.payload_buffer, sizeof(uint64_t), 1, fp) == 1); - debug_printf("LOADING global_state.payload_buffer: %lx\n", global_state.payload_buffer); - - assert(fread(&global_state.cap_timeout_detection, sizeof(global_state.cap_timeout_detection), 1, fp) == 1); - assert(fread(&global_state.cap_only_reload_mode, sizeof(global_state.cap_only_reload_mode), 1, fp) == 1); - assert(fread(&global_state.cap_compile_time_tracing, sizeof(global_state.cap_compile_time_tracing), 1, fp) == 1); - assert(fread(&global_state.cap_ijon_tracing, sizeof(global_state.cap_ijon_tracing), 1, fp) == 1); - assert(fread(&global_state.cap_cr3, sizeof(global_state.cap_cr3), 1, fp) == 1); - assert(fread(&global_state.cap_compile_time_tracing_buffer_vaddr, sizeof(global_state.cap_compile_time_tracing_buffer_vaddr), 1, fp) == 1); - assert(fread(&global_state.cap_ijon_tracing_buffer_vaddr, sizeof(global_state.cap_ijon_tracing_buffer_vaddr), 1, fp) == 1); - - if(!global_state.fast_reload_pre_image){ - assert(fread(&global_state.protect_payload_buffer, sizeof(bool), 1, fp) == 1); - if(global_state.payload_buffer != 0){ - debug_printf("REMAP PAYLOAD BUFFER!\n"); - remap_payload_buffer(global_state.payload_buffer, ((CPUState *)qemu_get_cpu(0)) ); - } - else{ - fprintf(stderr, "WARNING: address of payload buffer in snapshot file is zero!\n"); - } - } - - apply_capabilities(qemu_get_cpu(0)); - } - else{ - assert(fread(&global_state.nested_payload_pages_num, sizeof(uint32_t), 1, fp) == 1); - debug_printf("LOADING global_state.nested_payload_pages_num: %x\n", global_state.nested_payload_pages_num); - - global_state.in_fuzzing_mode = true; /* haaaeeeeh ??? */ - if(!global_state.fast_reload_pre_image){ - - assert(fread(&global_state.protect_payload_buffer, sizeof(bool), 1, fp) == 1); - debug_printf("LOADING global_state.protect_payload_buffer: %x\n", global_state.protect_payload_buffer); - - global_state.nested_payload_pages = (uint64_t*)malloc(sizeof(uint64_t)*global_state.nested_payload_pages_num); - - for(uint32_t i = 0; i < global_state.nested_payload_pages_num; i++){ - assert(fread(&global_state.nested_payload_pages[i], sizeof(uint64_t), 1, fp) == 1); - debug_printf("LOADED global_state.nested_payload_pages[%d]: %lx\n", i, global_state.nested_payload_pages[i]); - if(global_state.protect_payload_buffer){ - assert(remap_payload_slot_protected(GET_GLOBAL_STATE()->nested_payload_pages[i], i, ((CPUState *)qemu_get_cpu(0))) == true); - } - else{ - remap_payload_slot(global_state.nested_payload_pages[i], i, ((CPUState *)qemu_get_cpu(0))); - } - } - - } - } - - fclose(fp); - - free(tmp); -} - -static void* alloc_auxiliary_buffer(const char* file){ - void* ptr; - struct stat st; - int fd = open(file, O_CREAT|O_RDWR, S_IRWXU|S_IRWXG|S_IRWXO); - assert(ftruncate(fd, AUX_BUFFER_SIZE) == 0); - stat(file, &st); - QEMU_PT_PRINTF(INTERFACE_PREFIX, "new aux buffer file: (max size: %x) %lx", AUX_BUFFER_SIZE, st.st_size); - - assert(AUX_BUFFER_SIZE == st.st_size); - ptr = mmap(0, AUX_BUFFER_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (ptr == MAP_FAILED) { - fprintf(stderr, "aux buffer allocation failed!\n"); - return (void*)-1; - } - return ptr; -} - -void init_aux_buffer(const char* filename){ - global_state.auxilary_buffer = (auxilary_buffer_t*)alloc_auxiliary_buffer(filename); - init_auxiliary_buffer(global_state.auxilary_buffer); -} - -void set_payload_buffer(uint64_t payload_buffer){ - assert(global_state.payload_buffer == 0 && global_state.nested == false); - global_state.payload_buffer = payload_buffer; - global_state.nested = false; -} - -void set_payload_pages(uint64_t* payload_pages, uint32_t pages){ - assert(global_state.nested_payload_pages == NULL && global_state.nested_payload_pages_num == 0); - global_state.nested_payload_pages = (uint64_t*)malloc(sizeof(uint64_t)*pages); - global_state.nested_payload_pages_num = pages; - memcpy(global_state.nested_payload_pages, payload_pages, sizeof(uint64_t)*pages); - global_state.nested = true; -} - -void set_workdir_path(char* workdir){ - assert(workdir && !global_state.workdir_path); - assert(asprintf(&global_state.workdir_path, "%s", workdir) != -1); -} \ No newline at end of file diff --git a/nyx/state/snapshot_state.c b/nyx/state/snapshot_state.c new file mode 100644 index 0000000000..b45baa7ff4 --- /dev/null +++ b/nyx/state/snapshot_state.c @@ -0,0 +1,186 @@ + +#include "qemu/osdep.h" +#include "sysemu/cpus.h" +#include "nyx/state/snapshot_state.h" +#include "nyx/debug.h" +#include "nyx/state/state.h" +#include "nyx/memory_access.h" +#include + +void serialize_state(const char* filename_prefix, bool is_pre_snapshot){ + debug_printf("%s\n", __func__); + + char* tmp; + + assert(asprintf(&tmp, "%s/global.state", filename_prefix) != -1); + debug_printf("%s\n", tmp); + + FILE *fp = fopen(tmp, "wb"); + if(fp == NULL) { + debug_fprintf(stderr, "[%s] Could not open file %s.\n", __func__, tmp); + assert(false); + //exit(EXIT_FAILURE); + } + + qemu_nyx_state_t* nyx_global_state = GET_GLOBAL_STATE(); + + debug_printf("DUMPING global_state.pt_ip_filter_configured: -\n"); + fwrite(&nyx_global_state->pt_ip_filter_configured, sizeof(bool)*4, 1, fp); + + debug_printf("DUMPING global_state.pt_ip_filter_a: -\n"); + fwrite(&nyx_global_state->pt_ip_filter_a, sizeof(uint64_t)*4, 1, fp); + + debug_printf("DUMPING global_state.pt_ip_filter_b: -\n"); + fwrite(&nyx_global_state->pt_ip_filter_b, sizeof(uint64_t)*4, 1, fp); + + debug_printf("DUMPING global_state.parent_cr3: %lx\n", global_state.parent_cr3); + fwrite(&nyx_global_state->parent_cr3, sizeof(uint64_t), 1, fp); + + debug_printf("DUMPING global_state.disassembler_word_width: %x\n", global_state.disassembler_word_width); + fwrite(&nyx_global_state->disassembler_word_width, sizeof(uint8_t), 1, fp); + debug_printf("DUMPING global_state.fast_reload_pre_image: %x\n", global_state.fast_reload_pre_image); + fwrite(&nyx_global_state->fast_reload_pre_image, sizeof(bool), 1, fp); + + debug_printf("DUMPING global_state.mem_mode: %x\n", global_state.mem_mode); + fwrite(&nyx_global_state->mem_mode, sizeof(uint8_t), 1, fp); + + debug_printf("DUMPING global_state.pt_trace_mode: %x\n", global_state.pt_trace_mode); + fwrite(&nyx_global_state->pt_trace_mode, sizeof(bool), 1, fp); + + debug_printf("DUMPING global_state.nested: %x\n", global_state.nested); + fwrite(&nyx_global_state->nested, sizeof(bool), 1, fp); + + if(!global_state.nested){ + debug_printf("DUMPING global_state.payload_buffer: %lx\n", global_state.payload_buffer); + fwrite(&nyx_global_state->payload_buffer, sizeof(uint64_t), 1, fp); + + fwrite(&nyx_global_state->cap_timeout_detection, sizeof(global_state.cap_timeout_detection), 1, fp); + fwrite(&nyx_global_state->cap_only_reload_mode, sizeof(global_state.cap_only_reload_mode), 1, fp); + fwrite(&nyx_global_state->cap_compile_time_tracing, sizeof(global_state.cap_compile_time_tracing), 1, fp); + fwrite(&nyx_global_state->cap_ijon_tracing, sizeof(global_state.cap_ijon_tracing), 1, fp); + fwrite(&nyx_global_state->cap_cr3, sizeof(global_state.cap_cr3), 1, fp); + fwrite(&nyx_global_state->cap_compile_time_tracing_buffer_vaddr, sizeof(global_state.cap_compile_time_tracing_buffer_vaddr), 1, fp); + fwrite(&nyx_global_state->cap_ijon_tracing_buffer_vaddr, sizeof(global_state.cap_ijon_tracing_buffer_vaddr), 1, fp); + fwrite(&nyx_global_state->protect_payload_buffer, sizeof(bool), 1, fp); + } + else{ + assert(global_state.nested_payload_pages != NULL && global_state.nested_payload_pages_num != 0); + debug_printf("DUMPING global_state.nested_payload_pages_num: %x\n", global_state.nested_payload_pages_num); + fwrite(&nyx_global_state->nested_payload_pages_num, sizeof(uint32_t), 1, fp); + + if(global_state.nested_payload_pages_num != 0){ + debug_printf("DUMPING global_state.protect_payload_buffer: %x\n", global_state.protect_payload_buffer); + fwrite(&nyx_global_state->protect_payload_buffer, sizeof(bool), 1, fp); + } + + for(uint32_t i = 0; i < global_state.nested_payload_pages_num; i++){ + debug_printf("DUMPING global_state.nested_payload_pages[%d]: %lx\n", i, global_state.nested_payload_pages[i]); + fwrite(&nyx_global_state->nested_payload_pages[i], sizeof(uint64_t), 1, fp); + } + } + + + fclose(fp); + + free(tmp); +} + +void deserialize_state(const char* filename_prefix){ + debug_printf("%s\n", __func__); + + char* tmp; + + assert(asprintf(&tmp, "%s/global.state", filename_prefix) != -1); + debug_printf("%s\n", tmp); + + FILE *fp = fopen(tmp, "rb"); + if(fp == NULL) { + debug_fprintf(stderr, "[%s] Could not open file %s.\n", __func__, tmp); + assert(false); + //exit(EXIT_FAILURE); + } + + qemu_nyx_state_t* nyx_global_state = GET_GLOBAL_STATE(); + + assert(fread(&nyx_global_state->pt_ip_filter_configured, sizeof(bool)*4, 1, fp) == 1); + debug_printf("LOADING global_state.pt_ip_filter_configured: -\n"); + + assert(fread(&nyx_global_state->pt_ip_filter_a, sizeof(uint64_t)*4, 1, fp) == 1); + debug_printf("LOADING global_state.pt_ip_filter_a: -\n"); + + assert(fread(&nyx_global_state->pt_ip_filter_b, sizeof(uint64_t)*4, 1, fp) == 1); + debug_printf("LOADING global_state.pt_ip_filter_b: -\n"); + + assert(fread(&nyx_global_state->parent_cr3, sizeof(uint64_t), 1, fp) == 1); + debug_printf("LOADING global_state.parent_cr3: %lx\n", global_state.parent_cr3); + + assert(fread(&nyx_global_state->disassembler_word_width, sizeof(uint8_t), 1, fp) == 1); + debug_printf("LOADING global_state.disassembler_word_width: %x\n", global_state.disassembler_word_width); + + assert(fread(&nyx_global_state->fast_reload_pre_image, sizeof(bool), 1, fp) == 1); + debug_printf("LOADING global_state.fast_reload_pre_image: %x\n", global_state.fast_reload_pre_image); + + assert(fread(&nyx_global_state->mem_mode, sizeof(uint8_t), 1, fp) == 1); + debug_printf("LOADING global_state.mem_mode: %x\n", global_state.mem_mode); + + assert(fread(&nyx_global_state->pt_trace_mode, sizeof(bool), 1, fp) == 1); + debug_printf("LOADING global_state.pt_trace_mode: %x\n", global_state.pt_trace_mode); + + assert(fread(&nyx_global_state->nested, sizeof(bool), 1, fp) == 1); + debug_printf("LOADING global_state.nested: %x\n", global_state.nested); + + if(!global_state.nested){ + assert(fread(&nyx_global_state->payload_buffer, sizeof(uint64_t), 1, fp) == 1); + debug_printf("LOADING global_state.payload_buffer: %lx\n", global_state.payload_buffer); + + assert(fread(&nyx_global_state->cap_timeout_detection, sizeof(global_state.cap_timeout_detection), 1, fp) == 1); + assert(fread(&nyx_global_state->cap_only_reload_mode, sizeof(global_state.cap_only_reload_mode), 1, fp) == 1); + assert(fread(&nyx_global_state->cap_compile_time_tracing, sizeof(global_state.cap_compile_time_tracing), 1, fp) == 1); + assert(fread(&nyx_global_state->cap_ijon_tracing, sizeof(global_state.cap_ijon_tracing), 1, fp) == 1); + assert(fread(&nyx_global_state->cap_cr3, sizeof(global_state.cap_cr3), 1, fp) == 1); + assert(fread(&nyx_global_state->cap_compile_time_tracing_buffer_vaddr, sizeof(global_state.cap_compile_time_tracing_buffer_vaddr), 1, fp) == 1); + assert(fread(&nyx_global_state->cap_ijon_tracing_buffer_vaddr, sizeof(global_state.cap_ijon_tracing_buffer_vaddr), 1, fp) == 1); + + if(!global_state.fast_reload_pre_image){ + assert(fread(&nyx_global_state->protect_payload_buffer, sizeof(bool), 1, fp) == 1); + if(global_state.payload_buffer != 0){ + debug_printf("REMAP PAYLOAD BUFFER!\n"); + remap_payload_buffer(global_state.payload_buffer, ((CPUState *)qemu_get_cpu(0)) ); + } + else{ + fprintf(stderr, "WARNING: address of payload buffer in snapshot file is zero!\n"); + } + } + + assert(apply_capabilities(qemu_get_cpu(0))); + } + else{ + assert(fread(&nyx_global_state->nested_payload_pages_num, sizeof(uint32_t), 1, fp) == 1); + debug_printf("LOADING global_state.nested_payload_pages_num: %x\n", global_state.nested_payload_pages_num); + + global_state.in_fuzzing_mode = true; /* haaaeeeeh ??? */ + if(!global_state.fast_reload_pre_image){ + + assert(fread(&nyx_global_state->protect_payload_buffer, sizeof(bool), 1, fp) == 1); + debug_printf("LOADING global_state.protect_payload_buffer: %x\n", global_state.protect_payload_buffer); + + global_state.nested_payload_pages = (uint64_t*)malloc(sizeof(uint64_t)*global_state.nested_payload_pages_num); + + for(uint32_t i = 0; i < global_state.nested_payload_pages_num; i++){ + assert(fread(&nyx_global_state->nested_payload_pages[i], sizeof(uint64_t), 1, fp) == 1); + debug_printf("LOADED global_state.nested_payload_pages[%d]: %lx\n", i, global_state.nested_payload_pages[i]); + if(global_state.protect_payload_buffer){ + assert(remap_payload_slot_protected(GET_GLOBAL_STATE()->nested_payload_pages[i], i, ((CPUState *)qemu_get_cpu(0))) == true); + } + else{ + remap_payload_slot(global_state.nested_payload_pages[i], i, ((CPUState *)qemu_get_cpu(0))); + } + } + + } + } + + fclose(fp); + + free(tmp); +} \ No newline at end of file diff --git a/nyx/state/snapshot_state.h b/nyx/state/snapshot_state.h new file mode 100644 index 0000000000..397c05e01e --- /dev/null +++ b/nyx/state/snapshot_state.h @@ -0,0 +1,6 @@ +#pragma once + +#include + +void serialize_state(const char* filename_prefix, bool is_pre_snapshot); +void deserialize_state(const char* filename_prefix); diff --git a/nyx/state/state.c b/nyx/state/state.c new file mode 100644 index 0000000000..9a2c827f01 --- /dev/null +++ b/nyx/state/state.c @@ -0,0 +1,233 @@ +/* + +Copyright (C) 2019 Sergej Schumilo + +This file is part of QEMU-PT (HyperTrash / kAFL). + +QEMU-PT is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +QEMU-PT is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with QEMU-PT. If not, see . + +*/ + +#include "nyx/state/state.h" +#include "nyx/debug.h" +#include "nyx/memory_access.h" +#include "sysemu/kvm.h" +#include "nyx/auxiliary_buffer.h" +#include "nyx/sharedir.h" +#include "nyx/fast_vm_reload_sync.h" +#include "nyx/helpers.h" + +//#define STATE_VERBOSE + +/* global singleton */ +qemu_nyx_state_t global_state; + +#define LIBXDC_RELEASE_VERSION_REQUIRED 2 + +void state_init_global(void){ +#ifdef STATE_VERBOSE + fprintf(stderr, "--> %s <--\n", __func__); +#endif + /* safety first */ + assert(libxdc_get_release_version() == LIBXDC_RELEASE_VERSION_REQUIRED); + + global_state.nyx_fdl = false; + + global_state.workdir_path = NULL; + + global_state.fast_reload_enabled = false; + global_state.fast_reload_mode = false; + global_state.fast_reload_path = NULL; + global_state.fast_reload_pre_path = NULL; + global_state.fast_reload_pre_image = false; + + global_state.fast_reload_snapshot = fast_reload_new(); + global_state.reload_state = init_fast_vm_reload_sync(); + + global_state.decoder = NULL; + + global_state.page_cache = NULL; + + global_state.redqueen_enable_pending = false; + global_state.redqueen_disable_pending = false; + global_state.redqueen_instrumentation_mode = 0; + global_state.redqueen_update_blacklist = false; + global_state.patches_enable_pending = false; + global_state.patches_disable_pending = false; + global_state.redqueen_state = NULL; + + for(uint8_t i = 0; i < INTEL_PT_MAX_RANGES; i++){ + global_state.pt_ip_filter_configured[i] = false; + global_state.pt_ip_filter_enabled[i] = false; + global_state.pt_ip_filter_a[i] = 0x0; + global_state.pt_ip_filter_b[i] = 0x0; + } + global_state.pt_c3_filter = 0; + + global_state.parent_cr3 = 0; + global_state.disassembler_word_width = 64; + global_state.nested = false; + global_state.payload_buffer = 0; + global_state.nested_payload_pages = NULL; + global_state.nested_payload_pages_num = 0; + global_state.protect_payload_buffer = 0; + global_state.discard_tmp_snapshot = 0; + global_state.mem_mode = mm_unkown; + + init_timeout_detector(&(global_state.timeout_detector)); + + global_state.in_fuzzing_mode = false; + global_state.in_reload_mode = true; + global_state.shutdown_requested = false; + global_state.cow_cache_full = false; + + global_state.auxilary_buffer = NULL; + memset(&global_state.shadow_config, 0x0, sizeof(auxilary_buffer_config_t)); + + global_state.decoder_page_fault = false; + global_state.decoder_page_fault_addr = 0x0; + + global_state.dump_page = false; + global_state.dump_page_addr = 0x0; + + global_state.in_redqueen_reload_mode = false; + + global_state.pt_trace_mode = true; + global_state.pt_trace_mode_force = false; + + global_state.num_dirty_pages = 0; + + global_state.sharedir = sharedir_new(); + + + global_state.shared_bitmap_fd = 0; + global_state.shared_bitmap_size = 0; + global_state.shared_bitmap_real_size = 0; + global_state.shared_bitmap_ptr = NULL; + + global_state.shared_payload_buffer_fd = 0; + global_state.shared_payload_buffer_size = 0; + + global_state.shared_ijon_bitmap_fd = 0; + global_state.shared_ijon_bitmap_size = 0; + global_state.shared_ijon_bitmap_ptr = NULL; + + global_state.pt_trace_size = 0; + global_state.bb_coverage = 0; + + global_state.cap_timeout_detection = 0; + global_state.cap_only_reload_mode = 0; + global_state.cap_compile_time_tracing = 0; + global_state.cap_ijon_tracing = 0; + global_state.cap_cr3 = 0; + global_state.cap_compile_time_tracing_buffer_vaddr = 0; + global_state.cap_ijon_tracing_buffer_vaddr = 0; + + QTAILQ_INIT(&global_state.redqueen_breakpoints); +} + + +fast_reload_t* get_fast_reload_snapshot(void){ + return global_state.fast_reload_snapshot; +} + +void set_fast_reload_mode(bool mode){ + global_state.fast_reload_mode = mode; +} + +void set_fast_reload_path(const char* path){ + assert(global_state.fast_reload_path == NULL); + global_state.fast_reload_path = malloc(strlen(path)+1); + strcpy(global_state.fast_reload_path, path); +} + +void set_fast_reload_pre_path(const char* path){ + assert(global_state.fast_reload_pre_path == NULL); + global_state.fast_reload_pre_path = malloc(strlen(path)+1); + strcpy(global_state.fast_reload_pre_path, path); +} + +void set_fast_reload_pre_image(void){ + assert(global_state.fast_reload_pre_path != NULL); + global_state.fast_reload_pre_image = true; +} + +void enable_fast_reloads(void){ + assert(global_state.fast_reload_path != NULL); + global_state.fast_reload_enabled = true; +} + +void init_page_cache(char* path){ + assert(global_state.page_cache == NULL); + global_state.page_cache = page_cache_new((CPUState *)qemu_get_cpu(0), path); + #ifdef STATE_VERBOSE + debug_printf("\n\nINIT PAGE_CACHE => %s\n", path); + #endif +} + +page_cache_t* get_page_cache(void){ + assert(global_state.page_cache); + return global_state.page_cache; +} + +void init_redqueen_state(void){ + global_state.redqueen_state = new_rq_state((CPUState *)qemu_get_cpu(0), get_page_cache()); +} + + +redqueen_t* get_redqueen_state(void){ + assert(global_state.redqueen_state != NULL); + return global_state.redqueen_state; +} + +static void* alloc_auxiliary_buffer(const char* file){ + void* ptr; + struct stat st; + int fd = open(file, O_CREAT|O_RDWR, S_IRWXU|S_IRWXG|S_IRWXO); + assert(ftruncate(fd, AUX_BUFFER_SIZE) == 0); + stat(file, &st); + QEMU_PT_PRINTF(INTERFACE_PREFIX, "new aux buffer file: (max size: %x) %lx", AUX_BUFFER_SIZE, st.st_size); + + assert(AUX_BUFFER_SIZE == st.st_size); + ptr = mmap(0, AUX_BUFFER_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (ptr == MAP_FAILED) { + fprintf(stderr, "aux buffer allocation failed!\n"); + return (void*)-1; + } + return ptr; +} + +void init_aux_buffer(const char* filename){ + global_state.auxilary_buffer = (auxilary_buffer_t*)alloc_auxiliary_buffer(filename); + init_auxiliary_buffer(global_state.auxilary_buffer); +} + +void set_payload_buffer(uint64_t payload_buffer){ + assert(global_state.payload_buffer == 0 && global_state.nested == false); + global_state.payload_buffer = payload_buffer; + global_state.nested = false; +} + +void set_payload_pages(uint64_t* payload_pages, uint32_t pages){ + assert(global_state.nested_payload_pages == NULL && global_state.nested_payload_pages_num == 0); + global_state.nested_payload_pages = (uint64_t*)malloc(sizeof(uint64_t)*pages); + global_state.nested_payload_pages_num = pages; + memcpy(global_state.nested_payload_pages, payload_pages, sizeof(uint64_t)*pages); + global_state.nested = true; +} + +void set_workdir_path(char* workdir){ + assert(workdir && !global_state.workdir_path); + assert(asprintf(&global_state.workdir_path, "%s", workdir) != -1); +} \ No newline at end of file diff --git a/nyx/state.h b/nyx/state/state.h similarity index 93% rename from nyx/state.h rename to nyx/state/state.h index 79261b0c0b..79d4ec54d7 100644 --- a/nyx/state.h +++ b/nyx/state/state.h @@ -43,7 +43,7 @@ enum mem_mode { mm_64_l5_paging, /* 32 Bit / L5 Paging */ }; -struct state_qemu_pt{ +typedef struct qemu_nyx_state_s{ /* set if FDL backend is used (required to perform some additional runtime tests) */ bool nyx_fdl; @@ -91,11 +91,16 @@ struct state_qemu_pt{ /* mmap Options (not migratable) */ int shared_bitmap_fd; - uint32_t shared_bitmap_size; - uint32_t shared_ijon_bitmap_size; + uint32_t shared_bitmap_size; /* size of the shared memory file */ + uint32_t shared_bitmap_real_size; /* actual size of the bitmap */ + void* shared_bitmap_ptr; + int shared_payload_buffer_fd; uint32_t shared_payload_buffer_size; - void* shared_bitmap_ptr; + + int shared_ijon_bitmap_fd; + uint32_t shared_ijon_bitmap_size; + void* shared_ijon_bitmap_ptr; /* Intel PT Options (migratable) */ bool pt_ip_filter_configured[4]; @@ -103,7 +108,6 @@ struct state_qemu_pt{ uint64_t pt_ip_filter_b[4]; /* OPTIONS (MIGRATABLE VIA FAST SNAPSHOTS) */ - bool enable_hprintf; uint64_t parent_cr3; uint8_t disassembler_word_width; bool nested; @@ -132,6 +136,8 @@ struct state_qemu_pt{ bool in_redqueen_reload_mode; + uint32_t num_dirty_pages; + /* capabilites */ uint8_t cap_timeout_detection; uint8_t cap_only_reload_mode; @@ -146,9 +152,9 @@ struct state_qemu_pt{ sharedir_t* sharedir; QTAILQ_HEAD(, kvm_sw_breakpoint) redqueen_breakpoints; -}; +} qemu_nyx_state_t; -extern struct state_qemu_pt global_state; +extern qemu_nyx_state_t global_state; #define GET_GLOBAL_STATE() (&global_state) @@ -169,9 +175,6 @@ void init_redqueen_state(void); redqueen_t* get_redqueen_state(void); -void dump_global_state(const char* filename_prefix); -void load_global_state(const char* filename_prefix); - void init_aux_buffer(const char* filename); void set_fast_reload_pre_path(const char* path); diff --git a/nyx/synchronization.c b/nyx/synchronization.c index c3d1423117..ad279dbbbe 100644 --- a/nyx/synchronization.c +++ b/nyx/synchronization.c @@ -8,7 +8,7 @@ #include "sysemu/sysemu.h" #include "sysemu/kvm.h" #include "nyx/debug.h" -#include "nyx/state.h" +#include "nyx/state/state.h" #include #include #include "qemu/main-loop.h" @@ -214,6 +214,7 @@ static inline bool synchronization_check_page_not_found(void){ kvm_remove_all_breakpoints(qemu_get_cpu(0)); kvm_vcpu_ioctl(qemu_get_cpu(0), KVM_VMX_PT_DISABLE_PAGE_DUMP_CR3); kvm_vcpu_ioctl(qemu_get_cpu(0), KVM_VMX_PT_DISABLE_MTF); + reset_page_not_found_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer); failure = true; } @@ -241,9 +242,6 @@ void synchronization_lock_hprintf(void){ pthread_cond_wait(&synchronization_lock_condition, &synchronization_lock_mutex); pthread_mutex_unlock(&synchronization_lock_mutex); - - flush_hprintf_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer); - } void synchronization_lock(void){ @@ -255,7 +253,8 @@ void synchronization_lock(void){ } set_exec_done_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer, GET_GLOBAL_STATE()->timeout_detector.timeout_sec - GET_GLOBAL_STATE()->timeout_detector.arm_timeout.it_value.tv_sec, - GET_GLOBAL_STATE()->timeout_detector.timeout_usec - (uint32_t)GET_GLOBAL_STATE()->timeout_detector.arm_timeout.it_value.tv_usec); + GET_GLOBAL_STATE()->timeout_detector.timeout_usec - (uint32_t)GET_GLOBAL_STATE()->timeout_detector.arm_timeout.it_value.tv_usec, + GET_GLOBAL_STATE()->num_dirty_pages); /* if(last_timeout){ reset_timeout_detector_timeout(&(GET_GLOBAL_STATE()->timeout_detector)); @@ -291,7 +290,6 @@ void synchronization_lock(void){ pthread_cond_wait(&synchronization_lock_condition, &synchronization_lock_mutex); pthread_mutex_unlock(&synchronization_lock_mutex); - flush_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer); check_auxiliary_config_buffer(GET_GLOBAL_STATE()->auxilary_buffer, &GET_GLOBAL_STATE()->shadow_config); set_success_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer, 1); @@ -337,25 +335,6 @@ void synchronization_lock_crash_found(void){ in_fuzzing_loop = false; } -void synchronization_lock_asan_found(void){ - if(!in_fuzzing_loop){ - fprintf(stderr, "<%d-%ld>\t%s [NOT IN FUZZING LOOP]\n", getpid(), run_counter, __func__); - set_success_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer, 0); - } - - pt_disable(qemu_get_cpu(0), false); - - handle_tmp_snapshot_state(); - - set_asan_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer); - - perform_reload(); - - //synchronization_lock(); - - in_fuzzing_loop = false; -} - void synchronization_lock_timeout_found(void){ //fprintf(stderr, "<%d>\t%s\n", getpid(), __func__); diff --git a/nyx/synchronization.h b/nyx/synchronization.h index 8f378a8c69..7cd7ef902f 100644 --- a/nyx/synchronization.h +++ b/nyx/synchronization.h @@ -37,7 +37,6 @@ void synchronization_lock_hprintf(void); void synchronization_lock(void); void synchronization_lock_crash_found(void); -void synchronization_lock_asan_found(void); void synchronization_lock_timeout_found(void); void synchronization_lock_shutdown_detected(void); void synchronization_cow_full_detected(void); diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 2ee9da4aea..5a347cbba4 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -60,7 +60,7 @@ #endif #ifdef QEMU_NYX -#include "nyx/state.h" +#include "nyx/state/state.h" #endif #include "disas/capstone.h" diff --git a/vl.c b/vl.c index 13301802c9..10149b9f26 100644 --- a/vl.c +++ b/vl.c @@ -137,7 +137,7 @@ int main(int argc, char **argv) #include "nyx/hypercall/hypercall.h" #include "nyx/synchronization.h" #include "nyx/fast_vm_reload.h" -#include "nyx/state.h" +#include "nyx/state/state.h" #include "nyx/fast_vm_reload_sync.h" #endif