From bf7c5b421ad5caff46d1c6572460d790ab57e442 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sun, 13 Apr 2025 17:59:16 +0200 Subject: [PATCH 1/2] Add unhandled exception test --- src/samples/test-sample/test.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/samples/test-sample/test.cpp b/src/samples/test-sample/test.cpp index a3b03a34..40b7a1b1 100644 --- a/src/samples/test-sample/test.cpp +++ b/src/samples/test-sample/test.cpp @@ -404,6 +404,23 @@ namespace } } + bool test_unhandled_exception() + { + thread_local bool caught{}; + caught = false; + + auto* old = SetUnhandledExceptionFilter(+[](struct _EXCEPTION_POINTERS* ExceptionInfo) -> LONG { + caught = true; + ExceptionInfo->ContextRecord->Rip += 1; + return EXCEPTION_CONTINUE_EXECUTION; // + }); + + DebugBreak(); + SetUnhandledExceptionFilter(old); + + return caught; + } + bool test_illegal_instruction_exception() { const auto address = VirtualAlloc(nullptr, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); @@ -423,7 +440,9 @@ namespace bool test_native_exceptions() { - return test_access_violation_exception() && test_illegal_instruction_exception(); + return test_access_violation_exception() // + && test_illegal_instruction_exception() // + && test_unhandled_exception(); } void print_time() From 0af756abd5cd9bd65f6bda999a4a83a8b12f5d1c Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sun, 24 Aug 2025 16:18:26 +0200 Subject: [PATCH 2/2] Use stored RIP as emulators are unreliable --- src/windows-emulator/exception_dispatch.cpp | 36 ++++++++++----------- src/windows-emulator/exception_dispatch.hpp | 22 ++++++------- src/windows-emulator/windows_emulator.cpp | 16 ++++----- 3 files changed, 36 insertions(+), 38 deletions(-) diff --git a/src/windows-emulator/exception_dispatch.cpp b/src/windows-emulator/exception_dispatch.cpp index d4c158b1..a1cc0df3 100644 --- a/src/windows-emulator/exception_dispatch.cpp +++ b/src/windows-emulator/exception_dispatch.cpp @@ -2,6 +2,7 @@ #include "exception_dispatch.hpp" #include "process_context.hpp" #include "cpu_context.hpp" +#include "windows_emulator.hpp" namespace { @@ -136,19 +137,19 @@ namespace } } -void dispatch_exception(x86_64_emulator& emu, const process_context& proc, const DWORD status, - const std::vector::ULONG_PTR>& parameters) +void dispatch_exception(windows_emulator& win_emu, const DWORD status, const std::vector::ULONG_PTR>& parameters) { CONTEXT64 ctx{}; ctx.ContextFlags = CONTEXT64_ALL; - cpu_context::save(emu, ctx); + cpu_context::save(win_emu.emu(), ctx); + ctx.Rip = win_emu.current_thread().current_ip; exception_record record{}; memset(&record, 0, sizeof(record)); record.ExceptionCode = status; record.ExceptionFlags = 0; record.ExceptionRecord = 0; - record.ExceptionAddress = emu.read_instruction_pointer(); + record.ExceptionAddress = ctx.Rip; record.NumberParameters = static_cast(parameters.size()); if (parameters.size() > 15) @@ -165,44 +166,43 @@ void dispatch_exception(x86_64_emulator& emu, const process_context& proc, const pointers.ContextRecord = reinterpret_cast::PVOID>(&ctx); pointers.ExceptionRecord = reinterpret_cast::PVOID>(&record); - dispatch_exception_pointers(emu, proc.ki_user_exception_dispatcher, pointers); + dispatch_exception_pointers(win_emu.emu(), win_emu.process.ki_user_exception_dispatcher, pointers); } -void dispatch_access_violation(x86_64_emulator& emu, const process_context& proc, const uint64_t address, const memory_operation operation) +void dispatch_access_violation(windows_emulator& win_emu, const uint64_t address, const memory_operation operation) { - dispatch_exception(emu, proc, STATUS_ACCESS_VIOLATION, + dispatch_exception(win_emu, STATUS_ACCESS_VIOLATION, { map_violation_operation_to_parameter(operation), address, }); } -void dispatch_guard_page_violation(x86_64_emulator& emu, const process_context& proc, const uint64_t address, - const memory_operation operation) +void dispatch_guard_page_violation(windows_emulator& win_emu, const uint64_t address, const memory_operation operation) { - dispatch_exception(emu, proc, STATUS_GUARD_PAGE_VIOLATION, + dispatch_exception(win_emu, STATUS_GUARD_PAGE_VIOLATION, { map_violation_operation_to_parameter(operation), address, }); } -void dispatch_illegal_instruction_violation(x86_64_emulator& emu, const process_context& proc) +void dispatch_illegal_instruction_violation(windows_emulator& win_emu) { - dispatch_exception(emu, proc, STATUS_ILLEGAL_INSTRUCTION, {}); + dispatch_exception(win_emu, STATUS_ILLEGAL_INSTRUCTION, {}); } -void dispatch_integer_division_by_zero(x86_64_emulator& emu, const process_context& proc) +void dispatch_integer_division_by_zero(windows_emulator& win_emu) { - dispatch_exception(emu, proc, STATUS_INTEGER_DIVIDE_BY_ZERO, {}); + dispatch_exception(win_emu, STATUS_INTEGER_DIVIDE_BY_ZERO, {}); } -void dispatch_single_step(x86_64_emulator& emu, const process_context& proc) +void dispatch_single_step(windows_emulator& win_emu) { - dispatch_exception(emu, proc, STATUS_SINGLE_STEP, {}); + dispatch_exception(win_emu, STATUS_SINGLE_STEP, {}); } -void dispatch_breakpoint(x86_64_emulator& emu, const process_context& proc) +void dispatch_breakpoint(windows_emulator& win_emu) { - dispatch_exception(emu, proc, STATUS_BREAKPOINT, {}); + dispatch_exception(win_emu, STATUS_BREAKPOINT, {}); } diff --git a/src/windows-emulator/exception_dispatch.hpp b/src/windows-emulator/exception_dispatch.hpp index 333d8db9..e7eaca3d 100644 --- a/src/windows-emulator/exception_dispatch.hpp +++ b/src/windows-emulator/exception_dispatch.hpp @@ -5,21 +5,19 @@ #include #include -struct process_context; +class windows_emulator; -void dispatch_exception(x86_64_emulator& emu, const process_context& proc, DWORD status, - const std::vector::ULONG_PTR>& parameters); +void dispatch_exception(windows_emulator& win_emu, DWORD status, const std::vector::ULONG_PTR>& parameters); template requires(std::is_integral_v && !std::is_same_v) -void dispatch_exception(x86_64_emulator& emu, const process_context& proc, const T status, - const std::vector::ULONG_PTR>& parameters) +void dispatch_exception(windows_emulator& win_emu, const T status, const std::vector::ULONG_PTR>& parameters) { - dispatch_exception(emu, proc, static_cast(status), parameters); + dispatch_exception(win_emu, static_cast(status), parameters); } -void dispatch_access_violation(x86_64_emulator& emu, const process_context& proc, uint64_t address, memory_operation operation); -void dispatch_guard_page_violation(x86_64_emulator& emu, const process_context& proc, uint64_t address, memory_operation operation); -void dispatch_illegal_instruction_violation(x86_64_emulator& emu, const process_context& proc); -void dispatch_integer_division_by_zero(x86_64_emulator& emu, const process_context& proc); -void dispatch_single_step(x86_64_emulator& emu, const process_context& proc); -void dispatch_breakpoint(x86_64_emulator& emu, const process_context& proc); +void dispatch_access_violation(windows_emulator& win_emu, uint64_t address, memory_operation operation); +void dispatch_guard_page_violation(windows_emulator& win_emu, uint64_t address, memory_operation operation); +void dispatch_illegal_instruction_violation(windows_emulator& win_emu); +void dispatch_integer_division_by_zero(windows_emulator& win_emu); +void dispatch_single_step(windows_emulator& win_emu); +void dispatch_breakpoint(windows_emulator& win_emu); diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index 364352db..ab9ecbd8 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -466,7 +466,7 @@ void windows_emulator::setup_hooks() // TODO: Unicorn needs this - This should be handled in the backend this->emu().hook_instruction(x86_hookable_instructions::invalid, [&] { // TODO: Unify icicle & unicorn handling - dispatch_illegal_instruction_violation(this->emu(), this->process); + dispatch_illegal_instruction_violation(*this); return instruction_hook_continuation::skip_instruction; // }); @@ -477,7 +477,7 @@ void windows_emulator::setup_hooks() switch (interrupt) { case 0: - dispatch_integer_division_by_zero(this->emu(), this->process); + dispatch_integer_division_by_zero(*this); return; case 1: if ((eflags & 0x100) != 0) @@ -486,19 +486,19 @@ void windows_emulator::setup_hooks() } this->callbacks.on_suspicious_activity("Singlestep"); - dispatch_single_step(this->emu(), this->process); + dispatch_single_step(*this); return; case 3: this->callbacks.on_suspicious_activity("Breakpoint"); - dispatch_breakpoint(this->emu(), this->process); + dispatch_breakpoint(*this); return; case 6: this->callbacks.on_suspicious_activity("Illegal instruction"); - dispatch_illegal_instruction_violation(this->emu(), this->process); + dispatch_illegal_instruction_violation(*this); return; case 45: this->callbacks.on_suspicious_activity("DbgPrint"); - dispatch_breakpoint(this->emu(), this->process); + dispatch_breakpoint(*this); return; default: if (this->callbacks.on_generic_activity) @@ -517,12 +517,12 @@ void windows_emulator::setup_hooks() { // Unset the GUARD_PAGE flag and dispatch a STATUS_GUARD_PAGE_VIOLATION this->memory.protect_memory(region.allocation_base, region.length, region.permissions & ~memory_permission_ext::guard); - dispatch_guard_page_violation(this->emu(), this->process, address, operation); + dispatch_guard_page_violation(*this, address, operation); } else { this->callbacks.on_memory_violate(address, size, operation, type); - dispatch_access_violation(this->emu(), this->process, address, operation); + dispatch_access_violation(*this, address, operation); } return memory_violation_continuation::resume;