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.
This commit is contained in:
Sergej Schumilo 2022-02-23 10:26:02 +01:00
parent b95d6b9236
commit 1f675b053a
5 changed files with 58 additions and 32 deletions

View File

@ -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 {
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 {
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;
}
}
}

View File

@ -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;
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 */

View File

@ -26,6 +26,7 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
#include <linux/kvm.h>
#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 <http://www.gnu.org/licenses/>.
#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);

View File

@ -29,20 +29,12 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
#include "nyx/auxiliary_buffer.h"
#include "nyx/sharedir.h"
#include "nyx/fast_vm_reload_sync.h"
#include "nyx/types.h"
#include <libxdc.h>
#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;

12
nyx/types.h Normal file
View File

@ -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;