Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add registry support #24

Merged
merged 19 commits into from
Nov 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,8 @@ jobs:
path: |
build/${{matrix.preset}}/artifacts/*

- name: Dump Registry
run: cd build/${{matrix.preset}}/artifacts && ../../../src/grab-registry.bat

- name: CMake Test
run: cd build/${{matrix.preset}} && ctest --verbose
2 changes: 1 addition & 1 deletion deps/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ target_include_directories(reflect INTERFACE
##########################################

include(mini-gdbstub.cmake)
include(googletest.cmake)
include(googletest.cmake)
25 changes: 25 additions & 0 deletions src/common/utils/container.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include <string>
#include <string_view>
#include <unordered_set>
#include <unordered_map>

namespace utils
{
struct string_hash
{
using is_transparent = void;

size_t operator()(const std::string_view str) const
{
constexpr std::hash<std::string_view> hasher{};
return hasher(str);
}
};

template <typename T>
using unordered_string_map = std::unordered_map<std::string, T, string_hash, std::equal_to<>>;

using unordered_string_set = std::unordered_set<std::string, string_hash, std::equal_to<>>;
}
14 changes: 8 additions & 6 deletions src/emulator/serialization.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ namespace utils
};

template <typename T>
struct has_serialize_function<T, std::void_t<decltype(serialize(std::declval<buffer_serializer&>(),
std::declval<const T&>()))>>
struct has_serialize_function<T, std::void_t<decltype(::serialize(std::declval<buffer_serializer&>(),
std::declval<const std::remove_cvref_t<T>&>())
)>>
: std::true_type
{
};
Expand All @@ -50,8 +51,9 @@ namespace utils
};

template <typename T>
struct has_deserialize_function<T, std::void_t<decltype(deserialize(
std::declval<buffer_deserializer&>(), std::declval<T&>()))>>
struct has_deserialize_function<T, std::void_t<decltype(::deserialize(
std::declval<buffer_deserializer&>(),
std::declval<std::remove_cvref_t<T>&>()))>>
: std::true_type
{
};
Expand Down Expand Up @@ -122,7 +124,7 @@ namespace utils
}
else if constexpr (detail::has_deserialize_function<T>::value)
{
deserialize(*this, object);
::deserialize(*this, object);
}
else if constexpr (std::is_trivially_copyable_v<T>)
{
Expand Down Expand Up @@ -338,7 +340,7 @@ namespace utils
}
else if constexpr (detail::has_serialize_function<T>::value)
{
serialize(*this, object);
::serialize(*this, object);
}
else if constexpr (std::is_trivially_copyable_v<T>)
{
Expand Down
30 changes: 30 additions & 0 deletions src/emulator/serialization_helper.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma once

#include "serialization.hpp"

#include <chrono>
#include <filesystem>

inline void serialize(utils::buffer_serializer& buffer, const std::chrono::steady_clock::time_point& tp)
{
buffer.write(tp.time_since_epoch().count());
}

inline void deserialize(utils::buffer_deserializer& buffer, std::chrono::steady_clock::time_point& tp)
{
using time_point = std::chrono::steady_clock::time_point;
using duration = time_point::duration;

const auto count = buffer.read<duration::rep>();
tp = time_point{duration{count}};
}

inline void serialize(utils::buffer_serializer& buffer, const std::filesystem::path& path)
{
buffer.write_string<wchar_t>(path.wstring());
}

inline void deserialize(utils::buffer_deserializer& buffer, std::filesystem::path& path)
{
path = buffer.read_string<wchar_t>();
}
17 changes: 17 additions & 0 deletions src/grab-registry.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
@echo off

NET SESSIONS > NUL 2>&1
IF %ERRORLEVEL% NEQ 0 (
ECHO Error: This script requires administrative privileges.
EXIT /B 1
)

SET REGDIR="registry"
MKDIR %REGDIR%

REG SAVE HKLM\SYSTEM %REGDIR%\SYSTEM /Y
REG SAVE HKLM\SECURITY %REGDIR%\SECURITY /Y
REG SAVE HKLM\SOFTWARE %REGDIR%\SOFTWARE /Y
REG SAVE HKLM\HARDWARE %REGDIR%\HARDWARE /Y
REG SAVE HKLM\SAM %REGDIR%\SAM /Y
COPY /B /Y C:\Users\Default\NTUSER.DAT "%REGDIR%\NTUSER.DAT"
1 change: 1 addition & 0 deletions src/windows-emulator/handles.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ struct handle_types
semaphore,
port,
thread,
registry,
};
};

Expand Down
23 changes: 9 additions & 14 deletions src/windows-emulator/process_context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

#include "emulator_utils.hpp"
#include "handles.hpp"
#include "registry/registry_manager.hpp"

#include "module/module_manager.hpp"
#include <utils/nt_handle.hpp>
#include <utils/file_handle.hpp>

#include <x64_emulator.hpp>
#include <serialization_helper.hpp>


#define PEB_SEGMENT_SIZE (20 << 20) // 20 MB
Expand All @@ -23,20 +25,6 @@
#define GDT_LIMIT 0x1000
#define GDT_ENTRY_SIZE 0x8

inline void serialize(utils::buffer_serializer& buffer, const std::chrono::steady_clock::time_point& tp)
{
buffer.write(tp.time_since_epoch().count());
}

inline void deserialize(utils::buffer_deserializer& buffer, std::chrono::steady_clock::time_point& tp)
{
using time_point = std::chrono::steady_clock::time_point;
using duration = time_point::duration;

const auto count = buffer.read<duration::rep>();
tp = time_point{duration{count}};
}

struct ref_counted_object
{
uint32_t ref_count{1};
Expand Down Expand Up @@ -375,6 +363,8 @@ struct process_context
{
}

registry_manager registry{};

uint64_t executed_instructions{0};
uint64_t current_ip{0};
uint64_t previous_ip{0};
Expand Down Expand Up @@ -404,6 +394,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{};
Expand All @@ -414,6 +405,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);
Expand All @@ -438,6 +430,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);
Expand All @@ -449,6 +442,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);
Expand Down Expand Up @@ -477,6 +471,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);
Expand Down
Loading