diff --git a/src/test-sample/test.cpp b/src/test-sample/test.cpp index 4d146e56..6842432c 100644 --- a/src/test-sample/test.cpp +++ b/src/test-sample/test.cpp @@ -234,7 +234,7 @@ bool test_exceptions() } } -void throw_native_exception() +void throw_access_violation() { if (do_the_task) { @@ -242,19 +242,55 @@ void throw_native_exception() } } -bool test_native_exceptions() +bool test_access_violation_exception() { __try { - throw_native_exception(); + throw_access_violation(); return false; } __except (EXCEPTION_EXECUTE_HANDLER) { - return true; + return GetExceptionCode() == STATUS_ACCESS_VIOLATION; } } +bool test_ud2_exception(void* address) +{ + __try + { + static_cast(address)(); + return false; + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + return GetExceptionCode() == STATUS_ILLEGAL_INSTRUCTION; + } +} + +bool test_illegal_instruction_exception() +{ + const auto address = VirtualAlloc(nullptr, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); + if (!address) + { + return false; + } + + memcpy(address, "\x0F\x0B", 2); // ud2 + + const auto res = test_ud2_exception(address); + + VirtualFree(address, 0x1000, MEM_RELEASE); + + return res; +} + +bool test_native_exceptions() +{ + return test_access_violation_exception() + && test_illegal_instruction_exception(); +} + void print_time() { const auto epoch_time = std::chrono::system_clock::now().time_since_epoch(); diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index 1221a68e..1a0bd6e0 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -425,6 +425,27 @@ namespace dispatch_exception_pointers(emu, dispatcher, pointers); } + void dispatch_illegal_instruction_violation(x64_emulator& emu, const uint64_t dispatcher) + { + CONTEXT ctx{}; + ctx.ContextFlags = CONTEXT_ALL; + context_frame::save(emu, ctx); + + EXCEPTION_RECORD record{}; + memset(&record, 0, sizeof(record)); + record.ExceptionCode = static_cast(STATUS_ILLEGAL_INSTRUCTION); + record.ExceptionFlags = 0; + record.ExceptionRecord = nullptr; + record.ExceptionAddress = reinterpret_cast(emu.read_instruction_pointer()); + record.NumberParameters = 0; + + EXCEPTION_POINTERS pointers{}; + pointers.ContextRecord = &ctx; + pointers.ExceptionRecord = &record; + + dispatch_exception_pointers(emu, dispatcher, pointers); + } + void perform_context_switch_work(windows_emulator& win_emu) { auto& devices = win_emu.process().devices; @@ -462,7 +483,7 @@ namespace if (active_thread) { - win_emu.logger.print(color::green, "Performing thread switch...\n"); + win_emu.logger.print(color::dark_gray, "Performing thread switch...\n"); active_thread->save(emu); } @@ -812,11 +833,18 @@ void windows_emulator::setup_hooks() { const auto ip = this->emu().read_instruction_pointer(); printf("Invalid instruction at: 0x%llX\n", ip); + return instruction_hook_continuation::skip_instruction; }); this->emu().hook_interrupt([&](const int interrupt) { + if (interrupt == 6) + { + dispatch_illegal_instruction_violation(this->emu(), this->process().ki_user_exception_dispatcher); + return; + } + const auto rip = this->emu().read_instruction_pointer(); printf("Interrupt: %i 0x%llX\n", interrupt, rip);