From 4ce8e47684f91fff2995d8b8a41b228648c744f2 Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Sun, 14 Feb 2021 02:04:05 -0800 Subject: [PATCH] added SEH code... --- bluepill.vcxproj | 2 ++ bluepill.vcxproj.filters | 6 ++++ debug.cpp | 69 ++++++++++++++++++++++++++++++++++++++++ debug.hpp | 13 ++++++++ drv_entry.cpp | 12 +------ exit_handler.cpp | 2 +- idt.cpp | 43 ++++++++++++++++++++++--- idt.hpp | 4 ++- idt_handlers.asm | 1 - vmcs.cpp | 2 +- vmxexit_handler.h | 1 + 11 files changed, 136 insertions(+), 19 deletions(-) create mode 100644 debug.cpp create mode 100644 debug.hpp diff --git a/bluepill.vcxproj b/bluepill.vcxproj index e663bbd..cde56dc 100644 --- a/bluepill.vcxproj +++ b/bluepill.vcxproj @@ -83,6 +83,7 @@ + @@ -93,6 +94,7 @@ + diff --git a/bluepill.vcxproj.filters b/bluepill.vcxproj.filters index 84c41df..ca468fc 100644 --- a/bluepill.vcxproj.filters +++ b/bluepill.vcxproj.filters @@ -35,6 +35,9 @@ Source Files + + Source Files + @@ -70,6 +73,9 @@ Header Files + + Header Files + diff --git a/debug.cpp b/debug.cpp new file mode 100644 index 0000000..2048744 --- /dev/null +++ b/debug.cpp @@ -0,0 +1,69 @@ +#include "debug.hpp" + +auto dbg::debug_print_decimal(long long number) -> void +{ + if (number < 0) + { + __outbyte(PORT_NUM, '-'); + number = -number; + } + + for (auto d = 1000000000000000000; d != 0; d /= 10) + if ((number / d) != 0) + __outbyte(PORT_NUM, alphabet[(number / d) % 10]); +} + +auto dbg::debug_print_hex(u64 number, const bool show_zeros) -> void +{ + for (auto d = 0x1000000000000000; d != 0; d /= 0x10) + if (show_zeros || (number / d) != 0) + __outbyte(PORT_NUM, alphabet[(number / d) % 0x10]); +} + +auto dbg::print(const char* format, ...) -> void +{ + va_list args; + va_start(args, format); + + while (format[0]) + { + if (format[0] == '%') + { + switch (format[1]) + { + case 'd': + debug_print_decimal(va_arg(args, int)); + format += 2; + continue; + case 'x': + debug_print_hex(va_arg(args, u32), false); + format += 2; + continue; + case 'l': + if (format[2] == 'l') + { + switch (format[3]) + { + case 'd': + debug_print_decimal(va_arg(args, u64)); + format += 4; + continue; + case 'x': + debug_print_hex(va_arg(args, u64), false); + format += 4; + continue; + } + } + break; + case 'p': + debug_print_hex(va_arg(args, u64), true); + format += 2; + continue; + } + } + + __outbyte(PORT_NUM, format[0]); + ++format; + } + va_end(args); +} \ No newline at end of file diff --git a/debug.hpp b/debug.hpp new file mode 100644 index 0000000..08e801c --- /dev/null +++ b/debug.hpp @@ -0,0 +1,13 @@ +#pragma once +#include +#include +#include "hv_types.hpp" +#define PORT_NUM 0x3E8 + +namespace dbg +{ + constexpr char alphabet[] = "0123456789ABCDEF"; + auto debug_print_decimal(long long number) -> void; + auto debug_print_hex(u64 number, const bool show_zeros) -> void; + auto print(const char* format, ...) -> void; +} \ No newline at end of file diff --git a/drv_entry.cpp b/drv_entry.cpp index 2b3e1d9..5416da2 100644 --- a/drv_entry.cpp +++ b/drv_entry.cpp @@ -5,7 +5,7 @@ auto driver_unload( PDRIVER_OBJECT driver_object ) -> void { - // no unloading this hv... restart! lol + // no unloading this hv... restart... __debugbreak(); } @@ -62,16 +62,6 @@ auto driver_entry( idt::table[page_fault] = create_entry(hv::idt_addr_t{ __pf_handler }, idt::ist_idx::pf); idt::table[divide_error] = create_entry(hv::idt_addr_t{ __de_handler }, idt::ist_idx::de); - // change the segment selector to work with vmxroot gdt... - for (auto idx = 0u; idx < 255; ++idx) - { - segment_selector cs{}; - cs.idx = gdt::idx::cs; - cs.request_privilege_level = NULL; - cs.table = NULL; - idt::table[idx].segment_selector = cs.flags; - } - // used for SEH in vmxroot fault handler... idt::image_base = driver_object->DriverStart; diff --git a/exit_handler.cpp b/exit_handler.cpp index 1620c0b..803e8bc 100644 --- a/exit_handler.cpp +++ b/exit_handler.cpp @@ -12,7 +12,7 @@ auto exit_handler(hv::pguest_registers regs) -> void if (regs->rcx == 0xC0FFEE) { regs->rax = 0xC0FFEE; - __debugbreak(); + *(u8*)0x0 = 0xDE; } else { diff --git a/idt.cpp b/idt.cpp index 70d30e2..43f2f0f 100644 --- a/idt.cpp +++ b/idt.cpp @@ -1,10 +1,45 @@ #include "idt.hpp" -void seh_handler(hv::pidt_regs_t regs) +auto seh_handler(hv::pidt_regs_t regs) -> void { - // probably not going to work since software interrupts are disabled? __debugbreak(); - return; + + /*const auto rva = regs->rip - reinterpret_cast(idt::image_base); + + IMAGE_NT_HEADERS64* nt = (IMAGE_NT_HEADERS64*)(reinterpret_cast(idt::image_base) + + reinterpret_cast(idt::image_base).e_lfanew); + + IMAGE_DATA_DIRECTORY* exception = + &nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION]; + + RUNTIME_FUNCTION* functions = + (RUNTIME_FUNCTION*)((UINT64)&__ImageBase + exception->VirtualAddress); + + for (UINT32 i = 0; i < exception->Size / sizeof(RUNTIME_FUNCTION); ++i) { + RUNTIME_FUNCTION* function = &functions[i]; + if (!(rva >= function->BeginAddress && rva < function->EndAddress)) { + continue; + } + + UNWIND_INFO* unwindInfo = (UNWIND_INFO*)((UINT64)&__ImageBase + function->UnwindData); + if (!(unwindInfo->Flags & UNW_FLAG_EHANDLER)) { + continue; + } + + SCOPE_TABLE* scopeTable = + (SCOPE_TABLE*)((UINT64)&unwindInfo->UnwindCode[(unwindInfo->CountOfCodes + 1) & ~1] + + sizeof(UINT32)); + + for (UINT32 e = 0; e < scopeTable->Count; ++e) { + SCOPE_RECORD* scopeRecord = &scopeTable->ScopeRecords[e]; + + if (rva >= scopeRecord->BeginAddress && rva < scopeRecord->EndAddress) { + *rip = (UINT64)&__ImageBase + scopeRecord->JumpTarget; + return; + } + } + } + */ } namespace idt @@ -15,7 +50,7 @@ namespace idt result.segment_selector = readcs(); result.gate_type = SEGMENT_DESCRIPTOR_TYPE_INTERRUPT_GATE; result.present = true; - result.ist_index = ist_index; + result.ist_index = NULL; result.dpl = 0; result.offset_high = idt_handler.offset_high; diff --git a/idt.hpp b/idt.hpp index 15c12c4..7aec693 100644 --- a/idt.hpp +++ b/idt.hpp @@ -1,8 +1,9 @@ #pragma once #include "hv_types.hpp" #include "segment_intrin.h" -#pragma section(".idt", read, write) +#include "debug.hpp" +#pragma section(".idt", read, write) extern "C" void __gp_handler(void); extern "C" void __pf_handler(void); extern "C" void __de_handler(void); @@ -14,5 +15,6 @@ namespace idt inline hv::idt_entry_t table[256]; inline void* image_base = nullptr; // used for SEH... enum ist_idx : u8 { gp = 5, pf = 6, de = 7}; + auto create_entry(hv::idt_addr_t idt_handler, u8 ist_index) -> hv::idt_entry_t; } \ No newline at end of file diff --git a/idt_handlers.asm b/idt_handlers.asm index 96019e3..ff0c7b9 100644 --- a/idt_handlers.asm +++ b/idt_handlers.asm @@ -4,7 +4,6 @@ extern seh_handler : proc __pf_handler proc __de_handler proc __gp_handler proc - int 3 push rax push rbx push rcx diff --git a/vmcs.cpp b/vmcs.cpp index c6060a2..492f208 100644 --- a/vmcs.cpp +++ b/vmcs.cpp @@ -17,7 +17,7 @@ namespace vmcs const auto current_vcpu = vmxon::g_vmx_ctx->vcpus[KeGetCurrentProcessorNumber()]; - __vmx_vmwrite(VMCS_HOST_GDTR_BASE, reinterpret_cast(current_vcpu->gdt)); + __vmx_vmwrite(VMCS_HOST_GDTR_BASE, gdt_value.base_address); __vmx_vmwrite(VMCS_HOST_IDTR_BASE, reinterpret_cast(idt::table)); segment_selector es{ reades() }; diff --git a/vmxexit_handler.h b/vmxexit_handler.h index 5a818b3..e5b5ae3 100644 --- a/vmxexit_handler.h +++ b/vmxexit_handler.h @@ -1,5 +1,6 @@ #pragma once #include "hv_types.hpp" +#include "debug.hpp" #include "invd.hpp" extern "C" auto vmxexit_handler() -> void;