From bf5fb5530cafb71d2681bce1696cda783f541fd8 Mon Sep 17 00:00:00 2001 From: leecher1337 Date: Sun, 10 Mar 2019 15:41:08 +0100 Subject: [PATCH 01/11] Added fucntionality for BOPping needed for NTVDM --- core/include/vm.h | 3 ++- core/vcpu.c | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/core/include/vm.h b/core/include/vm.h index 08e33849..5a38c4aa 100644 --- a/core/include/vm.h +++ b/core/include/vm.h @@ -111,7 +111,8 @@ enum exit_status { HAX_EXIT_PAUSED, HAX_EXIT_FAST_MMIO, HAX_EXIT_PAGEFAULT, - HAX_EXIT_DEBUG + HAX_EXIT_DEBUG, + HAX_EXIT_OPCODE }; enum run_flag { diff --git a/core/vcpu.c b/core/vcpu.c index 545beaa6..e43ee356 100644 --- a/core/vcpu.c +++ b/core/vcpu.c @@ -1937,6 +1937,9 @@ static void vmwrite_cr(struct vcpu_t *vcpu) ~(cr0_fixed_0 ^ cr0_fixed_1); } + // leecher1337 + exc_bitmap |= 1u << VECTOR_UD; + if (vtlb_active(vcpu)) { hax_debug("vTLB mode, cr0 %llx\n", vcpu->state->_cr0); vcpu->mmu->mmu_mode = MMU_MODE_VTLB; @@ -2387,6 +2390,15 @@ static int exit_exc_nmi(struct vcpu_t *vcpu, struct hax_tunnel *htun) htun->debug.dr7 = 0; return HAX_EXIT; } + // leecher1337 + case VECTOR_UD: { + uint64_t va; + + htun->_exit_status = HAX_EXIT_OPCODE; + va = vcpu->state->_cs.long_mode == 1 ? vcpu->state->_rip : vcpu->state->_cs.base + vcpu->state->_rip; + vcpu_read_guest_virtual(vcpu, va, vcpu->io_buf, INSTR_MAX_LEN, INSTR_MAX_LEN, 0); + return HAX_EXIT; + } } if (exit_intr_info.vector == VECTOR_PF) { From ccdf4084b93b1141de8d340247fc2ef2e55418ef Mon Sep 17 00:00:00 2001 From: leecher1337 Date: Sun, 10 Mar 2019 19:06:11 +0100 Subject: [PATCH 02/11] Let caller know about the shutdown reason. Is it VMX_EXIT_FAILED_VMENTER_GS, is it VMX_EXIT_TRIPLE_FAULT? We want to know! --- core/cpu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/core/cpu.c b/core/cpu.c index f6c07bd2..3869426a 100644 --- a/core/cpu.c +++ b/core/cpu.c @@ -222,6 +222,7 @@ bool vcpu_is_panic(struct vcpu_t *vcpu) if (vcpu->panicked) { hax_error("vcpu has panicked, id:%d\n", vcpu->vcpu_id); hax_panic_log(vcpu); + htun->_exit_reason = vmx(vcpu, exit_reason).basic_reason; htun->_exit_status = HAX_EXIT_STATECHANGE; return 1; } From 06ab1fe1bc83ae8bae0d920488b242cc0ae09f62 Mon Sep 17 00:00:00 2001 From: leecher1337 Date: Sat, 16 Mar 2019 13:38:33 +0100 Subject: [PATCH 03/11] Fix for VMX_EXIT_FAILED_VMENTER_GS when entering VM after a STI on HAX_DEBUG_ENABLE --- core/vcpu.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/vcpu.c b/core/vcpu.c index e43ee356..43487307 100644 --- a/core/vcpu.c +++ b/core/vcpu.c @@ -1070,6 +1070,11 @@ static void load_dirty_vmcs_fields(struct vcpu_t *vcpu) vcpu->rflags_dirty = 1; vcpu->debug_control_dirty = 0; } + if ((vcpu->debug_control & HAX_DEBUG_STEP) && + (vmx(vcpu, interruptibility_state).raw & 3u)) { + vmx(vcpu, interruptibility_state).raw &= ~3u; + vcpu->interruptibility_dirty = 1; + } if (vcpu->rflags_dirty) { vmwrite(vcpu, GUEST_RFLAGS, state->_rflags); vcpu->rflags_dirty = 0; From 9dce9fcfa3971b4d22b72a0e42d42febf06aacdf Mon Sep 17 00:00:00 2001 From: leecher1337 Date: Fri, 19 Apr 2019 00:10:08 +0200 Subject: [PATCH 04/11] Make generic interface to define custom Exception bitmaps that return to supervisor. This is i.e. needed for BOPping in NTVDM (VECTOR_UD) or for Interrupt hooking (VERTOR_NP). So this generic call could be useful for hypervisors. --- core/include/hax_core_interface.h | 1 + core/include/vcpu.h | 3 +++ core/include/vm.h | 2 +- core/vcpu.c | 19 +++++++++++++------ include/hax_interface.h | 3 +++ platforms/windows/hax_entry.c | 4 ++++ platforms/windows/hax_entry.h | 3 +++ 7 files changed, 28 insertions(+), 7 deletions(-) diff --git a/core/include/hax_core_interface.h b/core/include/hax_core_interface.h index aa836d66..61776584 100644 --- a/core/include/hax_core_interface.h +++ b/core/include/hax_core_interface.h @@ -95,6 +95,7 @@ struct vm_t * hax_create_vm(int *vm_id); int hax_teardown_vm(struct vm_t *vm); int vcpu_event_pending(struct vcpu_t *vcpu); void vcpu_set_panic(struct vcpu_t *vcpu); +void vcpu_setexcbmp(struct vcpu_t *vcpu, uint32_t excbmp); #ifdef __cplusplus } diff --git a/core/include/vcpu.h b/core/include/vcpu.h index 2a842b8f..1a4e53db 100644 --- a/core/include/vcpu.h +++ b/core/include/vcpu.h @@ -238,6 +238,8 @@ struct vcpu_t { #ifdef CONFIG_HAX_EPT2 struct mmio_fetch_cache mmio_fetch; #endif // CONFIG_HAX_EPT2 + + uint32_t user_excbmp; }; #define vmx(v, field) v->vmx.field @@ -264,6 +266,7 @@ int vcpu_put_fpu(struct vcpu_t *vcpu, struct fx_layout *fl); int vcpu_get_msr(struct vcpu_t *vcpu, uint64_t entry, uint64_t *val); int vcpu_put_msr(struct vcpu_t *vcpu, uint64_t entry, uint64_t val); void vcpu_debug(struct vcpu_t *vcpu, struct hax_debug_t *debug); +void vcpu_setexcbmp(struct vcpu_t *vcpu, uint32_t excbmp); /* The declaration for OS wrapper code */ int hax_vcpu_destroy_host(struct vcpu_t *cvcpu, void *vcpu_host); diff --git a/core/include/vm.h b/core/include/vm.h index 5a38c4aa..50037bb0 100644 --- a/core/include/vm.h +++ b/core/include/vm.h @@ -112,7 +112,7 @@ enum exit_status { HAX_EXIT_FAST_MMIO, HAX_EXIT_PAGEFAULT, HAX_EXIT_DEBUG, - HAX_EXIT_OPCODE + HAX_EXIT_NMI }; enum run_flag { diff --git a/core/vcpu.c b/core/vcpu.c index 43487307..c51e1d0d 100644 --- a/core/vcpu.c +++ b/core/vcpu.c @@ -1309,6 +1309,7 @@ static void vcpu_update_exception_bitmap(struct vcpu_t *vcpu) if (vcpu->debug_control & HAX_DEBUG_USE_SW_BP) { exc_bitmap |= (1u << VECTOR_BP); } + exc_bitmap |= vcpu->user_excbmp; vmwrite(vcpu, VMX_EXCEPTION_BITMAP, exc_bitmap); } @@ -1942,9 +1943,6 @@ static void vmwrite_cr(struct vcpu_t *vcpu) ~(cr0_fixed_0 ^ cr0_fixed_1); } - // leecher1337 - exc_bitmap |= 1u << VECTOR_UD; - if (vtlb_active(vcpu)) { hax_debug("vTLB mode, cr0 %llx\n", vcpu->state->_cr0); vcpu->mmu->mmu_mode = MMU_MODE_VTLB; @@ -2395,11 +2393,13 @@ static int exit_exc_nmi(struct vcpu_t *vcpu, struct hax_tunnel *htun) htun->debug.dr7 = 0; return HAX_EXIT; } - // leecher1337 - case VECTOR_UD: { + default: + if (vcpu->user_excbmp & (1 << exit_intr_info.vector)) + { uint64_t va; - htun->_exit_status = HAX_EXIT_OPCODE; + htun->_exit_status = HAX_EXIT_NMI; + htun->nmi.exit_intr_info = exit_intr_info.raw; va = vcpu->state->_cs.long_mode == 1 ? vcpu->state->_rip : vcpu->state->_cs.base + vcpu->state->_rip; vcpu_read_guest_virtual(vcpu, va, vcpu->io_buf, INSTR_MAX_LEN, INSTR_MAX_LEN, 0); return HAX_EXIT; @@ -4120,6 +4120,13 @@ void vcpu_debug(struct vcpu_t *vcpu, struct hax_debug_t *debug) vcpu_update_exception_bitmap(vcpu); }; +void vcpu_setexcbmp(struct vcpu_t *vcpu, uint32_t excbmp) +{ + vcpu->user_excbmp = excbmp; + hax_error("set user_excbmp = %08X", vcpu->user_excbmp); + vcpu_update_exception_bitmap(vcpu); +} + static void vcpu_dump(struct vcpu_t *vcpu, uint32_t mask, const char *caption) { vcpu_vmread_all(vcpu); diff --git a/include/hax_interface.h b/include/hax_interface.h index 5dd15d94..8e0266dc 100644 --- a/include/hax_interface.h +++ b/include/hax_interface.h @@ -153,6 +153,9 @@ struct hax_tunnel { uint64_t dr6; uint64_t dr7; } debug; + struct { + uint32_t exit_intr_info; + } nmi; }; uint64_t apic_base; } PACKED; diff --git a/platforms/windows/hax_entry.c b/platforms/windows/hax_entry.c index 952a7773..6b8beb5b 100644 --- a/platforms/windows/hax_entry.c +++ b/platforms/windows/hax_entry.c @@ -430,6 +430,10 @@ NTSTATUS HaxVcpuControl(PDEVICE_OBJECT DeviceObject, vcpu_debug(cvcpu, (struct hax_debug_t*)inBuf); break; } + case HAX_VCPU_IOCTL_SET_EXCBMP: { + vcpu_setexcbmp(cvcpu, *(uint32_t*)inBuf); + break; + } default: hax_error("Unknow vcpu ioctl %lx\n", irpSp->Parameters.DeviceIoControl.IoControlCode); diff --git a/platforms/windows/hax_entry.h b/platforms/windows/hax_entry.h index 52613f7d..a441d478 100644 --- a/platforms/windows/hax_entry.h +++ b/platforms/windows/hax_entry.h @@ -166,4 +166,7 @@ extern PDRIVER_OBJECT HaxDriverObject; #define HAX_IOCTL_VCPU_DEBUG \ CTL_CODE(HAX_DEVICE_TYPE, 0x916, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define HAX_VCPU_IOCTL_SET_EXCBMP \ + CTL_CODE(HAX_DEVICE_TYPE, 0x919, METHOD_BUFFERED, FILE_ANY_ACCESS) + #endif // HAX_WINDOWS_HAX_ENTRY_H_ From 608b113718edf222a8afe577ed60633747600e0f Mon Sep 17 00:00:00 2001 From: leecher1337 Date: Fri, 19 Apr 2019 13:38:45 +0200 Subject: [PATCH 05/11] Whitespace fixes --- core/include/vcpu.h | 2 +- core/include/vm.h | 2 +- core/vcpu.c | 38 +++++++++++++++++------------------ include/hax_interface.h | 6 +++--- platforms/windows/hax_entry.c | 8 ++++---- 5 files changed, 28 insertions(+), 28 deletions(-) diff --git a/core/include/vcpu.h b/core/include/vcpu.h index 1a4e53db..da503d0c 100644 --- a/core/include/vcpu.h +++ b/core/include/vcpu.h @@ -239,7 +239,7 @@ struct vcpu_t { struct mmio_fetch_cache mmio_fetch; #endif // CONFIG_HAX_EPT2 - uint32_t user_excbmp; + uint32_t user_excbmp; }; #define vmx(v, field) v->vmx.field diff --git a/core/include/vm.h b/core/include/vm.h index 50037bb0..4ff10588 100644 --- a/core/include/vm.h +++ b/core/include/vm.h @@ -112,7 +112,7 @@ enum exit_status { HAX_EXIT_FAST_MMIO, HAX_EXIT_PAGEFAULT, HAX_EXIT_DEBUG, - HAX_EXIT_NMI + HAX_EXIT_NMI }; enum run_flag { diff --git a/core/vcpu.c b/core/vcpu.c index c51e1d0d..273b7c6c 100644 --- a/core/vcpu.c +++ b/core/vcpu.c @@ -1070,11 +1070,11 @@ static void load_dirty_vmcs_fields(struct vcpu_t *vcpu) vcpu->rflags_dirty = 1; vcpu->debug_control_dirty = 0; } - if ((vcpu->debug_control & HAX_DEBUG_STEP) && - (vmx(vcpu, interruptibility_state).raw & 3u)) { - vmx(vcpu, interruptibility_state).raw &= ~3u; - vcpu->interruptibility_dirty = 1; - } + if ((vcpu->debug_control & HAX_DEBUG_STEP) && + (vmx(vcpu, interruptibility_state).raw & 3u)) { + vmx(vcpu, interruptibility_state).raw &= ~3u; + vcpu->interruptibility_dirty = 1; + } if (vcpu->rflags_dirty) { vmwrite(vcpu, GUEST_RFLAGS, state->_rflags); vcpu->rflags_dirty = 0; @@ -1309,7 +1309,7 @@ static void vcpu_update_exception_bitmap(struct vcpu_t *vcpu) if (vcpu->debug_control & HAX_DEBUG_USE_SW_BP) { exc_bitmap |= (1u << VECTOR_BP); } - exc_bitmap |= vcpu->user_excbmp; + exc_bitmap |= vcpu->user_excbmp; vmwrite(vcpu, VMX_EXCEPTION_BITMAP, exc_bitmap); } @@ -2393,17 +2393,17 @@ static int exit_exc_nmi(struct vcpu_t *vcpu, struct hax_tunnel *htun) htun->debug.dr7 = 0; return HAX_EXIT; } - default: - if (vcpu->user_excbmp & (1 << exit_intr_info.vector)) - { - uint64_t va; + default: + if (vcpu->user_excbmp & (1 << exit_intr_info.vector)) + { + uint64_t va; - htun->_exit_status = HAX_EXIT_NMI; - htun->nmi.exit_intr_info = exit_intr_info.raw; - va = vcpu->state->_cs.long_mode == 1 ? vcpu->state->_rip : vcpu->state->_cs.base + vcpu->state->_rip; - vcpu_read_guest_virtual(vcpu, va, vcpu->io_buf, INSTR_MAX_LEN, INSTR_MAX_LEN, 0); - return HAX_EXIT; - } + htun->_exit_status = HAX_EXIT_NMI; + htun->nmi.exit_intr_info = exit_intr_info.raw; + va = vcpu->state->_cs.long_mode == 1 ? vcpu->state->_rip : vcpu->state->_cs.base + vcpu->state->_rip; + vcpu_read_guest_virtual(vcpu, va, vcpu->io_buf, INSTR_MAX_LEN, INSTR_MAX_LEN, 0); + return HAX_EXIT; + } } if (exit_intr_info.vector == VECTOR_PF) { @@ -4122,9 +4122,9 @@ void vcpu_debug(struct vcpu_t *vcpu, struct hax_debug_t *debug) void vcpu_setexcbmp(struct vcpu_t *vcpu, uint32_t excbmp) { - vcpu->user_excbmp = excbmp; - hax_error("set user_excbmp = %08X", vcpu->user_excbmp); - vcpu_update_exception_bitmap(vcpu); + vcpu->user_excbmp = excbmp; + hax_error("set user_excbmp = %08X", vcpu->user_excbmp); + vcpu_update_exception_bitmap(vcpu); } static void vcpu_dump(struct vcpu_t *vcpu, uint32_t mask, const char *caption) diff --git a/include/hax_interface.h b/include/hax_interface.h index 8e0266dc..fe8d0dc4 100644 --- a/include/hax_interface.h +++ b/include/hax_interface.h @@ -153,9 +153,9 @@ struct hax_tunnel { uint64_t dr6; uint64_t dr7; } debug; - struct { - uint32_t exit_intr_info; - } nmi; + struct { + uint32_t exit_intr_info; + } nmi; }; uint64_t apic_base; } PACKED; diff --git a/platforms/windows/hax_entry.c b/platforms/windows/hax_entry.c index 6b8beb5b..d8330992 100644 --- a/platforms/windows/hax_entry.c +++ b/platforms/windows/hax_entry.c @@ -430,10 +430,10 @@ NTSTATUS HaxVcpuControl(PDEVICE_OBJECT DeviceObject, vcpu_debug(cvcpu, (struct hax_debug_t*)inBuf); break; } - case HAX_VCPU_IOCTL_SET_EXCBMP: { - vcpu_setexcbmp(cvcpu, *(uint32_t*)inBuf); - break; - } + case HAX_VCPU_IOCTL_SET_EXCBMP: { + vcpu_setexcbmp(cvcpu, *(uint32_t*)inBuf); + break; + } default: hax_error("Unknow vcpu ioctl %lx\n", irpSp->Parameters.DeviceIoControl.IoControlCode); From 5e4113bff7b75777e8373f36468954217e30e3b3 Mon Sep 17 00:00:00 2001 From: leecher1337 Date: Thu, 15 Aug 2019 10:13:00 +0200 Subject: [PATCH 06/11] Bugfix for #234 --- core/memslot.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/memslot.c b/core/memslot.c index 8fd9acf9..ea37b591 100644 --- a/core/memslot.c +++ b/core/memslot.c @@ -364,8 +364,12 @@ static inline void memslot_delete(hax_memslot *dest) static inline void memslot_move(hax_memslot *dest, hax_memslot *src) { + hax_list_node entry; + ramblock_deref(dest->block); + entry = dest->entry; memslot_init(dest, src); + dest->entry = entry; } static inline void memslot_union(hax_memslot *dest, hax_memslot *src) From 792f407b29b7ccd01321cc86a641ef03c457e254 Mon Sep 17 00:00:00 2001 From: leecher1337 Date: Thu, 15 Aug 2019 13:18:17 +0200 Subject: [PATCH 07/11] Fix adapted to solution propsed by @wcwang, as there seem to be no design considerations for calling memslot_init --- core/memslot.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/core/memslot.c b/core/memslot.c index ea37b591..849651cb 100644 --- a/core/memslot.c +++ b/core/memslot.c @@ -362,14 +362,12 @@ static inline void memslot_delete(hax_memslot *dest) hax_vfree(dest, sizeof(hax_memslot)); } -static inline void memslot_move(hax_memslot *dest, hax_memslot *src) -{ - hax_list_node entry; - - ramblock_deref(dest->block); - entry = dest->entry; - memslot_init(dest, src); - dest->entry = entry; +static inline void memslot_move(hax_memslot *dest, hax_memslot *src) +{ + ramblock_deref(dest->block); + src->entry = dest->entry; + *dest = *src; + ramblock_ref(dest->block); } static inline void memslot_union(hax_memslot *dest, hax_memslot *src) From c2f9b77f8dd9277f49d52ca023cbcc760c004ff1 Mon Sep 17 00:00:00 2001 From: leecher1337 Date: Thu, 15 Aug 2019 14:31:44 +0200 Subject: [PATCH 08/11] Visual Studio copy&paste destroyed proper indentation, fixed. Bugfix description: Invoking memslot_init() in memslot_move() will result in losing the linked list information of the original memory slot node. Reimplement memslot_move() to resolve some exceptional issues during mapping memory slots. --- core/memslot.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/memslot.c b/core/memslot.c index 849651cb..e21481c0 100644 --- a/core/memslot.c +++ b/core/memslot.c @@ -364,10 +364,10 @@ static inline void memslot_delete(hax_memslot *dest) static inline void memslot_move(hax_memslot *dest, hax_memslot *src) { - ramblock_deref(dest->block); - src->entry = dest->entry; - *dest = *src; - ramblock_ref(dest->block); + ramblock_deref(dest->block); + src->entry = dest->entry; + *dest = *src; + ramblock_ref(dest->block); } static inline void memslot_union(hax_memslot *dest, hax_memslot *src) From a23145c09f31c9609050941c75cb481a2f6b5fbe Mon Sep 17 00:00:00 2001 From: leecher1337 Date: Wed, 21 Aug 2019 14:18:12 +0200 Subject: [PATCH 09/11] Hopefully the last indentation issue with tab instead of space :) --- core/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/cpu.c b/core/cpu.c index 3869426a..804ea62c 100644 --- a/core/cpu.c +++ b/core/cpu.c @@ -222,7 +222,7 @@ bool vcpu_is_panic(struct vcpu_t *vcpu) if (vcpu->panicked) { hax_error("vcpu has panicked, id:%d\n", vcpu->vcpu_id); hax_panic_log(vcpu); - htun->_exit_reason = vmx(vcpu, exit_reason).basic_reason; + htun->_exit_reason = vmx(vcpu, exit_reason).basic_reason; htun->_exit_status = HAX_EXIT_STATECHANGE; return 1; } From a9cc5f9e70509ba599f396c43f0228f56370f396 Mon Sep 17 00:00:00 2001 From: leecher1337 Date: Wed, 28 Aug 2019 21:19:55 +0200 Subject: [PATCH 10/11] Adapted patch to use new logging interface. --- core/vcpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/vcpu.c b/core/vcpu.c index f8975f1e..2e0d831c 100644 --- a/core/vcpu.c +++ b/core/vcpu.c @@ -4207,7 +4207,7 @@ void vcpu_debug(struct vcpu_t *vcpu, struct hax_debug_t *debug) void vcpu_setexcbmp(struct vcpu_t *vcpu, uint32_t excbmp) { vcpu->user_excbmp = excbmp; - hax_error("set user_excbmp = %08X", vcpu->user_excbmp); + hax_log(HAX_LOGE, "set user_excbmp = %08X", vcpu->user_excbmp); vcpu_update_exception_bitmap(vcpu); } From 99614cd615bbd075aaa96a5680ac7bd4dec738fe Mon Sep 17 00:00:00 2001 From: leecher1337 Date: Tue, 3 Sep 2019 08:45:41 +0200 Subject: [PATCH 11/11] Arrrrgh... Is there any way that VS2017 can be told that it has to use spaces instead of tabs on a PER-PROJECT basis? (EditorConfig possibly?) --- core/vcpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/vcpu.c b/core/vcpu.c index 2e0d831c..e68dd032 100644 --- a/core/vcpu.c +++ b/core/vcpu.c @@ -4207,7 +4207,7 @@ void vcpu_debug(struct vcpu_t *vcpu, struct hax_debug_t *debug) void vcpu_setexcbmp(struct vcpu_t *vcpu, uint32_t excbmp) { vcpu->user_excbmp = excbmp; - hax_log(HAX_LOGE, "set user_excbmp = %08X", vcpu->user_excbmp); + hax_log(HAX_LOGE, "set user_excbmp = %08X", vcpu->user_excbmp); vcpu_update_exception_bitmap(vcpu); }