From 1f675b053a86125945cdc1fa6985d76015a01520 Mon Sep 17 00:00:00 2001 From: Sergej Schumilo Date: Wed, 23 Feb 2022 10:26:02 +0100 Subject: [PATCH] fix crash notifier injection Decide which crash notifier (32bit or 64bit) to inject, based on the current memory mode instead of the current CPU mode. Otherwise, in the case of a 32bit loader running on a 64bit operating system, the wrong notifier code will be injected. --- nyx/hypercall/hypercall.c | 36 ++++++++++++++++++++++++++++-------- nyx/memory_access.c | 27 +++++++++++++-------------- nyx/memory_access.h | 3 +++ nyx/state/state.h | 12 ++---------- nyx/types.h | 12 ++++++++++++ 5 files changed, 58 insertions(+), 32 deletions(-) create mode 100644 nyx/types.h diff --git a/nyx/hypercall/hypercall.c b/nyx/hypercall/hypercall.c index 7d26c74469..f091a16981 100644 --- a/nyx/hypercall/hypercall.c +++ b/nyx/hypercall/hypercall.c @@ -442,10 +442,20 @@ static void handle_hypercall_kafl_submit_panic(struct kvm_run *run, CPUState *cp if(hypercall_enabled){ QEMU_PT_PRINTF(CORE_PREFIX, "Panic address:\t%lx", hypercall_arg); - if (run->hypercall.longmode) { - write_virtual_memory(hypercall_arg, (uint8_t*)PANIC_PAYLOAD_64, PAYLOAD_BUFFER_SIZE_64, cpu); - } else { - write_virtual_memory(hypercall_arg, (uint8_t*)PANIC_PAYLOAD_32, PAYLOAD_BUFFER_SIZE_32, cpu); + + switch (get_current_mem_mode(cpu)){ + case mm_32_protected: + case mm_32_paging: + case mm_32_pae: + write_virtual_memory(hypercall_arg, (uint8_t*)PANIC_PAYLOAD_32, PAYLOAD_BUFFER_SIZE_32, cpu); + break; + case mm_64_l4_paging: + case mm_64_l5_paging: + write_virtual_memory(hypercall_arg, (uint8_t*)PANIC_PAYLOAD_64, PAYLOAD_BUFFER_SIZE_64, cpu); + break; + default: + abort(); + break; } } } @@ -453,10 +463,20 @@ static void handle_hypercall_kafl_submit_panic(struct kvm_run *run, CPUState *cp 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 (run->hypercall.longmode){ - write_virtual_memory(hypercall_arg, (uint8_t*)KASAN_PAYLOAD_64, PAYLOAD_BUFFER_SIZE_64, cpu); - } else { - write_virtual_memory(hypercall_arg, (uint8_t*)KASAN_PAYLOAD_32, PAYLOAD_BUFFER_SIZE_32, cpu); + + switch (get_current_mem_mode(cpu)){ + case mm_32_protected: + case mm_32_paging: + case mm_32_pae: + write_virtual_memory(hypercall_arg, (uint8_t*)KASAN_PAYLOAD_32, PAYLOAD_BUFFER_SIZE_32, cpu); + break; + case mm_64_l4_paging: + case mm_64_l5_paging: + write_virtual_memory(hypercall_arg, (uint8_t*)KASAN_PAYLOAD_64, PAYLOAD_BUFFER_SIZE_64, cpu); + break; + default: + abort(); + break; } } } diff --git a/nyx/memory_access.c b/nyx/memory_access.c index 158f46a8ff..bf3ae92280 100644 --- a/nyx/memory_access.c +++ b/nyx/memory_access.c @@ -41,39 +41,38 @@ static uint64_t get_48_paging_phys_addr(uint64_t cr3, uint64_t addr, bool read_f #define x86_64_PAGE_SIZE 0x1000 #define x86_64_PAGE_MASK ~(x86_64_PAGE_SIZE - 1) -static void set_mem_mode(CPUState *cpu){ +mem_mode_t get_current_mem_mode(CPUState *cpu){ kvm_arch_get_registers(cpu); X86CPU *cpux86 = X86_CPU(cpu); CPUX86State *env = &cpux86->env; - - if (!(env->cr[0] & CR0_PG_MASK)) { - GET_GLOBAL_STATE()->mem_mode = mm_32_protected; - return; + + if (!(env->cr[0] & CR0_PG_MASK)) { + return mm_32_protected; } else{ if (env->cr[4] & CR4_PAE_MASK) { if (env->hflags & HF_LMA_MASK) { if (env->cr[4] & CR4_LA57_MASK) { - GET_GLOBAL_STATE()->mem_mode = mm_64_l5_paging; - return; + return mm_64_l5_paging; } else { - GET_GLOBAL_STATE()->mem_mode = mm_64_l4_paging; - return; + return mm_64_l4_paging; } } else{ - GET_GLOBAL_STATE()->mem_mode = mm_32_pae; - return; + return mm_32_pae; } } else { - GET_GLOBAL_STATE()->mem_mode = mm_32_paging; - return; + return mm_32_paging; } } - return; + return mm_unkown; +} + +static void set_mem_mode(CPUState *cpu){ + GET_GLOBAL_STATE()->mem_mode = get_current_mem_mode(cpu); } /* Warning: This might break memory handling for hypervisor fuzzing => FIXME LATER */ diff --git a/nyx/memory_access.h b/nyx/memory_access.h index 893f59982a..496acc1473 100644 --- a/nyx/memory_access.h +++ b/nyx/memory_access.h @@ -26,6 +26,7 @@ along with QEMU-PT. If not, see . #include #include "qemu-common.h" #include "sysemu/kvm_int.h" +#include "nyx/types.h" #define MEM_SPLIT_START 0x0C0000000 #define MEM_SPLIT_END 0x100000000 @@ -34,6 +35,8 @@ along with QEMU-PT. If not, see . #define address_to_ram_offset(offset) (offset >= MEM_SPLIT_END ? (offset - MEM_SPLIT_END) + MEM_SPLIT_START : offset) #define ram_offset_to_address(offset) (offset >= MEM_SPLIT_START ? (offset - MEM_SPLIT_START) + MEM_SPLIT_END : offset) +mem_mode_t get_current_mem_mode(CPUState *cpu); + uint64_t get_paging_phys_addr(CPUState *cpu, uint64_t cr3, uint64_t addr); bool read_physical_memory(uint64_t address, uint8_t* data, uint32_t size, CPUState *cpu); diff --git a/nyx/state/state.h b/nyx/state/state.h index e634d7375e..e434c30724 100644 --- a/nyx/state/state.h +++ b/nyx/state/state.h @@ -29,20 +29,12 @@ along with QEMU-PT. If not, see . #include "nyx/auxiliary_buffer.h" #include "nyx/sharedir.h" #include "nyx/fast_vm_reload_sync.h" +#include "nyx/types.h" #include #define INTEL_PT_MAX_RANGES 4 -enum mem_mode { - mm_unkown, - mm_32_protected, /* 32 Bit / No MMU */ - mm_32_paging, /* 32 Bit / L3 Paging */ - mm_32_pae, /* 32 Bit / PAE Paging */ - mm_64_l4_paging, /* 64 Bit / L4 Paging */ - mm_64_l5_paging, /* 32 Bit / L5 Paging */ -}; - typedef struct qemu_nyx_state_s{ /* set if FDL backend is used (required to perform some additional runtime tests) */ @@ -117,7 +109,7 @@ typedef struct qemu_nyx_state_s{ uint64_t* nested_payload_pages; bool protect_payload_buffer; bool discard_tmp_snapshot; - uint8_t mem_mode; + mem_mode_t mem_mode; uint32_t input_buffer_size; diff --git a/nyx/types.h b/nyx/types.h new file mode 100644 index 0000000000..7c15f8ee72 --- /dev/null +++ b/nyx/types.h @@ -0,0 +1,12 @@ +#pragma once + +enum mem_mode { + mm_unkown, + mm_32_protected, /* 32 Bit / No MMU */ + mm_32_paging, /* 32 Bit / L3 Paging */ + mm_32_pae, /* 32 Bit / PAE Paging */ + mm_64_l4_paging, /* 64 Bit / L4 Paging */ + mm_64_l5_paging, /* 32 Bit / L5 Paging */ +}; + +typedef uint8_t mem_mode_t;