From 53fb2f9116a7ab168a0b6f648200ce1e37cbec72 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sat, 22 Mar 2025 19:38:23 +0100 Subject: [PATCH] Support more syscalls --- src/common/platform/process.hpp | 4 ++ src/common/platform/status.hpp | 1 + src/windows-emulator/emulator_thread.cpp | 6 ++- src/windows-emulator/emulator_thread.hpp | 7 ++- src/windows-emulator/process_context.cpp | 4 +- src/windows-emulator/process_context.hpp | 3 +- src/windows-emulator/syscalls.cpp | 59 +++++++++++++++++++++-- src/windows-emulator/windows_emulator.cpp | 3 +- 8 files changed, 75 insertions(+), 12 deletions(-) diff --git a/src/common/platform/process.hpp b/src/common/platform/process.hpp index 88d4712c..c42c2792 100644 --- a/src/common/platform/process.hpp +++ b/src/common/platform/process.hpp @@ -2,6 +2,10 @@ // NOLINTBEGIN(modernize-use-using,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) +#ifndef OS_WINDOWS +#define CREATE_SUSPENDED 0x00000004 +#endif + #define CONTEXT_X86_MAIN 0x00010000 #define CONTEXT_AMD64_MAIN 0x100000 #define CONTEXT_CONTROL_32 (CONTEXT_X86_MAIN | 0x1L) diff --git a/src/common/platform/status.hpp b/src/common/platform/status.hpp index 0d0d9b62..0bda4ca5 100644 --- a/src/common/platform/status.hpp +++ b/src/common/platform/status.hpp @@ -43,6 +43,7 @@ using NTSTATUS = std::uint32_t; #define STATUS_INVALID_ADDRESS ((NTSTATUS)0xC0000141L) #define STATUS_NOT_FOUND ((NTSTATUS)0xC0000225L) #define STATUS_CONNECTION_REFUSED ((NTSTATUS)0xC0000236L) +#define STATUS_TIMER_RESOLUTION_NOT_SET ((NTSTATUS)0xC0000245L) #define STATUS_ADDRESS_ALREADY_ASSOCIATED ((NTSTATUS)0xC0000328L) #define STATUS_BUFFER_OVERFLOW ((NTSTATUS)0x80000005L) diff --git a/src/windows-emulator/emulator_thread.cpp b/src/windows-emulator/emulator_thread.cpp index d1fd7aec..1e9f6f58 100644 --- a/src/windows-emulator/emulator_thread.cpp +++ b/src/windows-emulator/emulator_thread.cpp @@ -96,12 +96,14 @@ namespace } emulator_thread::emulator_thread(memory_manager& memory, const process_context& context, const uint64_t start_address, - const uint64_t argument, const uint64_t stack_size, const uint32_t id) + const uint64_t argument, const uint64_t stack_size, const bool suspended, + const uint32_t id) : memory_ptr(&memory), stack_size(page_align_up(std::max(stack_size, static_cast(STACK_SIZE)))), start_address(start_address), argument(argument), id(id), + suspended(suspended), last_registers(context.default_register_set) { this->stack_base = memory.allocate_memory(this->stack_size, memory_permission::read_write); @@ -151,7 +153,7 @@ bool emulator_thread::is_terminated() const bool emulator_thread::is_thread_ready(process_context& process, utils::clock& clock) { - if (this->is_terminated()) + if (this->is_terminated() || this->suspended > 0) { return false; } diff --git a/src/windows-emulator/emulator_thread.hpp b/src/windows-emulator/emulator_thread.hpp index dc64f98c..b0cc364b 100644 --- a/src/windows-emulator/emulator_thread.hpp +++ b/src/windows-emulator/emulator_thread.hpp @@ -22,7 +22,7 @@ class emulator_thread : public ref_counted_object } emulator_thread(memory_manager& memory, const process_context& context, uint64_t start_address, uint64_t argument, - uint64_t stack_size, uint32_t id); + uint64_t stack_size, bool suspended, uint32_t id); emulator_thread(const emulator_thread&) = delete; emulator_thread& operator=(const emulator_thread&) = delete; @@ -54,6 +54,7 @@ class emulator_thread : public ref_counted_object bool await_any{false}; bool waiting_for_alert{false}; bool alerted{false}; + uint32_t suspended{0}; std::optional await_time{}; std::optional pending_status{}; @@ -123,6 +124,8 @@ class emulator_thread : public ref_counted_object buffer.write(this->waiting_for_alert); buffer.write(this->alerted); + buffer.write(this->suspended); + buffer.write_optional(this->await_time); buffer.write_optional(this->pending_status); buffer.write_optional(this->gs_segment); @@ -156,6 +159,8 @@ class emulator_thread : public ref_counted_object buffer.read(this->waiting_for_alert); buffer.read(this->alerted); + buffer.read(this->suspended); + buffer.read_optional(this->await_time); buffer.read_optional(this->pending_status); buffer.read_optional(this->gs_segment, [this] { return emulator_allocator(*this->memory_ptr); }); diff --git a/src/windows-emulator/process_context.cpp b/src/windows-emulator/process_context.cpp index 947543bb..fc9cb06b 100644 --- a/src/windows-emulator/process_context.cpp +++ b/src/windows-emulator/process_context.cpp @@ -198,9 +198,9 @@ void process_context::deserialize(utils::buffer_deserializer& buffer) } handle process_context::create_thread(memory_manager& memory, const uint64_t start_address, const uint64_t argument, - const uint64_t stack_size) + const uint64_t stack_size, const bool suspended) { - emulator_thread t{memory, *this, start_address, argument, stack_size, ++this->spawned_thread_count}; + emulator_thread t{memory, *this, start_address, argument, stack_size, suspended, ++this->spawned_thread_count}; auto [h, thr] = this->threads.store_and_get(std::move(t)); this->callbacks_->on_create_thread(h, *thr); return h; diff --git a/src/windows-emulator/process_context.hpp b/src/windows-emulator/process_context.hpp index 2118c59c..73f844b2 100644 --- a/src/windows-emulator/process_context.hpp +++ b/src/windows-emulator/process_context.hpp @@ -50,7 +50,8 @@ struct process_context void setup(x64_emulator& emu, memory_manager& memory, const application_settings& app_settings, const mapped_module& executable, const mapped_module& ntdll, const apiset::container& apiset_container); - handle create_thread(memory_manager& memory, uint64_t start_address, uint64_t argument, uint64_t stack_size); + handle create_thread(memory_manager& memory, uint64_t start_address, uint64_t argument, uint64_t stack_size, + bool suspended); void serialize(utils::buffer_serializer& buffer) const; void deserialize(utils::buffer_deserializer& buffer); diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index 5dd09b4a..511b8eb6 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -299,7 +299,7 @@ namespace return STATUS_INVALID_HANDLE; } - if (info_class == ThreadSchedulerSharedDataSlot) + if (info_class == ThreadSchedulerSharedDataSlot || info_class == ThreadBasePriority) { return STATUS_SUCCESS; } @@ -1169,7 +1169,8 @@ namespace { if (info_class == SystemFlushInformation || info_class == SystemFeatureConfigurationInformation || info_class == SystemSupportedProcessorArchitectures2 || - info_class == SystemFeatureConfigurationSectionInformation) + info_class == SystemFeatureConfigurationSectionInformation || + info_class == SystemLogicalProcessorInformation) { return STATUS_NOT_SUPPORTED; } @@ -1453,7 +1454,8 @@ namespace return STATUS_SUCCESS; } - if (info_class == ProcessEnclaveInformation || info_class == ProcessMitigationPolicy) + if (info_class == ProcessEnclaveInformation || info_class == ProcessMitigationPolicy || + info_class == ProcessGroupInformation) { return STATUS_NOT_SUPPORTED; } @@ -2523,6 +2525,11 @@ namespace 0xD4, 0x04, 0x4B, 0x68, 0x42, 0x34, 0x23, 0xBE, 0x69, 0x4E, 0xE9, 0x03, 0x00, 0x00, }; + if (token_information_class == TokenAppContainerSid) + { + return STATUS_NOT_SUPPORTED; + } + if (token_information_class == TokenUser) { constexpr auto required_size = sizeof(sid) + 0x10; @@ -3507,7 +3514,7 @@ namespace const emulator_object>> /*object_attributes*/, const handle process_handle, const uint64_t start_routine, const uint64_t argument, - const ULONG /*create_flags*/, const EmulatorTraits::SIZE_T /*zero_bits*/, + const ULONG create_flags, const EmulatorTraits::SIZE_T /*zero_bits*/, const EmulatorTraits::SIZE_T stack_size, const EmulatorTraits::SIZE_T /*maximum_stack_size*/, const emulator_object>> attribute_list) @@ -3517,7 +3524,8 @@ namespace return STATUS_NOT_SUPPORTED; } - const auto h = c.proc.create_thread(c.win_emu.memory, start_routine, argument, stack_size); + const auto h = c.proc.create_thread(c.win_emu.memory, start_routine, argument, stack_size, + create_flags & CREATE_SUSPENDED); thread_handle.write(h); if (!attribute_list) @@ -3878,6 +3886,22 @@ namespace return STATUS_SUCCESS; } + NTSTATUS handle_NtSetTimerResolution(const syscall_context&, const ULONG /*desired_resolution*/, + const BOOLEAN set_resolution, const emulator_object current_resolution) + { + if (current_resolution) + { + current_resolution.write(0x0002625a); + } + + if (set_resolution) + { + return STATUS_TIMER_RESOLUTION_NOT_SET; + } + + return STATUS_SUCCESS; + } + NTSTATUS handle_NtSetContextThread(const syscall_context& c, const handle thread_handle, const emulator_object thread_context) { @@ -3919,6 +3943,29 @@ namespace c.win_emu.yield_thread(); return STATUS_SUCCESS; } + + NTSTATUS handle_NtResumeThread(const syscall_context& c, const handle thread_handle, + const emulator_object previous_suspend_count) + { + auto* thread = c.proc.threads.get(thread_handle); + if (!thread) + { + return STATUS_INVALID_HANDLE; + } + + const auto old_count = thread->suspended; + if (previous_suspend_count) + { + previous_suspend_count.write(old_count); + } + + if (old_count > 0) + { + thread->suspended -= 1; + } + + return STATUS_SUCCESS; + } } void syscall_dispatcher::add_handlers(std::map& handler_mapping) @@ -4051,6 +4098,8 @@ void syscall_dispatcher::add_handlers(std::map& ha add_handler(NtSystemDebugControl); add_handler(NtRequestWaitReplyPort); add_handler(NtQueryDefaultLocale); + add_handler(NtSetTimerResolution); + add_handler(NtResumeThread); #undef add_handler } diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index 3df82d11..5ff9d817 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -281,7 +281,8 @@ void windows_emulator::setup_process(const application_settings& app_settings) this->dispatcher.setup(ntdll->exports, ntdll_data, win32u->exports, win32u_data); - const auto main_thread_id = context.create_thread(this->memory, this->mod_manager.executable->entry_point, 0, 0); + const auto main_thread_id = + context.create_thread(this->memory, this->mod_manager.executable->entry_point, 0, 0, false); switch_to_thread(*this, main_thread_id); }