mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-18 11:13:57 +00:00
Extract Windows version management into separate module
This commit is contained in:
@@ -2003,7 +2003,7 @@ typedef enum class _SECTION_INFORMATION_CLASS
|
||||
SectionInternalImageInformation = 4
|
||||
} SECTION_INFORMATION_CLASS, *PSECTION_INFORMATION_CLASS;
|
||||
|
||||
enum WINDOWS_VERSION : uint32_t
|
||||
typedef enum _WINDOWS_VERSION : uint32_t
|
||||
{
|
||||
WINDOWS_10_1507 = 10240,
|
||||
WINDOWS_10_1511 = 10586,
|
||||
@@ -2023,7 +2023,7 @@ enum WINDOWS_VERSION : uint32_t
|
||||
WINDOWS_11_22H2 = 22621,
|
||||
WINDOWS_11_23H2 = 22631,
|
||||
WINDOWS_11_24H2 = 26100,
|
||||
};
|
||||
} WINDOWS_VERSION, *PWINDOWS_VERSION;
|
||||
|
||||
constexpr uint64_t PS_SYSTEM_DLL_INIT_BLOCK_SIZE_V1 = sizeof(PS_SYSTEM_DLL_INIT_BLOCK_V1);
|
||||
constexpr uint64_t PS_SYSTEM_DLL_INIT_BLOCK_SIZE_V2_1703 = offsetof(PS_SYSTEM_DLL_INIT_BLOCK_V2, MitigationAuditOptionsMap);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "kusd_mmio.hpp"
|
||||
#include <utils/time.hpp>
|
||||
#include "windows_emulator.hpp"
|
||||
#include "version/windows_version_manager.hpp"
|
||||
|
||||
#include <address_utils.hpp>
|
||||
|
||||
@@ -11,7 +12,7 @@ constexpr auto KUSD_BUFFER_SIZE = page_align_up(KUSD_SIZE);
|
||||
|
||||
namespace
|
||||
{
|
||||
void setup_kusd(KUSER_SHARED_DATA64& kusd)
|
||||
void setup_kusd(KUSER_SHARED_DATA64& kusd, const windows_version_manager& version)
|
||||
{
|
||||
memset(reinterpret_cast<void*>(&kusd), 0, sizeof(kusd));
|
||||
|
||||
@@ -29,11 +30,12 @@ namespace
|
||||
kusd.LargePageMinimum = 0x00200000;
|
||||
kusd.RNGSeedVersion = 0;
|
||||
kusd.TimeZoneBiasStamp = 0x00000004;
|
||||
kusd.NtBuildNumber = 19045;
|
||||
kusd.NtBuildNumber = version.get_windows_build_number();
|
||||
kusd.NtProductType = NtProductWinNt;
|
||||
kusd.ProductTypeIsValid = 0x01;
|
||||
kusd.NativeProcessorArchitecture = 0x0009;
|
||||
kusd.NtMajorVersion = 0x0000000a;
|
||||
kusd.NtMajorVersion = version.get_major_version();
|
||||
kusd.NtMinorVersion = version.get_minor_version();
|
||||
kusd.BootId = 0;
|
||||
kusd.SystemExpirationDate.QuadPart = 0;
|
||||
kusd.SuiteMask = 0;
|
||||
@@ -80,8 +82,10 @@ namespace
|
||||
kusd.ProcessorFeatures.arr[PF_RDTSCP_INSTRUCTION_AVAILABLE] = 1;
|
||||
kusd.ProcessorFeatures.arr[PF_RDPID_INSTRUCTION_AVAILABLE] = 0;
|
||||
|
||||
constexpr std::u16string_view root_dir{u"C:\\Windows"};
|
||||
memcpy(&kusd.NtSystemRoot.arr[0], root_dir.data(), root_dir.size() * 2);
|
||||
const auto& system_root = version.get_system_root();
|
||||
const auto& root_str = system_root.u16string();
|
||||
const auto copy_size = std::min(root_str.size() * sizeof(char16_t), sizeof(kusd.NtSystemRoot.arr) - sizeof(char16_t));
|
||||
memcpy(&kusd.NtSystemRoot.arr[0], root_str.data(), copy_size);
|
||||
|
||||
kusd.ImageNumberLow = IMAGE_FILE_MACHINE_AMD64;
|
||||
kusd.ImageNumberHigh = IMAGE_FILE_MACHINE_AMD64;
|
||||
@@ -118,9 +122,9 @@ kusd_mmio::kusd_mmio(utils::buffer_deserializer& buffer)
|
||||
{
|
||||
}
|
||||
|
||||
void kusd_mmio::setup()
|
||||
void kusd_mmio::setup(const windows_version_manager& version)
|
||||
{
|
||||
setup_kusd(this->kusd_);
|
||||
setup_kusd(this->kusd_, version);
|
||||
this->register_mmio();
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
struct process_context;
|
||||
class windows_emulator;
|
||||
class windows_version_manager;
|
||||
|
||||
class kusd_mmio
|
||||
{
|
||||
@@ -38,7 +39,7 @@ class kusd_mmio
|
||||
|
||||
static uint64_t address();
|
||||
|
||||
void setup();
|
||||
void setup(const windows_version_manager& version);
|
||||
|
||||
private:
|
||||
memory_manager* memory_{};
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "platform/win_pefile.hpp"
|
||||
#include "windows-emulator/logger.hpp"
|
||||
#include "../wow64_heaven_gate.hpp"
|
||||
#include "../registry/registry_manager.hpp"
|
||||
#include "../version/windows_version_manager.hpp"
|
||||
#include "../process_context.hpp"
|
||||
|
||||
#include <serialization_helper.hpp>
|
||||
@@ -207,52 +207,6 @@ module_manager::module_manager(memory_manager& memory, file_system& file_sys, ca
|
||||
{
|
||||
}
|
||||
|
||||
void module_manager::get_system_information_from_registry(registry_manager& registry, system_information& info, const logger& logger)
|
||||
{
|
||||
constexpr auto version_key_path = R"(\Registry\Machine\Software\Microsoft\Windows NT\CurrentVersion)";
|
||||
|
||||
const auto version_key = registry.get_key({version_key_path});
|
||||
if (!version_key)
|
||||
{
|
||||
throw std::runtime_error("Failed to get CurrentVersion registry key");
|
||||
}
|
||||
|
||||
for (size_t i = 0; const auto value = registry.get_value(*version_key, i); ++i)
|
||||
{
|
||||
if (value->name == "SystemRoot" && value->type == REG_SZ && !value->data.empty())
|
||||
{
|
||||
const auto* data_ptr = reinterpret_cast<const char16_t*>(value->data.data());
|
||||
const auto char_count = value->data.size() / sizeof(char16_t);
|
||||
std::u16string system_root(data_ptr, char_count > 0 && data_ptr[char_count - 1] == u'\0' ? char_count - 1 : char_count);
|
||||
info.system_root = windows_path{system_root};
|
||||
}
|
||||
else if ((value->name == "CurrentBuildNumber" || value->name == "CurrentBuild") && value->type == REG_SZ)
|
||||
{
|
||||
const auto* s = reinterpret_cast<const char16_t*>(value->data.data());
|
||||
info.build_number = static_cast<uint32_t>(std::strtoul(u16_to_u8(s).c_str(), nullptr, 10));
|
||||
}
|
||||
else if (value->name == "UBR" && value->type == REG_DWORD && value->data.size() >= sizeof(uint32_t))
|
||||
{
|
||||
info.update_build_revision = *reinterpret_cast<const uint32_t*>(value->data.data());
|
||||
}
|
||||
}
|
||||
|
||||
if (info.system_root.u16string().empty())
|
||||
{
|
||||
throw std::runtime_error("SystemRoot not found in registry");
|
||||
}
|
||||
|
||||
if (info.build_number == 0)
|
||||
{
|
||||
logger.error("Failed to get CurrentBuildNumber from registry\n");
|
||||
}
|
||||
|
||||
if (info.update_build_revision == 0)
|
||||
{
|
||||
logger.error("Failed to get UBR from registry\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Core mapping logic to eliminate code duplication
|
||||
mapped_module* module_manager::map_module_core(const pe_detection_result& detection_result, const std::function<mapped_module()>& mapper,
|
||||
const logger& logger, bool is_static)
|
||||
@@ -307,7 +261,7 @@ void module_manager::load_native_64bit_modules(const windows_path& executable_pa
|
||||
|
||||
// WOW64 module loading
|
||||
void module_manager::load_wow64_modules(const windows_path& executable_path, const windows_path& ntdll_path,
|
||||
const windows_path& win32u_path, const windows_path& ntdll32_path, process_context& context,
|
||||
const windows_path& win32u_path, const windows_path& ntdll32_path, windows_version_manager& version,
|
||||
const logger& logger)
|
||||
{
|
||||
logger.info("Loading WOW64 modules for 32-bit application\n");
|
||||
@@ -328,7 +282,7 @@ void module_manager::load_wow64_modules(const windows_path& executable_path, con
|
||||
}
|
||||
|
||||
PS_SYSTEM_DLL_INIT_BLOCK init_block = {};
|
||||
const auto init_block_size = context.get_system_dll_init_block_size();
|
||||
const auto init_block_size = version.get_system_dll_init_block_size();
|
||||
|
||||
init_block.Size = static_cast<ULONG>(init_block_size);
|
||||
|
||||
@@ -463,16 +417,12 @@ void module_manager::install_wow64_heaven_gate(const logger& logger)
|
||||
}
|
||||
}
|
||||
|
||||
void module_manager::map_main_modules(const windows_path& executable_path, registry_manager& registry, process_context& context,
|
||||
void module_manager::map_main_modules(const windows_path& executable_path, windows_version_manager& version, process_context& context,
|
||||
const logger& logger)
|
||||
{
|
||||
system_information sys_info{};
|
||||
module_manager::get_system_information_from_registry(registry, sys_info, logger);
|
||||
const auto system32_path = sys_info.system_root / "System32";
|
||||
const auto syswow64_path = sys_info.system_root / "SysWOW64";
|
||||
|
||||
context.windows_build_number = sys_info.build_number;
|
||||
context.windows_update_build_revision_number = sys_info.update_build_revision;
|
||||
const auto& system_root = version.get_system_root();
|
||||
const auto system32_path = system_root / "System32";
|
||||
const auto syswow64_path = system_root / "SysWOW64";
|
||||
|
||||
current_execution_mode_ = detect_execution_mode(executable_path, logger);
|
||||
context.is_wow64_process = (current_execution_mode_ == execution_mode::wow64_32bit);
|
||||
@@ -484,7 +434,7 @@ void module_manager::map_main_modules(const windows_path& executable_path, regis
|
||||
break;
|
||||
|
||||
case execution_mode::wow64_32bit:
|
||||
load_wow64_modules(executable_path, system32_path / "ntdll.dll", system32_path / "win32u.dll", syswow64_path / "ntdll.dll", context,
|
||||
load_wow64_modules(executable_path, system32_path / "ntdll.dll", system32_path / "win32u.dll", syswow64_path / "ntdll.dll", version,
|
||||
logger);
|
||||
break;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
class logger;
|
||||
class registry_manager;
|
||||
class windows_version_manager;
|
||||
struct process_context;
|
||||
|
||||
// Execution mode for the emulated process
|
||||
@@ -80,13 +81,6 @@ class pe_architecture_detector
|
||||
static execution_mode determine_execution_mode(winpe::pe_arch executable_arch);
|
||||
};
|
||||
|
||||
struct system_information
|
||||
{
|
||||
windows_path system_root{};
|
||||
uint32_t build_number{0};
|
||||
uint32_t update_build_revision{0};
|
||||
};
|
||||
|
||||
class module_manager
|
||||
{
|
||||
public:
|
||||
@@ -100,7 +94,8 @@ class module_manager
|
||||
|
||||
module_manager(memory_manager& memory, file_system& file_sys, callbacks& cb);
|
||||
|
||||
void map_main_modules(const windows_path& executable_path, registry_manager& registry, process_context& context, const logger& logger);
|
||||
void map_main_modules(const windows_path& executable_path, windows_version_manager& version, process_context& context,
|
||||
const logger& logger);
|
||||
|
||||
mapped_module* map_module(const windows_path& file, const logger& logger, bool is_static = false);
|
||||
mapped_module* map_local_module(const std::filesystem::path& file, const logger& logger, bool is_static = false);
|
||||
@@ -194,13 +189,11 @@ class module_manager
|
||||
// Execution mode detection
|
||||
execution_mode detect_execution_mode(const windows_path& executable_path, const logger& logger);
|
||||
|
||||
static void get_system_information_from_registry(registry_manager& registry, system_information& info, const logger& logger);
|
||||
|
||||
// Module loading helpers
|
||||
void load_native_64bit_modules(const windows_path& executable_path, const windows_path& ntdll_path, const windows_path& win32u_path,
|
||||
const logger& logger);
|
||||
void load_wow64_modules(const windows_path& executable_path, const windows_path& ntdll_path, const windows_path& win32u_path,
|
||||
const windows_path& ntdll32_path, process_context& context, const logger& logger);
|
||||
const windows_path& ntdll32_path, windows_version_manager& version, const logger& logger);
|
||||
|
||||
void install_wow64_heaven_gate(const logger& logger);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "emulator_utils.hpp"
|
||||
#include "windows_emulator.hpp"
|
||||
#include "version/windows_version_manager.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -178,13 +179,13 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
void process_context::setup(x86_64_emulator& emu, memory_manager& memory, registry_manager& registry,
|
||||
void process_context::setup(x86_64_emulator& emu, memory_manager& memory, registry_manager& registry, windows_version_manager& version,
|
||||
const application_settings& app_settings, const mapped_module& executable, const mapped_module& ntdll,
|
||||
const apiset::container& apiset_container, const mapped_module* ntdll32)
|
||||
{
|
||||
setup_gdt(emu, memory);
|
||||
|
||||
this->kusd.setup();
|
||||
this->kusd.setup(version);
|
||||
|
||||
this->base_allocator = create_allocator(memory, PEB_SEGMENT_SIZE, this->is_wow64_process);
|
||||
auto& allocator = this->base_allocator;
|
||||
@@ -276,8 +277,9 @@ void process_context::setup(x86_64_emulator& emu, memory_manager& memory, regist
|
||||
p.ImageSubsystemMajorVersion = 6;
|
||||
|
||||
p.OSPlatformId = 2;
|
||||
p.OSMajorVersion = 0x0000000a;
|
||||
p.OSBuildNumber = 0x00006c51;
|
||||
p.OSMajorVersion = version.get_major_version();
|
||||
p.OSMinorVersion = version.get_minor_version();
|
||||
p.OSBuildNumber = static_cast<USHORT>(version.get_windows_build_number());
|
||||
|
||||
// p.AnsiCodePageData = allocator.reserve<CPTABLEINFO>().value();
|
||||
// p.OemCodePageData = allocator.reserve<CPTABLEINFO>().value();
|
||||
@@ -367,8 +369,9 @@ void process_context::setup(x86_64_emulator& emu, memory_manager& memory, regist
|
||||
p32.ImageSubsystemMajorVersion = 6;
|
||||
|
||||
p32.OSPlatformId = 2;
|
||||
p32.OSMajorVersion = 0x0a;
|
||||
p32.OSBuildNumber = 0x6c51;
|
||||
p32.OSMajorVersion = version.get_major_version();
|
||||
p32.OSMinorVersion = version.get_minor_version();
|
||||
p32.OSBuildNumber = static_cast<USHORT>(version.get_windows_build_number());
|
||||
|
||||
// Initialize NLS tables for 32-bit processes
|
||||
// These need to be in 32-bit addressable space
|
||||
@@ -400,7 +403,7 @@ void process_context::setup(x86_64_emulator& emu, memory_manager& memory, regist
|
||||
monitor.hmon = h.bits;
|
||||
monitor.rcMonitor = {.left = 0, .top = 0, .right = 1920, .bottom = 1080};
|
||||
monitor.rcWork = monitor.rcMonitor;
|
||||
if (this->is_build_before(26040))
|
||||
if (version.is_build_before(26040))
|
||||
{
|
||||
monitor.b20.monitorDpi = 96;
|
||||
monitor.b20.nativeDpi = monitor.b20.monitorDpi;
|
||||
@@ -436,8 +439,6 @@ void process_context::serialize(utils::buffer_serializer& buffer) const
|
||||
buffer.write(this->kusd);
|
||||
|
||||
buffer.write(this->is_wow64_process);
|
||||
buffer.write(this->windows_build_number);
|
||||
buffer.write(this->windows_update_build_revision_number);
|
||||
buffer.write(this->ntdll_image_base);
|
||||
buffer.write(this->ldr_initialize_thunk);
|
||||
buffer.write(this->rtl_user_thread_start);
|
||||
@@ -486,8 +487,6 @@ void process_context::deserialize(utils::buffer_deserializer& buffer)
|
||||
buffer.read(this->kusd);
|
||||
|
||||
buffer.read(this->is_wow64_process);
|
||||
buffer.read(this->windows_build_number);
|
||||
buffer.read(this->windows_update_build_revision_number);
|
||||
buffer.read(this->ntdll_image_base);
|
||||
buffer.read(this->ldr_initialize_thunk);
|
||||
buffer.read(this->rtl_user_thread_start);
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
struct emulator_settings;
|
||||
struct application_settings;
|
||||
class windows_version_manager;
|
||||
|
||||
struct process_context
|
||||
{
|
||||
@@ -72,9 +73,9 @@ struct process_context
|
||||
{
|
||||
}
|
||||
|
||||
void setup(x86_64_emulator& emu, memory_manager& memory, registry_manager& registry, const application_settings& app_settings,
|
||||
const mapped_module& executable, const mapped_module& ntdll, const apiset::container& apiset_container,
|
||||
const mapped_module* ntdll32 = nullptr);
|
||||
void setup(x86_64_emulator& emu, memory_manager& memory, registry_manager& registry, windows_version_manager& version,
|
||||
const application_settings& app_settings, const mapped_module& executable, const mapped_module& ntdll,
|
||||
const apiset::container& apiset_container, const mapped_module* ntdll32 = nullptr);
|
||||
|
||||
handle create_thread(memory_manager& memory, uint64_t start_address, uint64_t argument, uint64_t stack_size, uint32_t create_flags,
|
||||
bool initial_thread = false);
|
||||
@@ -93,72 +94,6 @@ struct process_context
|
||||
// WOW64 support flag - set during process setup based on executable architecture
|
||||
bool is_wow64_process{false};
|
||||
|
||||
uint32_t windows_build_number{0};
|
||||
uint32_t windows_update_build_revision_number{0};
|
||||
|
||||
bool is_build_before(uint32_t build, std::optional<uint32_t> ubr = std::nullopt) const
|
||||
{
|
||||
if (windows_build_number != build)
|
||||
{
|
||||
return windows_build_number < build;
|
||||
}
|
||||
return ubr.has_value() && windows_update_build_revision_number < *ubr;
|
||||
}
|
||||
|
||||
bool is_build_before_or_equal(uint32_t build, std::optional<uint32_t> ubr = std::nullopt) const
|
||||
{
|
||||
if (windows_build_number != build)
|
||||
{
|
||||
return windows_build_number < build;
|
||||
}
|
||||
return !ubr.has_value() || windows_update_build_revision_number <= *ubr;
|
||||
}
|
||||
|
||||
bool is_build_after_or_equal(uint32_t build, std::optional<uint32_t> ubr = std::nullopt) const
|
||||
{
|
||||
if (windows_build_number != build)
|
||||
{
|
||||
return windows_build_number > build;
|
||||
}
|
||||
return !ubr.has_value() || windows_update_build_revision_number >= *ubr;
|
||||
}
|
||||
|
||||
bool is_build_after(uint32_t build, std::optional<uint32_t> ubr = std::nullopt) const
|
||||
{
|
||||
if (windows_build_number != build)
|
||||
{
|
||||
return windows_build_number > build;
|
||||
}
|
||||
return ubr.has_value() && windows_update_build_revision_number > *ubr;
|
||||
}
|
||||
|
||||
bool is_build_within(uint32_t start_build, uint32_t end_build, std::optional<uint32_t> start_ubr = std::nullopt,
|
||||
std::optional<uint32_t> end_ubr = std::nullopt) const
|
||||
{
|
||||
return is_build_after_or_equal(start_build, start_ubr) && is_build_before(end_build, end_ubr);
|
||||
}
|
||||
|
||||
uint64_t get_system_dll_init_block_size() const
|
||||
{
|
||||
if (is_build_after_or_equal(WINDOWS_VERSION::WINDOWS_11_24H2))
|
||||
{
|
||||
return PS_SYSTEM_DLL_INIT_BLOCK_SIZE_V3;
|
||||
}
|
||||
if (is_build_after_or_equal(WINDOWS_VERSION::WINDOWS_10_2004))
|
||||
{
|
||||
return PS_SYSTEM_DLL_INIT_BLOCK_SIZE_V3_2004;
|
||||
}
|
||||
if (is_build_after_or_equal(WINDOWS_VERSION::WINDOWS_10_1709))
|
||||
{
|
||||
return PS_SYSTEM_DLL_INIT_BLOCK_SIZE_V2;
|
||||
}
|
||||
if (is_build_after_or_equal(WINDOWS_VERSION::WINDOWS_10_1703))
|
||||
{
|
||||
return PS_SYSTEM_DLL_INIT_BLOCK_SIZE_V2_1703;
|
||||
}
|
||||
return PS_SYSTEM_DLL_INIT_BLOCK_SIZE_V1;
|
||||
}
|
||||
|
||||
callbacks* callbacks_{};
|
||||
|
||||
uint64_t shared_section_address{0};
|
||||
|
||||
138
src/windows-emulator/version/windows_version_manager.cpp
Normal file
138
src/windows-emulator/version/windows_version_manager.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
#include "../std_include.hpp"
|
||||
#include "windows_version_manager.hpp"
|
||||
#include "../registry/registry_manager.hpp"
|
||||
#include "../logger.hpp"
|
||||
#include <platform/kernel_mapped.hpp>
|
||||
|
||||
void windows_version_manager::load_from_registry(registry_manager& registry, const logger& logger)
|
||||
{
|
||||
constexpr auto version_key_path = R"(\Registry\Machine\Software\Microsoft\Windows NT\CurrentVersion)";
|
||||
|
||||
const auto version_key = registry.get_key({version_key_path});
|
||||
if (!version_key)
|
||||
{
|
||||
throw std::runtime_error("Failed to get CurrentVersion registry key");
|
||||
}
|
||||
|
||||
for (size_t i = 0; const auto value = registry.get_value(*version_key, i); ++i)
|
||||
{
|
||||
if (value->name == "SystemRoot" && value->type == REG_SZ && !value->data.empty())
|
||||
{
|
||||
const auto* data_ptr = reinterpret_cast<const char16_t*>(value->data.data());
|
||||
const auto char_count = value->data.size() / sizeof(char16_t);
|
||||
std::u16string system_root(data_ptr, char_count > 0 && data_ptr[char_count - 1] == u'\0' ? char_count - 1 : char_count);
|
||||
info_.system_root = windows_path{system_root};
|
||||
}
|
||||
else if ((value->name == "CurrentBuildNumber" || value->name == "CurrentBuild") && value->type == REG_SZ)
|
||||
{
|
||||
const auto* s = reinterpret_cast<const char16_t*>(value->data.data());
|
||||
info_.windows_build_number = static_cast<uint32_t>(std::strtoul(u16_to_u8(s).c_str(), nullptr, 10));
|
||||
}
|
||||
else if (value->name == "UBR" && value->type == REG_DWORD && value->data.size() >= sizeof(uint32_t))
|
||||
{
|
||||
info_.windows_update_build_revision = *reinterpret_cast<const uint32_t*>(value->data.data());
|
||||
}
|
||||
else if (value->name == "CurrentMajorVersionNumber" && value->type == REG_DWORD && value->data.size() >= sizeof(uint32_t))
|
||||
{
|
||||
info_.major_version = *reinterpret_cast<const uint32_t*>(value->data.data());
|
||||
}
|
||||
else if (value->name == "CurrentMinorVersionNumber" && value->type == REG_DWORD && value->data.size() >= sizeof(uint32_t))
|
||||
{
|
||||
info_.minor_version = *reinterpret_cast<const uint32_t*>(value->data.data());
|
||||
}
|
||||
}
|
||||
|
||||
if (info_.system_root.u16string().empty())
|
||||
{
|
||||
throw std::runtime_error("SystemRoot not found in registry");
|
||||
}
|
||||
|
||||
if (info_.windows_build_number == 0)
|
||||
{
|
||||
logger.error("Failed to get CurrentBuildNumber from registry\n");
|
||||
}
|
||||
|
||||
if (info_.windows_update_build_revision == 0)
|
||||
{
|
||||
logger.error("Failed to get UBR from registry\n");
|
||||
}
|
||||
}
|
||||
|
||||
bool windows_version_manager::is_build_before(uint32_t build, std::optional<uint32_t> ubr) const
|
||||
{
|
||||
if (info_.windows_build_number != build)
|
||||
{
|
||||
return info_.windows_build_number < build;
|
||||
}
|
||||
return ubr.has_value() && info_.windows_update_build_revision < *ubr;
|
||||
}
|
||||
|
||||
bool windows_version_manager::is_build_before_or_equal(uint32_t build, std::optional<uint32_t> ubr) const
|
||||
{
|
||||
if (info_.windows_build_number != build)
|
||||
{
|
||||
return info_.windows_build_number < build;
|
||||
}
|
||||
return !ubr.has_value() || info_.windows_update_build_revision <= *ubr;
|
||||
}
|
||||
|
||||
bool windows_version_manager::is_build_after_or_equal(uint32_t build, std::optional<uint32_t> ubr) const
|
||||
{
|
||||
if (info_.windows_build_number != build)
|
||||
{
|
||||
return info_.windows_build_number > build;
|
||||
}
|
||||
return !ubr.has_value() || info_.windows_update_build_revision >= *ubr;
|
||||
}
|
||||
|
||||
bool windows_version_manager::is_build_after(uint32_t build, std::optional<uint32_t> ubr) const
|
||||
{
|
||||
if (info_.windows_build_number != build)
|
||||
{
|
||||
return info_.windows_build_number > build;
|
||||
}
|
||||
return ubr.has_value() && info_.windows_update_build_revision > *ubr;
|
||||
}
|
||||
|
||||
bool windows_version_manager::is_build_within(uint32_t start_build, uint32_t end_build, std::optional<uint32_t> start_ubr,
|
||||
std::optional<uint32_t> end_ubr) const
|
||||
{
|
||||
return is_build_after_or_equal(start_build, start_ubr) && is_build_before(end_build, end_ubr);
|
||||
}
|
||||
|
||||
uint64_t windows_version_manager::get_system_dll_init_block_size() const
|
||||
{
|
||||
if (is_build_after_or_equal(WINDOWS_VERSION::WINDOWS_11_24H2))
|
||||
{
|
||||
return PS_SYSTEM_DLL_INIT_BLOCK_SIZE_V3;
|
||||
}
|
||||
if (is_build_after_or_equal(WINDOWS_VERSION::WINDOWS_10_2004))
|
||||
{
|
||||
return PS_SYSTEM_DLL_INIT_BLOCK_SIZE_V3_2004;
|
||||
}
|
||||
if (is_build_after_or_equal(WINDOWS_VERSION::WINDOWS_10_1709))
|
||||
{
|
||||
return PS_SYSTEM_DLL_INIT_BLOCK_SIZE_V2;
|
||||
}
|
||||
if (is_build_after_or_equal(WINDOWS_VERSION::WINDOWS_10_1703))
|
||||
{
|
||||
return PS_SYSTEM_DLL_INIT_BLOCK_SIZE_V2_1703;
|
||||
}
|
||||
return PS_SYSTEM_DLL_INIT_BLOCK_SIZE_V1;
|
||||
}
|
||||
|
||||
void windows_version_manager::serialize(utils::buffer_serializer& buffer) const
|
||||
{
|
||||
buffer.write(info_.major_version);
|
||||
buffer.write(info_.minor_version);
|
||||
buffer.write(info_.windows_build_number);
|
||||
buffer.write(info_.windows_update_build_revision);
|
||||
}
|
||||
|
||||
void windows_version_manager::deserialize(utils::buffer_deserializer& buffer)
|
||||
{
|
||||
buffer.read(info_.major_version);
|
||||
buffer.read(info_.minor_version);
|
||||
buffer.read(info_.windows_build_number);
|
||||
buffer.read(info_.windows_update_build_revision);
|
||||
}
|
||||
84
src/windows-emulator/version/windows_version_manager.hpp
Normal file
84
src/windows-emulator/version/windows_version_manager.hpp
Normal file
@@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
#include "../windows_path.hpp"
|
||||
#include <serialization.hpp>
|
||||
#include <optional>
|
||||
#include <cstdint>
|
||||
|
||||
class logger;
|
||||
class registry_manager;
|
||||
|
||||
struct windows_version_info
|
||||
{
|
||||
windows_path system_root{};
|
||||
uint32_t major_version{0};
|
||||
uint32_t minor_version{0};
|
||||
uint32_t windows_build_number{0};
|
||||
uint32_t windows_update_build_revision{0};
|
||||
};
|
||||
|
||||
class windows_version_manager
|
||||
{
|
||||
public:
|
||||
void load_from_registry(registry_manager& registry, const logger& logger);
|
||||
|
||||
bool is_build_before(uint32_t build, std::optional<uint32_t> ubr = std::nullopt) const;
|
||||
bool is_build_before_or_equal(uint32_t build, std::optional<uint32_t> ubr = std::nullopt) const;
|
||||
bool is_build_after_or_equal(uint32_t build, std::optional<uint32_t> ubr = std::nullopt) const;
|
||||
bool is_build_after(uint32_t build, std::optional<uint32_t> ubr = std::nullopt) const;
|
||||
bool is_build_within(uint32_t start_build, uint32_t end_build, std::optional<uint32_t> start_ubr = std::nullopt,
|
||||
std::optional<uint32_t> end_ubr = std::nullopt) const;
|
||||
|
||||
uint64_t get_system_dll_init_block_size() const;
|
||||
|
||||
void serialize(utils::buffer_serializer& buffer) const;
|
||||
void deserialize(utils::buffer_deserializer& buffer);
|
||||
|
||||
const windows_path& get_system_root() const
|
||||
{
|
||||
return info_.system_root;
|
||||
}
|
||||
void set_system_root(const windows_path& value)
|
||||
{
|
||||
info_.system_root = value;
|
||||
}
|
||||
|
||||
uint32_t get_major_version() const
|
||||
{
|
||||
return info_.major_version;
|
||||
}
|
||||
void set_major_version(uint32_t value)
|
||||
{
|
||||
info_.major_version = value;
|
||||
}
|
||||
|
||||
uint32_t get_minor_version() const
|
||||
{
|
||||
return info_.minor_version;
|
||||
}
|
||||
void set_minor_version(uint32_t value)
|
||||
{
|
||||
info_.minor_version = value;
|
||||
}
|
||||
|
||||
uint32_t get_windows_build_number() const
|
||||
{
|
||||
return info_.windows_build_number;
|
||||
}
|
||||
void set_windows_build_number(uint32_t value)
|
||||
{
|
||||
info_.windows_build_number = value;
|
||||
}
|
||||
|
||||
uint32_t get_windows_update_build_revision() const
|
||||
{
|
||||
return info_.windows_update_build_revision;
|
||||
}
|
||||
void set_windows_update_build_revision(uint32_t value)
|
||||
{
|
||||
info_.windows_update_build_revision = value;
|
||||
}
|
||||
|
||||
private:
|
||||
windows_version_info info_{};
|
||||
};
|
||||
@@ -351,7 +351,9 @@ void windows_emulator::setup_process(const application_settings& app_settings)
|
||||
const auto& emu = this->emu();
|
||||
auto& context = this->process;
|
||||
|
||||
this->mod_manager.map_main_modules(app_settings.application, this->registry, context, this->log);
|
||||
this->version.load_from_registry(this->registry, this->log);
|
||||
|
||||
this->mod_manager.map_main_modules(app_settings.application, this->version, context, this->log);
|
||||
|
||||
const auto* executable = this->mod_manager.executable;
|
||||
const auto* ntdll = this->mod_manager.ntdll;
|
||||
@@ -359,7 +361,7 @@ void windows_emulator::setup_process(const application_settings& app_settings)
|
||||
|
||||
const auto apiset_data = apiset::obtain(this->emulation_root);
|
||||
|
||||
this->process.setup(this->emu(), this->memory, this->registry, app_settings, *executable, *ntdll, apiset_data,
|
||||
this->process.setup(this->emu(), this->memory, this->registry, this->version, app_settings, *executable, *ntdll, apiset_data,
|
||||
this->mod_manager.wow64_modules_.ntdll32);
|
||||
|
||||
const auto ntdll_data = emu.read_memory(ntdll->image_base, static_cast<size_t>(ntdll->size_of_image));
|
||||
@@ -627,6 +629,8 @@ void windows_emulator::serialize(utils::buffer_serializer& buffer) const
|
||||
buffer.write(this->switch_thread_);
|
||||
buffer.write(this->use_relative_time_);
|
||||
|
||||
this->version.serialize(buffer);
|
||||
|
||||
this->emu().serialize_state(buffer, false);
|
||||
this->memory.serialize_memory_state(buffer, false);
|
||||
this->mod_manager.serialize(buffer);
|
||||
@@ -650,6 +654,8 @@ void windows_emulator::deserialize(utils::buffer_deserializer& buffer)
|
||||
throw std::runtime_error("Can not deserialize emulator with different time dimensions");
|
||||
}
|
||||
|
||||
this->version.deserialize(buffer);
|
||||
|
||||
this->memory.unmap_all_memory();
|
||||
|
||||
this->emu().deserialize_state(buffer, false);
|
||||
@@ -667,6 +673,8 @@ void windows_emulator::save_snapshot()
|
||||
buffer.write(this->executed_instructions_);
|
||||
buffer.write(this->switch_thread_);
|
||||
|
||||
this->version.serialize(buffer);
|
||||
|
||||
this->emu().serialize_state(buffer, true);
|
||||
this->memory.serialize_memory_state(buffer, true);
|
||||
this->mod_manager.serialize(buffer);
|
||||
@@ -694,6 +702,8 @@ void windows_emulator::restore_snapshot()
|
||||
buffer.read(this->executed_instructions_);
|
||||
buffer.read(this->switch_thread_);
|
||||
|
||||
this->version.deserialize(buffer);
|
||||
|
||||
this->emu().deserialize_state(buffer, true);
|
||||
this->memory.deserialize_memory_state(buffer, true);
|
||||
this->mod_manager.deserialize(buffer);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "memory_manager.hpp"
|
||||
#include "module/module_manager.hpp"
|
||||
#include "network/socket_factory.hpp"
|
||||
#include "version/windows_version_manager.hpp"
|
||||
|
||||
struct io_device;
|
||||
|
||||
@@ -94,6 +95,7 @@ class windows_emulator
|
||||
file_system file_sys;
|
||||
memory_manager memory;
|
||||
registry_manager registry{};
|
||||
windows_version_manager version{};
|
||||
module_manager mod_manager;
|
||||
process_context process;
|
||||
syscall_dispatcher dispatcher;
|
||||
|
||||
Reference in New Issue
Block a user