mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-18 19:23:56 +00:00
Prepare registry support
This commit is contained in:
2
deps/windows-hive-parser
vendored
2
deps/windows-hive-parser
vendored
Submodule deps/windows-hive-parser updated: b1bd6ca49e...fdeabc39b1
@@ -13,6 +13,7 @@ struct handle_types
|
||||
semaphore,
|
||||
port,
|
||||
thread,
|
||||
registry,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "emulator_utils.hpp"
|
||||
#include "handles.hpp"
|
||||
#include "registry_manager.hpp"
|
||||
|
||||
#include "module/module_manager.hpp"
|
||||
#include <utils/nt_handle.hpp>
|
||||
@@ -375,6 +376,8 @@ struct process_context
|
||||
{
|
||||
}
|
||||
|
||||
registry_manager registry{R"(C:\Users\mauri\Desktop\windows\win-x64\registry)"}; // TODO: Fix
|
||||
|
||||
uint64_t executed_instructions{0};
|
||||
uint64_t current_ip{0};
|
||||
uint64_t previous_ip{0};
|
||||
@@ -404,6 +407,7 @@ struct process_context
|
||||
handle_store<handle_types::file, file> files{};
|
||||
handle_store<handle_types::semaphore, semaphore> semaphores{};
|
||||
handle_store<handle_types::port, port> ports{};
|
||||
handle_store<handle_types::registry, registry_key> registry_keys{};
|
||||
std::map<uint16_t, std::wstring> atoms{};
|
||||
|
||||
std::vector<std::byte> default_register_set{};
|
||||
@@ -414,6 +418,7 @@ struct process_context
|
||||
|
||||
void serialize(utils::buffer_serializer& buffer) const
|
||||
{
|
||||
buffer.write(this->registry);
|
||||
buffer.write(this->executed_instructions);
|
||||
buffer.write(this->current_ip);
|
||||
buffer.write(this->previous_ip);
|
||||
@@ -438,6 +443,7 @@ struct process_context
|
||||
buffer.write(this->files);
|
||||
buffer.write(this->semaphores);
|
||||
buffer.write(this->ports);
|
||||
buffer.write(this->registry_keys);
|
||||
buffer.write_map(this->atoms);
|
||||
|
||||
buffer.write_vector(this->default_register_set);
|
||||
@@ -449,6 +455,7 @@ struct process_context
|
||||
|
||||
void deserialize(utils::buffer_deserializer& buffer)
|
||||
{
|
||||
buffer.read(this->registry);
|
||||
buffer.read(this->executed_instructions);
|
||||
buffer.read(this->current_ip);
|
||||
buffer.read(this->previous_ip);
|
||||
@@ -477,6 +484,7 @@ struct process_context
|
||||
buffer.read(this->files);
|
||||
buffer.read(this->semaphores);
|
||||
buffer.read(this->ports);
|
||||
buffer.read(this->registry_keys);
|
||||
buffer.read_map(this->atoms);
|
||||
|
||||
buffer.read_vector(this->default_register_set);
|
||||
|
||||
123
src/windows-emulator/registry_manager.cpp
Normal file
123
src/windows-emulator/registry_manager.cpp
Normal file
@@ -0,0 +1,123 @@
|
||||
#include "registry_manager.hpp"
|
||||
#include <hive_parser.hh>
|
||||
|
||||
namespace
|
||||
{
|
||||
std::filesystem::path canonicalize_path(const std::filesystem::path& key)
|
||||
{
|
||||
auto path = key.lexically_normal().wstring();
|
||||
std::ranges::transform(path, path.begin(), std::towlower);
|
||||
return {std::move(path)};
|
||||
}
|
||||
|
||||
bool is_subpath(const std::filesystem::path& root, const std::filesystem::path& p)
|
||||
{
|
||||
auto root_it = root.begin();
|
||||
auto p_it = p.begin();
|
||||
|
||||
for (; root_it != root.end(); ++root_it, ++p_it)
|
||||
{
|
||||
if (p_it == p.end() || *root_it != *p_it)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void register_hive(registry_manager::hive_map& hives,
|
||||
const std::filesystem::path& key, const std::filesystem::path& file)
|
||||
{
|
||||
hives[canonicalize_path(key)] = std::make_unique<hive_parser>(file);
|
||||
}
|
||||
}
|
||||
|
||||
registry_manager::~registry_manager() = default;
|
||||
|
||||
registry_manager::registry_manager(const std::filesystem::path& hive_path)
|
||||
{
|
||||
const std::filesystem::path root = R"(\registry)";
|
||||
const std::filesystem::path machine = root / "machine";
|
||||
|
||||
register_hive(this->hives_, machine / "system", hive_path / "SYSTEM");
|
||||
register_hive(this->hives_, machine / "security", hive_path / "SECURITY");
|
||||
register_hive(this->hives_, machine / "sam", hive_path / "SAM");
|
||||
register_hive(this->hives_, machine / "software", hive_path / "SOFTWARE");
|
||||
register_hive(this->hives_, machine / "system", hive_path / "SYSTEM");
|
||||
register_hive(this->hives_, machine / "hardware", hive_path / "HARDWARE");
|
||||
|
||||
register_hive(this->hives_, root / "user", hive_path / "NTUSER.dat");
|
||||
|
||||
this->add_path_mapping(machine / "system" / "CurrentControlSet", machine / "system" / "ControlSet001");
|
||||
}
|
||||
|
||||
void registry_manager::serialize(utils::buffer_serializer& buffer) const
|
||||
{
|
||||
(void)buffer;
|
||||
}
|
||||
|
||||
void registry_manager::deserialize(utils::buffer_deserializer& buffer)
|
||||
{
|
||||
(void)buffer;
|
||||
}
|
||||
|
||||
std::filesystem::path registry_manager::normalize_path(const std::filesystem::path& path) const
|
||||
{
|
||||
auto canonical_path = canonicalize_path(path);
|
||||
|
||||
for (const auto& mapping : this->path_mapping_)
|
||||
{
|
||||
if (is_subpath(mapping.first, canonical_path))
|
||||
{
|
||||
return mapping.second / canonical_path.lexically_relative(mapping.first);
|
||||
}
|
||||
}
|
||||
|
||||
return canonical_path;
|
||||
}
|
||||
|
||||
void registry_manager::add_path_mapping(const std::filesystem::path& key, const std::filesystem::path& value)
|
||||
{
|
||||
this->path_mapping_[canonicalize_path(key)] = canonicalize_path(value);
|
||||
}
|
||||
|
||||
std::optional<registry_key> registry_manager::get_key(const std::filesystem::path& key)
|
||||
{
|
||||
const auto normal_key = this->normalize_path(key);
|
||||
const auto iterator = this->find_hive(normal_key);
|
||||
if (iterator == this->hives_.end())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
registry_key reg_key{};
|
||||
reg_key.hive = iterator->first;
|
||||
reg_key.path = normal_key.lexically_relative(reg_key.hive);
|
||||
|
||||
if (reg_key.path.empty())
|
||||
{
|
||||
return {std::move(reg_key)};
|
||||
}
|
||||
|
||||
const auto entry = iterator->second->get_subkey(reg_key.path.begin()->string(), reg_key.path.generic_string());
|
||||
if (!entry)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return {std::move(reg_key)};
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (is_subpath(i->first, key))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return this->hives_.end();
|
||||
}
|
||||
48
src/windows-emulator/registry_manager.hpp
Normal file
48
src/windows-emulator/registry_manager.hpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include "std_include.hpp"
|
||||
#include <serialization.hpp>
|
||||
|
||||
class hive_parser;
|
||||
|
||||
struct registry_key
|
||||
{
|
||||
std::filesystem::path hive{};
|
||||
std::filesystem::path path{};
|
||||
|
||||
void serialize(utils::buffer_serializer& buffer) const
|
||||
{
|
||||
buffer.write_string<wchar_t>(this->hive.wstring());
|
||||
buffer.write_string<wchar_t>(this->path.wstring());
|
||||
}
|
||||
|
||||
void deserialize(utils::buffer_deserializer& buffer)
|
||||
{
|
||||
this->hive = buffer.read_string<wchar_t>();
|
||||
this->path = buffer.read_string<wchar_t>();
|
||||
}
|
||||
};
|
||||
|
||||
class registry_manager
|
||||
{
|
||||
public:
|
||||
using hive_ptr = std::unique_ptr<hive_parser>;
|
||||
using hive_map = std::unordered_map<std::filesystem::path, hive_ptr>;
|
||||
|
||||
registry_manager(const std::filesystem::path& hive_path);
|
||||
~registry_manager();
|
||||
|
||||
void serialize(utils::buffer_serializer& buffer) const;
|
||||
void deserialize(utils::buffer_deserializer& buffer);
|
||||
|
||||
std::optional<registry_key> get_key(const std::filesystem::path& key);
|
||||
|
||||
private:
|
||||
hive_map hives_{};
|
||||
std::unordered_map<std::filesystem::path, std::filesystem::path> path_mapping_{};
|
||||
|
||||
std::filesystem::path normalize_path(const std::filesystem::path& path) const;
|
||||
void add_path_mapping(const std::filesystem::path& key, const std::filesystem::path& value);
|
||||
|
||||
hive_map::iterator find_hive(const std::filesystem::path& key);
|
||||
};
|
||||
@@ -53,7 +53,7 @@ namespace
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtOpenKey(const syscall_context& c, const emulator_object<uint64_t> /*key_handle*/,
|
||||
NTSTATUS handle_NtOpenKey(const syscall_context& c, const emulator_object<uint64_t> key_handle,
|
||||
const ACCESS_MASK /*desired_access*/,
|
||||
const emulator_object<OBJECT_ATTRIBUTES> object_attributes)
|
||||
{
|
||||
@@ -62,7 +62,16 @@ namespace
|
||||
|
||||
c.win_emu.logger.print(color::dark_gray, "--> Registry key: %S\n", key.c_str());
|
||||
|
||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
auto entry = c.proc.registry.get_key(key);
|
||||
if (!entry.has_value())
|
||||
{
|
||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
const auto handle = c.proc.registry_keys.store(std::move(entry.value()));
|
||||
key_handle.write(handle.bits);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtOpenKeyEx()
|
||||
|
||||
Reference in New Issue
Block a user