Format all the code

This commit is contained in:
momo5502
2025-01-06 17:13:33 +01:00
parent 64c2a79f0f
commit bff8420ffd
100 changed files with 16439 additions and 14509 deletions

View File

@@ -5,216 +5,216 @@
namespace
{
constexpr uint64_t MAIN_ROOT_OFFSET = 0x1000;
constexpr uint64_t MAIN_KEY_BLOCK_OFFSET = MAIN_ROOT_OFFSET + 0x20;
constexpr uint64_t MAIN_ROOT_OFFSET = 0x1000;
constexpr uint64_t MAIN_KEY_BLOCK_OFFSET = MAIN_ROOT_OFFSET + 0x20;
struct offset_entry_t
{
int32_t offset;
int32_t hash;
};
struct offset_entry_t
{
int32_t offset;
int32_t hash;
};
struct offsets_t
{
int32_t block_size;
char block_type[2];
int16_t count;
offset_entry_t entries[1];
};
struct offsets_t
{
int32_t block_size;
char block_type[2];
int16_t count;
offset_entry_t entries[1];
};
struct key_block_t
{
int32_t block_size;
char block_type[2];
uint8_t dummya[18];
int32_t subkey_count;
uint8_t dummyb[4];
int32_t subkeys;
uint8_t dummyc[4];
int32_t value_count;
int32_t offsets;
uint8_t dummyd[28];
int16_t len;
int16_t du;
char name[255];
};
struct key_block_t
{
int32_t block_size;
char block_type[2];
uint8_t dummya[18];
int32_t subkey_count;
uint8_t dummyb[4];
int32_t subkeys;
uint8_t dummyc[4];
int32_t value_count;
int32_t offsets;
uint8_t dummyd[28];
int16_t len;
int16_t du;
char name[255];
};
struct value_block_t
{
int32_t block_size;
char block_type[2];
int16_t name_len;
int32_t size;
int32_t offset;
int32_t value_type;
int16_t flags;
int16_t dummy;
char name[255];
};
struct value_block_t
{
int32_t block_size;
char block_type[2];
int16_t name_len;
int32_t size;
int32_t offset;
int32_t value_type;
int16_t flags;
int16_t dummy;
char name[255];
};
bool read_file_data_safe(std::ifstream& file, const uint64_t offset, void* buffer, const size_t size)
{
if (file.bad())
{
return false;
}
bool read_file_data_safe(std::ifstream& file, const uint64_t offset, void* buffer, const size_t size)
{
if (file.bad())
{
return false;
}
file.clear();
file.clear();
if (!file.good())
{
return false;
}
if (!file.good())
{
return false;
}
file.seekg(static_cast<std::streamoff>(offset));
file.seekg(static_cast<std::streamoff>(offset));
if (!file.good())
{
return false;
}
if (!file.good())
{
return false;
}
file.read(static_cast<char*>(buffer), static_cast<std::streamsize>(size));
file.read(static_cast<char*>(buffer), static_cast<std::streamsize>(size));
return file.good();
}
return file.good();
}
void read_file_data(std::ifstream& file, const uint64_t offset, void* buffer, const size_t size)
{
if (!read_file_data_safe(file, offset, buffer, size))
{
throw std::runtime_error("Failed to read file data");
}
}
void read_file_data(std::ifstream& file, const uint64_t offset, void* buffer, const size_t size)
{
if (!read_file_data_safe(file, offset, buffer, size))
{
throw std::runtime_error("Failed to read file data");
}
}
std::vector<std::byte> read_file_data(std::ifstream& file, const uint64_t offset, const size_t size)
{
std::vector<std::byte> result{};
result.resize(size);
std::vector<std::byte> read_file_data(std::ifstream& file, const uint64_t offset, const size_t size)
{
std::vector<std::byte> result{};
result.resize(size);
read_file_data(file, offset, result.data(), size);
return result;
}
read_file_data(file, offset, result.data(), size);
return result;
}
std::string read_file_data_string(std::ifstream& file, const uint64_t offset, const size_t size)
{
std::string result{};
result.resize(size);
std::string read_file_data_string(std::ifstream& file, const uint64_t offset, const size_t size)
{
std::string result{};
result.resize(size);
read_file_data(file, offset, result.data(), size);
return result;
}
read_file_data(file, offset, result.data(), size);
return result;
}
template <typename T>
requires(std::is_trivially_copyable_v<T>)
T read_file_object(std::ifstream& file, const uint64_t offset, const size_t array_index = 0)
{
T obj{};
read_file_data(file, offset + (array_index * sizeof(T)), &obj, sizeof(T));
return obj;
}
template <typename T>
requires(std::is_trivially_copyable_v<T>)
T read_file_object(std::ifstream& file, const uint64_t offset, const size_t array_index = 0)
{
T obj{};
read_file_data(file, offset + (array_index * sizeof(T)), &obj, sizeof(T));
return obj;
}
hive_key parse_root_block(std::ifstream& file, const std::filesystem::path& file_path)
{
try
{
if (read_file_data_string(file, 0, 4) != "regf")
{
throw std::runtime_error("Invalid signature");
}
hive_key parse_root_block(std::ifstream& file, const std::filesystem::path& file_path)
{
try
{
if (read_file_data_string(file, 0, 4) != "regf")
{
throw std::runtime_error("Invalid signature");
}
const auto key_block = read_file_object<key_block_t>(file, MAIN_KEY_BLOCK_OFFSET);
const auto key_block = read_file_object<key_block_t>(file, MAIN_KEY_BLOCK_OFFSET);
return {key_block.subkeys, key_block.value_count, key_block.offsets};
}
catch (const std::exception& e)
{
throw std::runtime_error("Bad hive file '" + file_path.string() + "': " + e.what());
}
}
return {key_block.subkeys, key_block.value_count, key_block.offsets};
}
catch (const std::exception& e)
{
throw std::runtime_error("Bad hive file '" + file_path.string() + "': " + e.what());
}
}
}
const hive_value* hive_key::get_value(std::ifstream& file, const std::string_view name)
{
this->parse(file);
this->parse(file);
const auto entry = this->values_.find(name);
if (entry == this->values_.end())
{
return nullptr;
}
const auto entry = this->values_.find(name);
if (entry == this->values_.end())
{
return nullptr;
}
auto& value = entry->second;
auto& value = entry->second;
if (!value.parsed)
{
value.data = read_file_data(file, MAIN_ROOT_OFFSET + value.data_offset, value.data_length);
value.parsed = true;
}
if (!value.parsed)
{
value.data = read_file_data(file, MAIN_ROOT_OFFSET + value.data_offset, value.data_length);
value.parsed = true;
}
return &value;
return &value;
}
void hive_key::parse(std::ifstream& file)
{
if (this->parsed_)
{
return;
}
if (this->parsed_)
{
return;
}
this->parsed_ = true;
this->parsed_ = true;
// Values
// Values
for (auto i = 0; i < this->value_count_; i++)
{
const auto offset = read_file_object<int>(file, MAIN_ROOT_OFFSET + this->value_offsets_ + 4, i);
const auto value = read_file_object<value_block_t>(file, MAIN_ROOT_OFFSET + offset);
for (auto i = 0; i < this->value_count_; i++)
{
const auto offset = read_file_object<int>(file, MAIN_ROOT_OFFSET + this->value_offsets_ + 4, i);
const auto value = read_file_object<value_block_t>(file, MAIN_ROOT_OFFSET + offset);
std::string value_name(value.name, std::min(value.name_len, static_cast<short>(sizeof(value.name))));
std::string value_name(value.name, std::min(value.name_len, static_cast<short>(sizeof(value.name))));
raw_hive_value raw_value{};
raw_value.parsed = false;
raw_value.type = value.value_type;
raw_value.name = value_name;
raw_value.data_length = value.size & 0xffff;
raw_value.data_offset = value.offset + 4;
raw_hive_value raw_value{};
raw_value.parsed = false;
raw_value.type = value.value_type;
raw_value.name = value_name;
raw_value.data_length = value.size & 0xffff;
raw_value.data_offset = value.offset + 4;
if (value.size & 1 << 31)
{
raw_value.data_offset = offset + static_cast<int>(offsetof(value_block_t, offset));
}
if (value.size & 1 << 31)
{
raw_value.data_offset = offset + static_cast<int>(offsetof(value_block_t, offset));
}
utils::string::to_lower_inplace(value_name);
this->values_[std::move(value_name)] = std::move(raw_value);
}
utils::string::to_lower_inplace(value_name);
this->values_[std::move(value_name)] = std::move(raw_value);
}
// Subkeys
// Subkeys
const auto item = read_file_object<offsets_t>(file, MAIN_ROOT_OFFSET + this->subkey_block_offset_);
const auto item = read_file_object<offsets_t>(file, MAIN_ROOT_OFFSET + this->subkey_block_offset_);
if (item.block_type[1] != 'f' && item.block_type[1] != 'h')
{
return;
}
if (item.block_type[1] != 'f' && item.block_type[1] != 'h')
{
return;
}
const auto entry_offsets = this->subkey_block_offset_ + offsetof(offsets_t, entries);
const auto entry_offsets = this->subkey_block_offset_ + offsetof(offsets_t, entries);
for (short i = 0; i < item.count; ++i)
{
const auto offset_entry = read_file_object<offset_entry_t>(file, MAIN_ROOT_OFFSET + entry_offsets, i);
for (short i = 0; i < item.count; ++i)
{
const auto offset_entry = read_file_object<offset_entry_t>(file, MAIN_ROOT_OFFSET + entry_offsets, i);
const auto subkey_block_offset = MAIN_ROOT_OFFSET + offset_entry.offset;
const auto subkey = read_file_object<key_block_t>(file, subkey_block_offset);
const auto subkey_block_offset = MAIN_ROOT_OFFSET + offset_entry.offset;
const auto subkey = read_file_object<key_block_t>(file, subkey_block_offset);
std::string subkey_name(subkey.name, std::min(subkey.len, static_cast<int16_t>(sizeof(subkey.name))));
utils::string::to_lower_inplace(subkey_name);
std::string subkey_name(subkey.name, std::min(subkey.len, static_cast<int16_t>(sizeof(subkey.name))));
utils::string::to_lower_inplace(subkey_name);
this->sub_keys_.emplace(std::move(subkey_name), hive_key{subkey.subkeys, subkey.value_count, subkey.offsets});
}
this->sub_keys_.emplace(std::move(subkey_name), hive_key{subkey.subkeys, subkey.value_count, subkey.offsets});
}
}
hive_parser::hive_parser(const std::filesystem::path& file_path)
: file_(file_path, std::ios::binary)
, root_key_(parse_root_block(file_, file_path))
: file_(file_path, std::ios::binary),
root_key_(parse_root_block(file_, file_path))
{
}

View File

@@ -8,95 +8,95 @@
struct hive_value
{
uint32_t type{};
std::string name{};
std::vector<std::byte> data{};
uint32_t type{};
std::string name{};
std::vector<std::byte> data{};
};
class hive_key
{
public:
hive_key(const int subkey_block_offset, const int value_count, const int value_offsets)
: subkey_block_offset_(subkey_block_offset)
, value_count_(value_count)
, value_offsets_(value_offsets)
{
}
public:
hive_key(const int subkey_block_offset, const int value_count, const int value_offsets)
: subkey_block_offset_(subkey_block_offset),
value_count_(value_count),
value_offsets_(value_offsets)
{
}
utils::unordered_string_map<hive_key>& get_sub_keys(std::ifstream& file)
{
this->parse(file);
return this->sub_keys_;
}
utils::unordered_string_map<hive_key>& get_sub_keys(std::ifstream& file)
{
this->parse(file);
return this->sub_keys_;
}
hive_key* get_sub_key(std::ifstream& file, const std::string_view name)
{
auto& sub_keys = this->get_sub_keys(file);
const auto entry = sub_keys.find(name);
hive_key* get_sub_key(std::ifstream& file, const std::string_view name)
{
auto& sub_keys = this->get_sub_keys(file);
const auto entry = sub_keys.find(name);
if (entry == sub_keys.end())
{
return nullptr;
}
if (entry == sub_keys.end())
{
return nullptr;
}
return &entry->second;
}
return &entry->second;
}
const hive_value* get_value(std::ifstream& file, const std::string_view name);
const hive_value* get_value(std::ifstream& file, const std::string_view name);
private:
struct raw_hive_value : hive_value
{
bool parsed{false};
int data_offset{};
size_t data_length{};
};
private:
struct raw_hive_value : hive_value
{
bool parsed{false};
int data_offset{};
size_t data_length{};
};
bool parsed_{false};
utils::unordered_string_map<hive_key> sub_keys_{};
utils::unordered_string_map<raw_hive_value> values_{};
bool parsed_{false};
utils::unordered_string_map<hive_key> sub_keys_{};
utils::unordered_string_map<raw_hive_value> values_{};
const int subkey_block_offset_{};
const int value_count_{};
const int value_offsets_{};
const int subkey_block_offset_{};
const int value_count_{};
const int value_offsets_{};
void parse(std::ifstream& file);
void parse(std::ifstream& file);
};
class hive_parser
{
public:
explicit hive_parser(const std::filesystem::path& file_path);
public:
explicit hive_parser(const std::filesystem::path& file_path);
[[nodiscard]] hive_key* get_sub_key(const std::filesystem::path& key)
{
hive_key* current_key = &this->root_key_;
[[nodiscard]] hive_key* get_sub_key(const std::filesystem::path& key)
{
hive_key* current_key = &this->root_key_;
for (const auto& key_part : key)
{
if (!current_key)
{
return nullptr;
}
for (const auto& key_part : key)
{
if (!current_key)
{
return nullptr;
}
current_key = current_key->get_sub_key(this->file_, key_part.string());
}
current_key = current_key->get_sub_key(this->file_, key_part.string());
}
return current_key;
}
return current_key;
}
[[nodiscard]] const hive_value* get_value(const std::filesystem::path& key, const std::string_view name)
{
auto* sub_key = this->get_sub_key(key);
if (!sub_key)
{
return nullptr;
}
[[nodiscard]] const hive_value* get_value(const std::filesystem::path& key, const std::string_view name)
{
auto* sub_key = this->get_sub_key(key);
if (!sub_key)
{
return nullptr;
}
return sub_key->get_value(this->file_, name);
}
return sub_key->get_value(this->file_, name);
}
private:
std::ifstream file_{};
hive_key root_key_;
private:
std::ifstream file_{};
hive_key root_key_;
};

View File

@@ -7,33 +7,33 @@
namespace
{
std::filesystem::path canonicalize_path(const std::filesystem::path& key)
{
auto path = key.lexically_normal().wstring();
return utils::string::to_lower_consume(path);
}
std::filesystem::path canonicalize_path(const std::filesystem::path& key)
{
auto path = key.lexically_normal().wstring();
return utils::string::to_lower_consume(path);
}
bool is_subpath(const std::filesystem::path& root, const std::filesystem::path& p)
{
auto root_it = root.begin();
auto p_it = p.begin();
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;
}
}
for (; root_it != root.end(); ++root_it, ++p_it)
{
if (p_it == p.end() || *root_it != *p_it)
{
return false;
}
}
return true;
}
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);
}
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;
@@ -42,130 +42,130 @@ registry_manager::registry_manager(registry_manager&&) noexcept = default;
registry_manager& registry_manager::operator=(registry_manager&&) noexcept = default;
registry_manager::registry_manager(const std::filesystem::path& hive_path)
: hive_path_(absolute(hive_path))
: hive_path_(absolute(hive_path))
{
this->setup();
this->setup();
}
void registry_manager::setup()
{
this->path_mapping_.clear();
this->hives_.clear();
this->path_mapping_.clear();
this->hives_.clear();
const std::filesystem::path root = R"(\registry)";
const std::filesystem::path machine = root / "machine";
const std::filesystem::path root = R"(\registry)";
const std::filesystem::path machine = root / "machine";
register_hive(this->hives_, machine / "system", this->hive_path_ / "SYSTEM");
register_hive(this->hives_, machine / "security", this->hive_path_ / "SECURITY");
register_hive(this->hives_, machine / "sam", this->hive_path_ / "SAM");
register_hive(this->hives_, machine / "software", this->hive_path_ / "SOFTWARE");
register_hive(this->hives_, machine / "system", this->hive_path_ / "SYSTEM");
register_hive(this->hives_, machine / "hardware", this->hive_path_ / "HARDWARE");
register_hive(this->hives_, machine / "system", this->hive_path_ / "SYSTEM");
register_hive(this->hives_, machine / "security", this->hive_path_ / "SECURITY");
register_hive(this->hives_, machine / "sam", this->hive_path_ / "SAM");
register_hive(this->hives_, machine / "software", this->hive_path_ / "SOFTWARE");
register_hive(this->hives_, machine / "system", this->hive_path_ / "SYSTEM");
register_hive(this->hives_, machine / "hardware", this->hive_path_ / "HARDWARE");
register_hive(this->hives_, root / "user", this->hive_path_ / "NTUSER.dat");
register_hive(this->hives_, root / "user", this->hive_path_ / "NTUSER.dat");
this->add_path_mapping(machine / "system" / "CurrentControlSet", machine / "system" / "ControlSet001");
this->add_path_mapping(machine / "system" / "CurrentControlSet", machine / "system" / "ControlSet001");
}
void registry_manager::serialize(utils::buffer_serializer& buffer) const
{
buffer.write(this->hive_path_);
buffer.write(this->hive_path_);
}
void registry_manager::deserialize(utils::buffer_deserializer& buffer)
{
buffer.read(this->hive_path_);
this->setup();
buffer.read(this->hive_path_);
this->setup();
}
std::filesystem::path registry_manager::normalize_path(const std::filesystem::path& path) const
{
auto canonical_path = canonicalize_path(path);
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);
}
}
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;
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);
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 normal_key = this->normalize_path(key);
if (is_subpath(normal_key, "\\registry\\machine"))
{
registry_key reg_key{};
reg_key.hive = normal_key;
return {std::move(reg_key)};
}
if (is_subpath(normal_key, "\\registry\\machine"))
{
registry_key reg_key{};
reg_key.hive = normal_key;
return {std::move(reg_key)};
}
const auto iterator = this->find_hive(normal_key);
if (iterator == this->hives_.end())
{
return {};
}
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);
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)};
}
if (reg_key.path.empty())
{
return {std::move(reg_key)};
}
const auto entry = iterator->second->get_sub_key(reg_key.path);
if (!entry)
{
return std::nullopt;
}
const auto entry = iterator->second->get_sub_key(reg_key.path);
if (!entry)
{
return std::nullopt;
}
return {std::move(reg_key)};
return {std::move(reg_key)};
}
std::optional<registry_value> registry_manager::get_value(const registry_key& key, std::string name)
{
utils::string::to_lower_inplace(name);
utils::string::to_lower_inplace(name);
const auto iterator = this->hives_.find(key.hive);
if (iterator == this->hives_.end())
{
return std::nullopt;
}
const auto iterator = this->hives_.find(key.hive);
if (iterator == this->hives_.end())
{
return std::nullopt;
}
auto* entry = iterator->second->get_value(key.path, name);
if (!entry)
{
return std::nullopt;
}
auto* entry = iterator->second->get_value(key.path, name);
if (!entry)
{
return std::nullopt;
}
registry_value v{};
v.type = entry->type;
v.name = entry->name;
v.data = entry->data;
registry_value v{};
v.type = entry->type;
v.name = entry->name;
v.data = entry->data;
return v;
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)
{
if (is_subpath(i->first, key))
{
return i;
}
}
for (auto i = this->hives_.begin(); i != this->hives_.end(); ++i)
{
if (is_subpath(i->first, key))
{
return i;
}
}
return this->hives_.end();
return this->hives_.end();
}

View File

@@ -6,61 +6,60 @@
struct registry_key
{
std::filesystem::path hive{};
std::filesystem::path path{};
std::filesystem::path hive{};
std::filesystem::path path{};
void serialize(utils::buffer_serializer& buffer) const
{
buffer.write(this->hive);
buffer.write(this->path);
}
void serialize(utils::buffer_serializer& buffer) const
{
buffer.write(this->hive);
buffer.write(this->path);
}
void deserialize(utils::buffer_deserializer& buffer)
{
buffer.read(this->hive);
buffer.read(this->path);
}
void deserialize(utils::buffer_deserializer& buffer)
{
buffer.read(this->hive);
buffer.read(this->path);
}
};
struct registry_value
{
uint32_t type;
std::string_view name;
std::span<const std::byte> data;
uint32_t type;
std::string_view name;
std::span<const std::byte> data;
};
class registry_manager
{
public:
using hive_ptr = std::unique_ptr<hive_parser>;
using hive_map = std::unordered_map<std::filesystem::path, hive_ptr>;
public:
using hive_ptr = std::unique_ptr<hive_parser>;
using hive_map = std::unordered_map<std::filesystem::path, hive_ptr>;
registry_manager();
registry_manager(const std::filesystem::path& hive_path);
~registry_manager();
registry_manager();
registry_manager(const std::filesystem::path& hive_path);
~registry_manager();
registry_manager(registry_manager&&) noexcept;
registry_manager& operator=(registry_manager&&) noexcept;
registry_manager(registry_manager&&) noexcept;
registry_manager& operator=(registry_manager&&) noexcept;
registry_manager(const registry_manager&) = delete;
registry_manager& operator=(const registry_manager&) = delete;
registry_manager(const registry_manager&) = delete;
registry_manager& operator=(const registry_manager&) = delete;
void serialize(utils::buffer_serializer& buffer) const;
void deserialize(utils::buffer_deserializer& buffer);
void serialize(utils::buffer_serializer& buffer) const;
void deserialize(utils::buffer_deserializer& buffer);
std::optional<registry_key> get_key(const std::filesystem::path& key);
std::optional<registry_value> get_value(const registry_key& key, std::string name);
std::optional<registry_key> get_key(const std::filesystem::path& key);
std::optional<registry_value> get_value(const registry_key& key, std::string name);
private:
std::filesystem::path hive_path_{};
hive_map hives_{};
std::unordered_map<std::filesystem::path, std::filesystem::path> path_mapping_{};
private:
std::filesystem::path hive_path_{};
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);
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);
hive_map::iterator find_hive(const std::filesystem::path& key);
void setup();
void setup();
};