From ce6cb0116bcf17b6155229013c973a6b81b1f7f2 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sat, 21 Dec 2024 20:18:59 +0100 Subject: [PATCH] Support more syscalls --- src/emulator/memory_manager.hpp | 6 +++ src/windows-emulator/process_context.hpp | 9 ++-- src/windows-emulator/syscalls.cpp | 57 ++++++++++++++++++++++- src/windows-emulator/windows_emulator.cpp | 23 +++++++-- 4 files changed, 87 insertions(+), 8 deletions(-) diff --git a/src/emulator/memory_manager.hpp b/src/emulator/memory_manager.hpp index d78d43a..0d7bbb9 100644 --- a/src/emulator/memory_manager.hpp +++ b/src/emulator/memory_manager.hpp @@ -71,6 +71,12 @@ class memory_manager this->write_memory(address, &value, sizeof(value)); } + template + void write_memory(void* address, const T& value) + { + this->write_memory(reinterpret_cast(address), &value, sizeof(value)); + } + void write_memory(void* address, const void* data, const size_t size) { this->write_memory(reinterpret_cast(address), data, size); diff --git a/src/windows-emulator/process_context.hpp b/src/windows-emulator/process_context.hpp index 500c563..2a78ce1 100644 --- a/src/windows-emulator/process_context.hpp +++ b/src/windows-emulator/process_context.hpp @@ -253,7 +253,8 @@ class emulator_thread : ref_counted_object std::wstring name{}; std::optional exit_status{}; - std::optional await_object{}; + std::vector await_objects{}; + bool await_any{false}; bool waiting_for_alert{false}; bool alerted{false}; std::optional await_time{}; @@ -317,7 +318,8 @@ class emulator_thread : ref_counted_object buffer.write_string(this->name); buffer.write_optional(this->exit_status); - buffer.write_optional(this->await_object); + buffer.write_vector(this->await_objects); + buffer.write(this->await_any); buffer.write(this->waiting_for_alert); buffer.write(this->alerted); @@ -349,7 +351,8 @@ class emulator_thread : ref_counted_object buffer.read_string(this->name); buffer.read_optional(this->exit_status); - buffer.read_optional(this->await_object); + buffer.read_vector(this->await_objects); + buffer.read(this->await_any); buffer.read(this->waiting_for_alert); buffer.read(this->alerted); diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index 55325fe..463cda6 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -399,6 +399,11 @@ namespace return STATUS_NO_TOKEN; } + NTSTATUS handle_NtOpenThreadTokenEx() + { + return STATUS_NO_TOKEN; + } + NTSTATUS handle_NtCreateEvent(const syscall_context& c, const emulator_object event_handle, const ACCESS_MASK /*desired_access*/, const emulator_object object_attributes, @@ -1764,6 +1769,12 @@ namespace return STATUS_NOT_SUPPORTED; } + NTSTATUS handle_NtOpenProcessTokenEx() + { + //puts("NtOpenProcessToken not supported"); + return STATUS_NOT_SUPPORTED; + } + NTSTATUS handle_NtQuerySecurityAttributesToken() { //puts("NtQuerySecurityAttributesToken not supported"); @@ -2554,6 +2565,46 @@ namespace return FALSE; } + NTSTATUS handle_NtWaitForMultipleObjects(const syscall_context& c, const ULONG count, + const emulator_object handles, const WAIT_TYPE wait_type, + const BOOLEAN alertable, const emulator_object timeout) + { + if (alertable) + { + c.win_emu.logger.print(color::gray, "Alertable NtWaitForMultipleObjects not supported yet!\n"); + } + + if (wait_type != WaitAny && wait_type != WaitAll) + { + puts("Wait type not supported!"); + c.emu.stop(); + return STATUS_NOT_SUPPORTED; + } + + auto& t = c.win_emu.current_thread(); + t.await_objects.clear(); + t.await_any = wait_type == WaitAny; + + for (ULONG i = 0; i < count; ++i) + { + const auto h = handles.read(i); + + if (h.value.type != handle_types::thread && h.value.type != handle_types::event) + { + c.win_emu.logger.print(color::gray, "Unsupported handle type for NtWaitForMultipleObjects!\n"); + return STATUS_NOT_SUPPORTED; + } + } + + if (timeout.value() && !t.await_time.has_value()) + { + t.await_time = convert_delay_interval_to_time_point(timeout.read()); + } + + c.win_emu.yield_thread(); + return STATUS_SUCCESS; + } + NTSTATUS handle_NtWaitForSingleObject(const syscall_context& c, const handle h, const BOOLEAN alertable, const emulator_object timeout) @@ -2570,7 +2621,8 @@ namespace } auto& t = c.win_emu.current_thread(); - t.await_object = h; + t.await_objects = {h}; + t.await_any = false; if (timeout.value() && !t.await_time.has_value()) { @@ -2690,6 +2742,7 @@ void syscall_dispatcher::add_handlers(std::map& ha add_handler(NtFreeVirtualMemory); add_handler(NtQueryVirtualMemory); add_handler(NtOpenThreadToken); + add_handler(NtOpenThreadTokenEx); add_handler(NtQueryPerformanceCounter); add_handler(NtQuerySystemInformation); add_handler(NtCreateEvent); @@ -2715,6 +2768,7 @@ void syscall_dispatcher::add_handlers(std::map& ha add_handler(NtDeviceIoControlFile); add_handler(NtQueryWnfStateData); add_handler(NtOpenProcessToken); + add_handler(NtOpenProcessTokenEx); add_handler(NtQuerySecurityAttributesToken); add_handler(NtQueryLicenseValue); add_handler(NtTestAlert); @@ -2766,6 +2820,7 @@ void syscall_dispatcher::add_handlers(std::map& ha add_handler(NtGetCurrentProcessorNumberEx); add_handler(NtQueryObject); add_handler(NtQueryAttributesFile); + add_handler(NtWaitForMultipleObjects); #undef add_handler } diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index fa8ef0c..568ca92 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -591,7 +591,7 @@ void emulator_thread::mark_as_ready(const NTSTATUS status) { this->pending_status = status; this->await_time = {}; - this->await_object = {}; + this->await_objects = {}; // TODO: Find out if this is correct if (this->waiting_for_alert) @@ -625,11 +625,26 @@ bool emulator_thread::is_thread_ready(windows_emulator& win_emu) return false; } - if (this->await_object.has_value()) + if (!this->await_objects.empty()) { - if (is_object_signaled(win_emu.process(), *this->await_object)) + bool all_signaled = true; + for (uint32_t i = 0; i < this->await_objects.size(); ++i) { - this->mark_as_ready(STATUS_WAIT_0); + const auto& obj = this->await_objects[i]; + + const auto signaled = is_object_signaled(win_emu.process(), obj); + all_signaled &= signaled; + + if (signaled && this->await_any) + { + this->mark_as_ready(STATUS_WAIT_0 + i); + return true; + } + } + + if (!this->await_any && all_signaled) + { + this->mark_as_ready(STATUS_SUCCESS); return true; }