From 3dfad0f78928a794d73cbe65ff1c765ec9824287 Mon Sep 17 00:00:00 2001 From: Igor Pissolati Date: Sat, 19 Apr 2025 13:52:13 -0300 Subject: [PATCH 1/5] Add more atom-related syscalls --- src/windows-emulator/process_context.cpp | 76 ++++++++++++++++++++++ src/windows-emulator/process_context.hpp | 20 +++++- src/windows-emulator/syscalls.cpp | 81 ++++++++++++------------ 3 files changed, 136 insertions(+), 41 deletions(-) diff --git a/src/windows-emulator/process_context.cpp b/src/windows-emulator/process_context.cpp index b8d22677..36205f3e 100644 --- a/src/windows-emulator/process_context.cpp +++ b/src/windows-emulator/process_context.cpp @@ -236,3 +236,79 @@ handle process_context::create_thread(memory_manager& memory, const uint64_t sta this->callbacks_->on_create_thread(h, *thr); return h; } + +uint16_t process_context::add_or_find_atom(std::u16string name) +{ + uint16_t index = 0; + if (!atoms.empty()) + { + auto i = atoms.end(); + --i; + index = i->first + 1; + } + + std::optional last_entry{}; + for (auto& entry : atoms) + { + if (entry.second.name == name) + { + entry.second.ref_count++; + return entry.first; + } + + if (entry.first > 0) + { + if (!last_entry) + { + index = 0; + } + else + { + const auto diff = entry.first - *last_entry; + if (diff > 1) + { + index = *last_entry + 1; + } + } + } + + last_entry = entry.first; + } + + atoms[index] = {std::move(name), 1}; + + return index; +} + +bool process_context::delete_atom(const std::u16string& name) +{ + for (auto it = atoms.begin(); it != atoms.end(); ++it) + { + if (it->second.name == name) + { + if (--it->second.ref_count == 0) + { + atoms.erase(it); + } + return true; + } + } + + return false; +} + +bool process_context::delete_atom(uint16_t atom_id) +{ + const auto it = atoms.find(atom_id); + if (it == atoms.end()) + { + return false; + } + + if (--it->second.ref_count == 0) + { + atoms.erase(it); + } + + return true; +} diff --git a/src/windows-emulator/process_context.hpp b/src/windows-emulator/process_context.hpp index 1be428b3..ac42f5f1 100644 --- a/src/windows-emulator/process_context.hpp +++ b/src/windows-emulator/process_context.hpp @@ -36,6 +36,20 @@ struct process_context utils::optional_function on_thread_terminated{}; }; + struct atom_entry + { + std::u16string name; + uint32_t ref_count = 0; + + atom_entry(std::u16string n, uint32_t count) + : name(std::move(n)), + ref_count(count) + { + } + + atom_entry() = default; + }; + process_context(x64_emulator& emu, memory_manager& memory, utils::clock& clock, callbacks& cb) : callbacks_(&cb), base_allocator(emu), @@ -51,6 +65,10 @@ struct process_context handle create_thread(memory_manager& memory, uint64_t start_address, uint64_t argument, uint64_t stack_size, bool suspended); + uint16_t add_or_find_atom(std::u16string name); + bool delete_atom(const std::u16string& name); + bool delete_atom(uint16_t atom_id); + void serialize(utils::buffer_serializer& buffer) const; void deserialize(utils::buffer_deserializer& buffer); @@ -86,7 +104,7 @@ struct process_context handle_store ports{}; handle_store mutants{}; handle_store registry_keys{}; - std::map atoms{}; + std::map atoms{}; std::vector default_register_set{}; diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index bf18f69c..536f02e5 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -525,47 +525,21 @@ namespace syscalls c.emu.read_memory(atom_name, name.data(), length); - uint16_t index = 0; - if (!c.proc.atoms.empty()) - { - auto i = c.proc.atoms.end(); - --i; - index = i->first + 1; - } - - std::optional last_entry{}; - for (auto& entry : c.proc.atoms) - { - if (entry.second == name) - { - if (atom) - { - atom.write(entry.first); - return STATUS_SUCCESS; - } - } - - if (entry.first > 0) - { - if (!last_entry) - { - index = 0; - } - else - { - const auto diff = entry.first - *last_entry; - if (diff > 1) - { - index = *last_entry + 1; - } - } - } - - last_entry = entry.first; - } - - c.proc.atoms[index] = std::move(name); + uint16_t index = c.proc.add_or_find_atom(name); atom.write(index); + + return STATUS_SUCCESS; + } + + NTSTATUS handle_NtAddAtom(const syscall_context& c, const uint64_t atom_name, const ULONG length, + const emulator_object atom) + { + return handle_NtAddAtomEx(c, atom_name, length, atom, 0); + } + + NTSTATUS handle_NtDeleteAtom(const syscall_context& c, const emulator_object atom) + { + c.proc.delete_atom(atom.read()); return STATUS_SUCCESS; } @@ -643,6 +617,29 @@ namespace syscalls { return 0; } + + template + struct CLSMENUNAME + { + LPSTR pszClientAnsiMenuName; + LPWSTR pwszClientUnicodeMenuName; + EMULATOR_CAST(typename Traits::PVOID, UNICODE_STRING*) pusMenuName; + }; + NTSTATUS handle_NtUserRegisterClassExWOW(const syscall_context& c, const emulator_object /*wnd_class_ex*/, + const emulator_object>> class_name, + const emulator_object>> /*class_version*/, + const emulator_object>> /*class_menu_name*/, + const DWORD /*function_id*/, const DWORD /*flags*/, const emulator_pointer /*wow*/) + { + uint16_t index = c.proc.add_or_find_atom(read_unicode_string(c.emu, class_name)); + return index; + } + + NTSTATUS handle_NtUserUnregisterClass(const syscall_context& c, const emulator_object>> class_name, + const emulator_pointer /*instance*/, const emulator_object>> /*class_menu_name*/) + { + return c.proc.delete_atom(read_unicode_string(c.emu, class_name)); + } } void syscall_dispatcher::add_handlers(std::map& handler_mapping) @@ -705,6 +702,8 @@ void syscall_dispatcher::add_handlers(std::map& ha add_handler(NtQueryInformationToken); add_handler(NtDxgkIsFeatureEnabled); add_handler(NtAddAtomEx); + add_handler(NtAddAtom); + add_handler(NtDeleteAtom); add_handler(NtInitializeNlsFiles); add_handler(NtUnmapViewOfSection); add_handler(NtUnmapViewOfSectionEx); @@ -788,6 +787,8 @@ void syscall_dispatcher::add_handlers(std::map& ha add_handler(NtCreateNamedPipeFile); add_handler(NtFsControlFile); add_handler(NtQueryFullAttributesFile); + add_handler(NtUserRegisterClassExWOW); + add_handler(NtUserUnregisterClass); #undef add_handler } From 6b1df674abed7313cdb93e196e15c9422a1e4b4c Mon Sep 17 00:00:00 2001 From: Igor Pissolati Date: Sat, 19 Apr 2025 15:07:12 -0300 Subject: [PATCH 2/5] Fix non-windows builds --- src/windows-emulator/syscalls.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index 536f02e5..59164baa 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -621,11 +621,11 @@ namespace syscalls template struct CLSMENUNAME { - LPSTR pszClientAnsiMenuName; - LPWSTR pwszClientUnicodeMenuName; + EMULATOR_CAST(typename Traits::PVOID, char*) pszClientAnsiMenuName; + EMULATOR_CAST(typename Traits::PVOID, char16_t*) pwszClientUnicodeMenuName; EMULATOR_CAST(typename Traits::PVOID, UNICODE_STRING*) pusMenuName; }; - NTSTATUS handle_NtUserRegisterClassExWOW(const syscall_context& c, const emulator_object /*wnd_class_ex*/, + NTSTATUS handle_NtUserRegisterClassExWOW(const syscall_context& c, const emulator_pointer /*wnd_class_ex*/, const emulator_object>> class_name, const emulator_object>> /*class_version*/, const emulator_object>> /*class_menu_name*/, From 09b25d8c89d2cf1a1f2d5e78da30c51fcb560702 Mon Sep 17 00:00:00 2001 From: Igor Pissolati Date: Sat, 19 Apr 2025 15:18:26 -0300 Subject: [PATCH 3/5] Fix NtDeleteAtom signature --- src/windows-emulator/syscalls.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index 59164baa..720d6dab 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -537,9 +537,9 @@ namespace syscalls return handle_NtAddAtomEx(c, atom_name, length, atom, 0); } - NTSTATUS handle_NtDeleteAtom(const syscall_context& c, const emulator_object atom) + NTSTATUS handle_NtDeleteAtom(const syscall_context& c, const RTL_ATOM atom) { - c.proc.delete_atom(atom.read()); + c.proc.delete_atom(atom); return STATUS_SUCCESS; } From 88a744a7566d8dae92ba5bba7fc9999194e820dc Mon Sep 17 00:00:00 2001 From: Igor Pissolati Date: Sat, 19 Apr 2025 15:21:22 -0300 Subject: [PATCH 4/5] Hopefully fix formatting --- src/windows-emulator/syscalls.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index 720d6dab..80e6fd06 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -625,18 +625,22 @@ namespace syscalls EMULATOR_CAST(typename Traits::PVOID, char16_t*) pwszClientUnicodeMenuName; EMULATOR_CAST(typename Traits::PVOID, UNICODE_STRING*) pusMenuName; }; + NTSTATUS handle_NtUserRegisterClassExWOW(const syscall_context& c, const emulator_pointer /*wnd_class_ex*/, const emulator_object>> class_name, const emulator_object>> /*class_version*/, const emulator_object>> /*class_menu_name*/, - const DWORD /*function_id*/, const DWORD /*flags*/, const emulator_pointer /*wow*/) + const DWORD /*function_id*/, const DWORD /*flags*/, + const emulator_pointer /*wow*/) { uint16_t index = c.proc.add_or_find_atom(read_unicode_string(c.emu, class_name)); return index; } - NTSTATUS handle_NtUserUnregisterClass(const syscall_context& c, const emulator_object>> class_name, - const emulator_pointer /*instance*/, const emulator_object>> /*class_menu_name*/) + NTSTATUS handle_NtUserUnregisterClass(const syscall_context& c, + const emulator_object>> class_name, + const emulator_pointer /*instance*/, + const emulator_object>> /*class_menu_name*/) { return c.proc.delete_atom(read_unicode_string(c.emu, class_name)); } From e74b1dad5a619835e1cf77310f8d440e1e46f304 Mon Sep 17 00:00:00 2001 From: Igor Pissolati Date: Sat, 19 Apr 2025 17:23:03 -0300 Subject: [PATCH 5/5] Fix formatting (attempt 2) --- src/windows-emulator/syscalls.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index 80e6fd06..bd3126fc 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -626,12 +626,12 @@ namespace syscalls EMULATOR_CAST(typename Traits::PVOID, UNICODE_STRING*) pusMenuName; }; - NTSTATUS handle_NtUserRegisterClassExWOW(const syscall_context& c, const emulator_pointer /*wnd_class_ex*/, - const emulator_object>> class_name, - const emulator_object>> /*class_version*/, - const emulator_object>> /*class_menu_name*/, - const DWORD /*function_id*/, const DWORD /*flags*/, - const emulator_pointer /*wow*/) + NTSTATUS handle_NtUserRegisterClassExWOW( + const syscall_context& c, const emulator_pointer /*wnd_class_ex*/, + const emulator_object>> class_name, + const emulator_object>> /*class_version*/, + const emulator_object>> /*class_menu_name*/, const DWORD /*function_id*/, + const DWORD /*flags*/, const emulator_pointer /*wow*/) { uint16_t index = c.proc.add_or_find_atom(read_unicode_string(c.emu, class_name)); return index;