From 4be39b1fe7ff9040de3d4ff4b51d0bd08ac69efa Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sun, 22 Dec 2024 15:31:33 +0100 Subject: [PATCH] Prepare mutant support --- src/windows-emulator/handles.hpp | 1 + src/windows-emulator/process_context.hpp | 25 +++++++++ src/windows-emulator/syscalls.cpp | 64 ++++++++++++++++++++++- src/windows-emulator/windows_emulator.cpp | 17 ++++++ 4 files changed, 105 insertions(+), 2 deletions(-) diff --git a/src/windows-emulator/handles.hpp b/src/windows-emulator/handles.hpp index e601af51..85c6f99a 100644 --- a/src/windows-emulator/handles.hpp +++ b/src/windows-emulator/handles.hpp @@ -15,6 +15,7 @@ struct handle_types port, thread, registry, + mutant, }; }; diff --git a/src/windows-emulator/process_context.hpp b/src/windows-emulator/process_context.hpp index 2a78ce18..1f2691ce 100644 --- a/src/windows-emulator/process_context.hpp +++ b/src/windows-emulator/process_context.hpp @@ -84,6 +84,28 @@ struct event : ref_counted_object } }; +struct mutant : ref_counted_object +{ + bool locked{false}; + std::wstring name{}; + + void serialize(utils::buffer_serializer& buffer) const + { + buffer.write(this->locked); + buffer.write(this->name); + + ref_counted_object::serialize(buffer); + } + + void deserialize(utils::buffer_deserializer& buffer) + { + buffer.read(this->locked); + buffer.read(this->name); + + ref_counted_object::deserialize(buffer); + } +}; + struct file { utils::file_handle handle{}; @@ -436,6 +458,7 @@ struct process_context handle_store devices{}; handle_store semaphores{}; handle_store ports{}; + handle_store mutants{}; handle_store registry_keys{}; std::map atoms{}; @@ -473,6 +496,7 @@ struct process_context buffer.write(this->devices); buffer.write(this->semaphores); buffer.write(this->ports); + buffer.write(this->mutants); buffer.write(this->registry_keys); buffer.write_map(this->atoms); @@ -515,6 +539,7 @@ struct process_context buffer.read(this->devices); buffer.read(this->semaphores); buffer.read(this->ports); + buffer.read(this->mutants); buffer.read(this->registry_keys); buffer.read_map(this->atoms); diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index 193f161f..48072a5a 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -386,6 +386,11 @@ namespace return STATUS_SUCCESS; } + if (value.type == handle_types::mutant && c.proc.mutants.erase(h)) + { + return STATUS_SUCCESS; + } + return STATUS_INVALID_HANDLE; } @@ -394,6 +399,42 @@ namespace return STATUS_SUCCESS; } + NTSTATUS handle_NtCreateMutant(const syscall_context& c, const emulator_object mutant_handle, + const ACCESS_MASK /*desired_access*/, + const emulator_object object_attributes, + const BOOLEAN initial_owner) + { + std::wstring name{}; + if (object_attributes) + { + const auto attributes = object_attributes.read(); + if (attributes.ObjectName) + { + name = read_unicode_string(c.emu, attributes.ObjectName); + } + } + + if (!name.empty()) + { + for (const auto& mutant : c.proc.mutants) + { + if (mutant.second.name == name) + { + return STATUS_OBJECT_NAME_EXISTS; + } + } + } + + mutant e{}; + e.locked = initial_owner != FALSE; + e.name = std::move(name); + + const auto handle = c.proc.mutants.store(std::move(e)); + mutant_handle.write(handle); + + return STATUS_SUCCESS; + } + NTSTATUS handle_NtCreateEvent(const syscall_context& c, const emulator_object event_handle, const ACCESS_MASK /*desired_access*/, const emulator_object object_attributes, @@ -409,6 +450,17 @@ namespace } } + if (!name.empty()) + { + for (const auto& event : c.proc.events) + { + if (event.second.name == name) + { + return STATUS_OBJECT_NAME_EXISTS; + } + } + } + event e{}; e.type = event_type; e.signaled = initial_state != FALSE; @@ -2741,6 +2793,13 @@ namespace return FALSE; } + bool is_awaitable_object_type(const handle h) + { + return h.value.type == handle_types::thread // + || h.value.type == handle_types::mutant // + || h.value.type == handle_types::event; + } + 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) @@ -2765,7 +2824,7 @@ namespace { const auto h = handles.read(i); - if (h.value.type != handle_types::thread && h.value.type != handle_types::event) + if (!is_awaitable_object_type(h)) { c.win_emu.logger.print(color::gray, "Unsupported handle type for NtWaitForMultipleObjects: %d!\n", h.value.type); @@ -2791,7 +2850,7 @@ namespace c.win_emu.logger.print(color::gray, "Alertable NtWaitForSingleObject not supported yet!\n"); } - if (h.value.type != handle_types::thread && h.value.type != handle_types::event) + if (!is_awaitable_object_type(h)) { c.win_emu.logger.print(color::gray, "Unsupported handle type for NtWaitForSingleObject: %d!\n", h.value.type); @@ -2999,6 +3058,7 @@ void syscall_dispatcher::add_handlers(std::map& ha add_handler(NtQueryObject); add_handler(NtQueryAttributesFile); add_handler(NtWaitForMultipleObjects); + add_handler(NtCreateMutant); #undef add_handler } diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index 568ca92a..5eb27e15 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -539,6 +539,23 @@ namespace break; } + case handle_types::mutant: + { + auto* e = c.mutants.get(h); + if (e) + { + if (e->locked) + { + return false; + } + + e->locked = true; + return true; + } + + break; + } + case handle_types::thread: { const auto* t = c.threads.get(h);