add several improvements:
- Intel PT page dump feature works now - size of input and bitmap buffers are configurable - new aux buffer layout - various bug fixes
This commit is contained in:
parent
646c85021e
commit
42d434e28f
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
2
memory.c
2
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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -23,7 +23,7 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -37,6 +37,15 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#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);
|
||||
|
@ -47,7 +47,8 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#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);
|
||||
|
||||
|
@ -35,6 +35,7 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
#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);
|
||||
|
@ -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:
|
||||
|
@ -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){
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include <sys/time.h>
|
||||
#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
|
||||
|
@ -30,8 +30,6 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#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 <http://www.gnu.org/licenses/>.
|
||||
#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 <http://www.gnu.org/licenses/>.
|
||||
#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;
|
||||
|
||||
|
@ -22,7 +22,6 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
#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);
|
||||
|
@ -48,7 +48,7 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "nyx/snapshot/devices/state_reallocation.h"
|
||||
#include "nyx/memory_access.h"
|
||||
#include <sys/ioctl.h>
|
||||
#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),
|
||||
|
||||
|
||||
|
@ -23,15 +23,10 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
#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);
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -30,7 +30,7 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
#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;
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
/*
|
||||
|
@ -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];
|
||||
|
104
nyx/printk.c
104
nyx/printk.c
@ -1,104 +0,0 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include <linux/kvm.h>
|
||||
#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;
|
||||
|
||||
}
|
28
nyx/printk.h
28
nyx/printk.h
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef PRINTK_H
|
||||
#define PRINTK_H
|
||||
|
||||
bool kafl_linux_printk(CPUState *cpu);
|
||||
|
||||
|
||||
#endif
|
6
nyx/pt.c
6
nyx/pt.c
@ -38,7 +38,7 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "nyx/redqueen_patch.h"
|
||||
#include "nyx/patcher.h"
|
||||
#include "nyx/page_cache.h"
|
||||
#include "nyx/state.h"
|
||||
#include "nyx/state/state.h"
|
||||
#include <libxdc.h>
|
||||
#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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -28,7 +28,7 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "patcher.h"
|
||||
#include "debug.h"
|
||||
#include "redqueen_trace.h"
|
||||
#include "nyx/state.h"
|
||||
#include "nyx/state/state.h"
|
||||
#include <capstone/capstone.h>
|
||||
#include <capstone/x86.h>
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include <sys/mman.h>
|
||||
#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
|
||||
|
@ -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;
|
||||
|
@ -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){
|
||||
|
@ -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);
|
||||
|
@ -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){
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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) */
|
||||
|
@ -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);
|
||||
|
@ -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){
|
||||
|
409
nyx/state.c
409
nyx/state.c
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
186
nyx/state/snapshot_state.c
Normal file
186
nyx/state/snapshot_state.c
Normal file
@ -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 <stdio.h>
|
||||
|
||||
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);
|
||||
}
|
6
nyx/state/snapshot_state.h
Normal file
6
nyx/state/snapshot_state.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
void serialize_state(const char* filename_prefix, bool is_pre_snapshot);
|
||||
void deserialize_state(const char* filename_prefix);
|
233
nyx/state/state.c
Normal file
233
nyx/state/state.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
@ -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);
|
||||
|
@ -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 <sys/syscall.h>
|
||||
#include <linux/kvm.h>
|
||||
#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__);
|
||||
|
@ -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);
|
||||
|
@ -60,7 +60,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef QEMU_NYX
|
||||
#include "nyx/state.h"
|
||||
#include "nyx/state/state.h"
|
||||
#endif
|
||||
|
||||
#include "disas/capstone.h"
|
||||
|
Loading…
x
Reference in New Issue
Block a user