From 8e9cba4f31539be42763aab73b9370ad2a78855f Mon Sep 17 00:00:00 2001 From: momo5502 Date: Fri, 23 Aug 2024 21:30:59 +0200 Subject: [PATCH] Prepare better syscall handling --- src/windows_emulator/syscalls.cpp | 120 ++++++++++++++++++++++-------- 1 file changed, 90 insertions(+), 30 deletions(-) diff --git a/src/windows_emulator/syscalls.cpp b/src/windows_emulator/syscalls.cpp index 8b8ad8c4..98b8e4aa 100644 --- a/src/windows_emulator/syscalls.cpp +++ b/src/windows_emulator/syscalls.cpp @@ -3,6 +3,70 @@ namespace { + struct syscall_context + { + x64_emulator& emu; + process_context& proc; + }; + + uint64_t get_syscall_argument(x64_emulator& emu, const size_t index) + { + switch (index) + { + case 0: + return emu.reg(x64_register::r10); + case 1: + return emu.reg(x64_register::rdx); + case 2: + return emu.reg(x64_register::r8); + case 3: + return emu.reg(x64_register::r9); + default: + return emu.read_stack(index + 1); + } + } + + template + requires(std::is_integral_v) + T resolve_argument(x64_emulator& emu, const size_t index) + { + const auto arg = get_syscall_argument(emu, index); + return static_cast(arg); + } + + template + T resolve_argument(x64_emulator& emu, const size_t index) + { + const auto arg = get_syscall_argument(emu, index); + return T(emu, arg); + } + + template + T resolve_indexed_argument(x64_emulator& emu, size_t& index) + { + return resolve_argument(emu, index++); + } + + void forward(const syscall_context& c, NTSTATUS (*handler)()) + { + const auto ret = handler(); + c.emu.reg(x64_register::rax, static_cast(ret)); + } + + template + void forward(const syscall_context& c, NTSTATUS (*handler)(const syscall_context&, Args...)) + { + size_t index = 0; + std::tuple func_args + { + c, + resolve_indexed_argument>>(c.emu, index)... + }; + + const auto ret = std::apply(handler, std::move(func_args)); + c.emu.reg(x64_register::rax, static_cast(ret)); + } + void handle_NtQueryPerformanceCounter(x64_emulator& emu) { const emulator_object performance_counter{emu, emu.reg(x64_register::r10)}; @@ -34,24 +98,24 @@ namespace } } - void handle_NtManageHotPatch(x64_emulator& emu) + NTSTATUS handle_NtManageHotPatch() { - emu.reg(x64_register::rax, STATUS_NOT_SUPPORTED); + return STATUS_NOT_SUPPORTED; } - void handle_NtOpenKey(x64_emulator& emu) + NTSTATUS handle_NtOpenKey() { - emu.reg(x64_register::rax, STATUS_NOT_SUPPORTED); + return STATUS_NOT_SUPPORTED; } - void handle_NtCreateIoCompletion(x64_emulator& emu) + NTSTATUS handle_NtCreateIoCompletion() { - emu.reg(x64_register::rax, STATUS_NOT_SUPPORTED); + return STATUS_NOT_SUPPORTED; } - void handle_NtTraceEvent(x64_emulator& emu) + NTSTATUS handle_NtTraceEvent() { - emu.reg(x64_register::rax, STATUS_NOT_SUPPORTED); + return STATUS_NOT_SUPPORTED; } void handle_NtCreateEvent(x64_emulator& emu, process_context& context) @@ -362,18 +426,14 @@ namespace emu.reg(x64_register::rax, STATUS_SUCCESS); } - void handle_NtAllocateVirtualMemory(x64_emulator& emu) + NTSTATUS handle_NtAllocateVirtualMemory(const syscall_context& c, const uint64_t process_handle, + const emulator_object base_address, + const emulator_object bytes_to_allocate, + const uint32_t /*allocation_type*/, const uint32_t page_protection) { - const auto process_handle = emu.reg(x64_register::r10); - const emulator_object base_address{emu, emu.reg(x64_register::rdx)}; - const emulator_object bytes_to_allocate{emu, emu.reg(x64_register::r9)}; - //const auto allocation_type =emu.reg(x64_register::r9d); - const auto page_protection = static_cast(emu.read_stack(6)); - if (process_handle != ~0ULL) { - emu.reg(x64_register::rax, STATUS_NOT_IMPLEMENTED); - return; + return STATUS_NOT_IMPLEMENTED; } constexpr auto allocation_granularity = 0x10000; @@ -390,17 +450,16 @@ namespace allocate_anywhere = true; allocation_base = allocation_granularity; } - else if (is_memory_allocated(emu, allocation_base)) + else if (is_memory_allocated(c.emu, allocation_base)) { - emu.reg(x64_register::rax, STATUS_SUCCESS); - return; + return STATUS_SUCCESS; } bool succeeded = false; while (true) { - succeeded = emu.try_map_memory(allocation_base, allocation_bytes, protection); + succeeded = c.emu.try_map_memory(allocation_base, allocation_bytes, protection); if (succeeded || !allocate_anywhere) { break; @@ -411,10 +470,9 @@ namespace base_address.write(allocation_base); - emu.reg(x64_register::rax, succeeded - ? STATUS_SUCCESS - : STATUS_NOT_SUPPORTED // No idea what the correct code is - ); + return succeeded + ? STATUS_SUCCESS + : STATUS_NOT_SUPPORTED; // No idea what the correct code is } void handle_NtAllocateVirtualMemoryEx(x64_emulator& emu) @@ -512,15 +570,17 @@ void handle_syscall(x64_emulator& emu, process_context& context) printf("Handling syscall: %X (%llX)\n", syscall_id, address); + syscall_context c{emu, context}; + try { switch (syscall_id) { case 0x12: - handle_NtOpenKey(emu); + forward(c, handle_NtOpenKey); break; case 0x18: - handle_NtAllocateVirtualMemory(emu); + forward(c, handle_NtAllocateVirtualMemory); break; case 0x1E: handle_NtFreeVirtualMemory(emu); @@ -544,16 +604,16 @@ void handle_syscall(x64_emulator& emu, process_context& context) handle_NtProtectVirtualMemory(emu); break; case 0x5E: - handle_NtTraceEvent(emu); + forward(c, handle_NtTraceEvent); break; case 0x78: handle_NtAllocateVirtualMemoryEx(emu); break; case 0xB2: - handle_NtCreateIoCompletion(emu); + forward(c, handle_NtCreateIoCompletion); break; case 0x11A: - handle_NtManageHotPatch(emu); + forward(c, handle_NtManageHotPatch); break; case 0x16E: handle_NtQuerySystemInformationEx(emu);