From 86609ff151208998a1690987792aaa04beb79bbf Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sat, 2 Nov 2024 22:52:09 +0100 Subject: [PATCH] Almost working registry support --- deps/windows-hive-parser | 2 +- src/windows-emulator/registry_manager.cpp | 27 ++++++++++ src/windows-emulator/registry_manager.hpp | 7 +++ src/windows-emulator/syscalls.cpp | 63 ++++++++++++++++++++++- 4 files changed, 96 insertions(+), 3 deletions(-) diff --git a/deps/windows-hive-parser b/deps/windows-hive-parser index fdeabc39..df62310e 160000 --- a/deps/windows-hive-parser +++ b/deps/windows-hive-parser @@ -1 +1 @@ -Subproject commit fdeabc39b1ed79fb7472fd08288eba8e6649a812 +Subproject commit df62310ec375a47f9460f5c756346462033359b8 diff --git a/src/windows-emulator/registry_manager.cpp b/src/windows-emulator/registry_manager.cpp index 7137df9b..0008452c 100644 --- a/src/windows-emulator/registry_manager.cpp +++ b/src/windows-emulator/registry_manager.cpp @@ -109,6 +109,33 @@ std::optional registry_manager::get_key(const std::filesystem::pat return {std::move(reg_key)}; } +std::optional registry_manager::get_value(const registry_key& key, const std::string_view name) +{ + const auto iterator = this->hives_.find(key.hive); + if (iterator == this->hives_.end()) + { + return {}; + } + + auto entry = iterator->second->get_subkey(key.path.begin()->string(), key.path.generic_string()); + if (!entry) + { + return {}; + } + + const auto value = entry->get_key_value(name); + if (!value) + { + return {}; + } + + registry_value v{}; + v.type = value->first; + v.data = value->second; + + return v; +} + registry_manager::hive_map::iterator registry_manager::find_hive(const std::filesystem::path& key) { for (auto i = this->hives_.begin(); i != this->hives_.end(); ++i) diff --git a/src/windows-emulator/registry_manager.hpp b/src/windows-emulator/registry_manager.hpp index 3f96cbde..d8fb7ce9 100644 --- a/src/windows-emulator/registry_manager.hpp +++ b/src/windows-emulator/registry_manager.hpp @@ -23,6 +23,12 @@ struct registry_key } }; +struct registry_value +{ + uint32_t type; + std::string_view data; +}; + class registry_manager { public: @@ -36,6 +42,7 @@ public: void deserialize(utils::buffer_deserializer& buffer); std::optional get_key(const std::filesystem::path& key); + std::optional get_value(const registry_key& key, const std::string_view name); private: hive_map hives_{}; diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index 9bd29fa7..2f22d2a1 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -74,9 +74,62 @@ namespace return STATUS_SUCCESS; } - NTSTATUS handle_NtOpenKeyEx() + NTSTATUS handle_NtOpenKeyEx(const syscall_context& c, const emulator_object key_handle, + const ACCESS_MASK desired_access, + const emulator_object object_attributes, + ULONG /*open_options*/) { - return STATUS_NOT_SUPPORTED; + return handle_NtOpenKey(c, key_handle, desired_access, object_attributes); + } + + NTSTATUS handle_NtQueryValueKey(const syscall_context& c, handle key_handle, + const emulator_object value_name, + KEY_VALUE_INFORMATION_CLASS key_value_information_class, + uint64_t key_value_information, + ULONG length, const emulator_object result_length) + { + if (key_value_information_class != KeyValuePartialInformation) + { + c.win_emu.logger.print(color::gray, "Unsupported registry class: %X\n", key_value_information_class); + c.emu.stop(); + return STATUS_NOT_SUPPORTED; + } + + const auto* key = c.proc.registry_keys.get(key_handle); + if (!key) + { + return STATUS_INVALID_HANDLE; + } + + const auto wide_name = read_unicode_string(c.emu, value_name); + const std::string name(wide_name.begin(), wide_name.end()); + + const auto value = c.proc.registry.get_value(*key, name); + if (!value) + { + return STATUS_OBJECT_NAME_NOT_FOUND; + } + + const auto required_size = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + value->data.size() - 1; + result_length.write(static_cast(required_size)); + + if (required_size > length) + { + return STATUS_BUFFER_TOO_SMALL; + } + + KEY_VALUE_PARTIAL_INFORMATION partial_info{}; + partial_info.TitleIndex = 0; + partial_info.Type = value->type; + partial_info.DataLength = static_cast(value->data.size()); + + const emulator_object partial_info_obj{c.emu, key_value_information}; + partial_info_obj.write(partial_info); + + c.emu.write_memory(key_value_information + offsetof(KEY_VALUE_PARTIAL_INFORMATION, Data), value->data.data(), + value->data.size()); + + return STATUS_SUCCESS; } NTSTATUS handle_NtSetInformationThread(const syscall_context& c, const uint64_t thread_handle, @@ -165,6 +218,11 @@ namespace return STATUS_SUCCESS; } + if (value.type == handle_types::registry && c.proc.registry_keys.erase(handle)) + { + return STATUS_SUCCESS; + } + return STATUS_INVALID_HANDLE; } @@ -2276,6 +2334,7 @@ void syscall_dispatcher::add_handlers(std::map& ha add_handler(NtReadFile); add_handler(NtSetInformationFile); add_handler(NtUserRegisterWindowMessage); + add_handler(NtQueryValueKey); #undef add_handler }