Prepare registry support

This commit is contained in:
momo5502
2024-11-02 16:07:27 +01:00
parent e0dc1934eb
commit 92b9712e45
6 changed files with 192 additions and 3 deletions

View File

@@ -13,6 +13,7 @@ struct handle_types
semaphore,
port,
thread,
registry,
};
};

View File

@@ -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);

View 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();
}

View 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);
};

View File

@@ -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()