From 0a414ca346a209a5a080a7ee4083c71cf3b25b4b Mon Sep 17 00:00:00 2001 From: brian Date: Fri, 9 Jan 2026 16:44:48 +0800 Subject: [PATCH] Extract Windows version management into separate module --- src/common/platform/kernel_mapped.hpp | 4 +- src/windows-emulator/kusd_mmio.cpp | 18 ++- src/windows-emulator/kusd_mmio.hpp | 3 +- .../module/module_manager.cpp | 66 +-------- .../module/module_manager.hpp | 15 +- src/windows-emulator/process_context.cpp | 21 ++- src/windows-emulator/process_context.hpp | 73 +-------- .../version/windows_version_manager.cpp | 138 ++++++++++++++++++ .../version/windows_version_manager.hpp | 84 +++++++++++ src/windows-emulator/windows_emulator.cpp | 14 +- src/windows-emulator/windows_emulator.hpp | 2 + 11 files changed, 277 insertions(+), 161 deletions(-) create mode 100644 src/windows-emulator/version/windows_version_manager.cpp create mode 100644 src/windows-emulator/version/windows_version_manager.hpp diff --git a/src/common/platform/kernel_mapped.hpp b/src/common/platform/kernel_mapped.hpp index 27a8d4e7..4413e518 100644 --- a/src/common/platform/kernel_mapped.hpp +++ b/src/common/platform/kernel_mapped.hpp @@ -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); diff --git a/src/windows-emulator/kusd_mmio.cpp b/src/windows-emulator/kusd_mmio.cpp index 8657ee04..b4ccd5d5 100644 --- a/src/windows-emulator/kusd_mmio.cpp +++ b/src/windows-emulator/kusd_mmio.cpp @@ -2,6 +2,7 @@ #include "kusd_mmio.hpp" #include #include "windows_emulator.hpp" +#include "version/windows_version_manager.hpp" #include @@ -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(&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(); } diff --git a/src/windows-emulator/kusd_mmio.hpp b/src/windows-emulator/kusd_mmio.hpp index 449b534b..48b0fc63 100644 --- a/src/windows-emulator/kusd_mmio.hpp +++ b/src/windows-emulator/kusd_mmio.hpp @@ -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_{}; diff --git a/src/windows-emulator/module/module_manager.cpp b/src/windows-emulator/module/module_manager.cpp index 7d7ac9d2..b3c251f8 100644 --- a/src/windows-emulator/module/module_manager.cpp +++ b/src/windows-emulator/module/module_manager.cpp @@ -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 @@ -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(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(value->data.data()); - info.build_number = static_cast(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(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& 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(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; diff --git a/src/windows-emulator/module/module_manager.hpp b/src/windows-emulator/module/module_manager.hpp index 402a0955..0cc9d475 100644 --- a/src/windows-emulator/module/module_manager.hpp +++ b/src/windows-emulator/module/module_manager.hpp @@ -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); diff --git a/src/windows-emulator/process_context.cpp b/src/windows-emulator/process_context.cpp index c3f5d641..35545df9 100644 --- a/src/windows-emulator/process_context.cpp +++ b/src/windows-emulator/process_context.cpp @@ -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(version.get_windows_build_number()); // p.AnsiCodePageData = allocator.reserve().value(); // p.OemCodePageData = allocator.reserve().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(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); diff --git a/src/windows-emulator/process_context.hpp b/src/windows-emulator/process_context.hpp index b5d5f850..a5283cdc 100644 --- a/src/windows-emulator/process_context.hpp +++ b/src/windows-emulator/process_context.hpp @@ -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 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 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 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 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 start_ubr = std::nullopt, - std::optional 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}; diff --git a/src/windows-emulator/version/windows_version_manager.cpp b/src/windows-emulator/version/windows_version_manager.cpp new file mode 100644 index 00000000..928366f9 --- /dev/null +++ b/src/windows-emulator/version/windows_version_manager.cpp @@ -0,0 +1,138 @@ +#include "../std_include.hpp" +#include "windows_version_manager.hpp" +#include "../registry/registry_manager.hpp" +#include "../logger.hpp" +#include + +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(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(value->data.data()); + info_.windows_build_number = static_cast(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(value->data.data()); + } + else if (value->name == "CurrentMajorVersionNumber" && value->type == REG_DWORD && value->data.size() >= sizeof(uint32_t)) + { + info_.major_version = *reinterpret_cast(value->data.data()); + } + else if (value->name == "CurrentMinorVersionNumber" && value->type == REG_DWORD && value->data.size() >= sizeof(uint32_t)) + { + info_.minor_version = *reinterpret_cast(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 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 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 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 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 start_ubr, + std::optional 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); +} diff --git a/src/windows-emulator/version/windows_version_manager.hpp b/src/windows-emulator/version/windows_version_manager.hpp new file mode 100644 index 00000000..18f65bc3 --- /dev/null +++ b/src/windows-emulator/version/windows_version_manager.hpp @@ -0,0 +1,84 @@ +#pragma once + +#include "../windows_path.hpp" +#include +#include +#include + +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 ubr = std::nullopt) const; + bool is_build_before_or_equal(uint32_t build, std::optional ubr = std::nullopt) const; + bool is_build_after_or_equal(uint32_t build, std::optional ubr = std::nullopt) const; + bool is_build_after(uint32_t build, std::optional ubr = std::nullopt) const; + bool is_build_within(uint32_t start_build, uint32_t end_build, std::optional start_ubr = std::nullopt, + std::optional 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_{}; +}; diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index 2fc214e2..a65c2230 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -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(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); diff --git a/src/windows-emulator/windows_emulator.hpp b/src/windows-emulator/windows_emulator.hpp index 86e2a0e2..4ba30bda 100644 --- a/src/windows-emulator/windows_emulator.hpp +++ b/src/windows-emulator/windows_emulator.hpp @@ -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;