diff --git a/src/common/platform/kernel_mapped.hpp b/src/common/platform/kernel_mapped.hpp index cad0ecf0..4413e518 100644 --- a/src/common/platform/kernel_mapped.hpp +++ b/src/common/platform/kernel_mapped.hpp @@ -2003,4 +2003,32 @@ typedef enum class _SECTION_INFORMATION_CLASS SectionInternalImageInformation = 4 } SECTION_INFORMATION_CLASS, *PSECTION_INFORMATION_CLASS; +typedef enum _WINDOWS_VERSION : uint32_t +{ + WINDOWS_10_1507 = 10240, + WINDOWS_10_1511 = 10586, + WINDOWS_10_1607 = 14393, + WINDOWS_10_1703 = 15063, + WINDOWS_10_1709 = 16299, + WINDOWS_10_1803 = 17134, + WINDOWS_10_1809 = 17763, + WINDOWS_10_1903 = 18362, + WINDOWS_10_1909 = 18363, + WINDOWS_10_2004 = 19041, + WINDOWS_10_20H2 = 19042, + WINDOWS_10_21H1 = 19043, + WINDOWS_10_21H2 = 19044, + WINDOWS_10_22H2 = 19045, + WINDOWS_11_21H2 = 22000, + 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); +constexpr uint64_t PS_SYSTEM_DLL_INIT_BLOCK_SIZE_V2 = sizeof(PS_SYSTEM_DLL_INIT_BLOCK_V2); +constexpr uint64_t PS_SYSTEM_DLL_INIT_BLOCK_SIZE_V3_2004 = offsetof(PS_SYSTEM_DLL_INIT_BLOCK_V3, ScpCfgCheckFunction); +constexpr uint64_t PS_SYSTEM_DLL_INIT_BLOCK_SIZE_V3 = sizeof(PS_SYSTEM_DLL_INIT_BLOCK_V3); + // NOLINTEND(modernize-use-using,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) diff --git a/src/common/utils/string.hpp b/src/common/utils/string.hpp index a732217d..c887de7f 100644 --- a/src/common/utils/string.hpp +++ b/src/common/utils/string.hpp @@ -30,6 +30,21 @@ namespace utils::string array[std::min(Size - 1, size)] = {}; } + template > + requires(std::is_trivially_copyable_v) + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + void copy(T (&array)[Size], const std::basic_string_view str) + { + if constexpr (Size == 0) + { + return; + } + + const auto size = std::min(Size - 1, str.size()); + memcpy(array, str.data(), size * sizeof(T)); + array[size] = {}; + } + inline char char_to_lower(const char val) { return static_cast(std::tolower(static_cast(val))); diff --git a/src/windows-emulator/kusd_mmio.cpp b/src/windows-emulator/kusd_mmio.cpp index 8657ee04..076ce0d9 100644 --- a/src/windows-emulator/kusd_mmio.cpp +++ b/src/windows-emulator/kusd_mmio.cpp @@ -1,7 +1,9 @@ #include "std_include.hpp" #include "kusd_mmio.hpp" #include +#include #include "windows_emulator.hpp" +#include "version/windows_version_manager.hpp" #include @@ -11,7 +13,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 +31,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 +83,8 @@ 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(); + utils::string::copy(kusd.NtSystemRoot.arr, std::u16string_view{system_root.u16string()}); kusd.ImageNumberLow = IMAGE_FILE_MACHINE_AMD64; kusd.ImageNumberHigh = IMAGE_FILE_MACHINE_AMD64; @@ -118,9 +121,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/memory_manager.cpp b/src/windows-emulator/memory_manager.cpp index e1c2f964..925cab3f 100644 --- a/src/windows-emulator/memory_manager.cpp +++ b/src/windows-emulator/memory_manager.cpp @@ -309,6 +309,11 @@ bool memory_manager::commit_memory(const uint64_t address, const size_t size, co return false; } + if (memory_region_policy::is_section_kind(entry->second.kind)) + { + return false; + } + const auto end = address + size; const auto region_end = entry->first + entry->second.length; diff --git a/src/windows-emulator/module/module_manager.cpp b/src/windows-emulator/module/module_manager.cpp index fb6610e4..6bfcb15e 100644 --- a/src/windows-emulator/module/module_manager.cpp +++ b/src/windows-emulator/module/module_manager.cpp @@ -4,6 +4,8 @@ #include "platform/win_pefile.hpp" #include "windows-emulator/logger.hpp" #include "../wow64_heaven_gate.hpp" +#include "../version/windows_version_manager.hpp" +#include "../process_context.hpp" #include #include @@ -11,6 +13,30 @@ #include #include +namespace +{ + uint64_t get_system_dll_init_block_size(const windows_version_manager& version) + { + if (version.is_build_after_or_equal(WINDOWS_VERSION::WINDOWS_11_24H2)) + { + return PS_SYSTEM_DLL_INIT_BLOCK_SIZE_V3; + } + if (version.is_build_after_or_equal(WINDOWS_VERSION::WINDOWS_10_2004)) + { + return PS_SYSTEM_DLL_INIT_BLOCK_SIZE_V3_2004; + } + if (version.is_build_after_or_equal(WINDOWS_VERSION::WINDOWS_10_1709)) + { + return PS_SYSTEM_DLL_INIT_BLOCK_SIZE_V2; + } + if (version.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; + } +} + namespace utils { static void serialize(buffer_serializer& buffer, const exported_symbol& sym) @@ -257,23 +283,19 @@ void module_manager::load_native_64bit_modules(const windows_path& executable_pa this->win32u = this->map_module(win32u_path, logger, true); } -// WOW64 module loading (with TODO placeholders for 32-bit details) +// 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, const logger& logger) + 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"); - // Load 32-bit main executable this->executable = this->map_module(executable_path, logger, true); + this->ntdll = this->map_module(ntdll_path, logger, true); + this->win32u = this->map_module(win32u_path, logger, true); - // Load 64-bit system modules for WOW64 subsystem - this->ntdll = this->map_module(ntdll_path, logger, true); // 64-bit ntdll - this->win32u = this->map_module(win32u_path, logger, true); // 64-bit win32u + this->wow64_modules_.ntdll32 = this->map_module(ntdll32_path, logger, true); - // Load 32-bit ntdll module for WOW64 subsystem - this->wow64_modules_.ntdll32 = this->map_module(ntdll32_path, logger, true); // 32-bit ntdll - - // Get original ImageBase values from PE files const auto ntdll32_original_imagebase = this->wow64_modules_.ntdll32->get_image_base_file(); const auto ntdll64_original_imagebase = this->ntdll->get_image_base_file(); @@ -283,12 +305,10 @@ void module_manager::load_wow64_modules(const windows_path& executable_path, con return; } - // Set up LdrSystemDllInitBlock structure PS_SYSTEM_DLL_INIT_BLOCK init_block = {}; - constexpr uint64_t symtem_dll_init_block_fix_size = 0xF0; // Wine or WIN10 + const auto init_block_size = get_system_dll_init_block_size(version); - // Basic structure initialization - init_block.Size = symtem_dll_init_block_fix_size; + init_block.Size = static_cast(init_block_size); // Calculate relocation values // SystemDllWowRelocation = mapped_base - original_imagebase for 32-bit ntdll @@ -344,8 +364,7 @@ void module_manager::load_wow64_modules(const windows_path& executable_path, con return; } - // Write the initialized structure to the export address - this->memory_->write_memory(ldr_init_block_addr, &init_block, symtem_dll_init_block_fix_size); + this->memory_->write_memory(ldr_init_block_addr, &init_block, static_cast(init_block_size)); logger.info("Successfully initialized LdrSystemDllInitBlock at 0x%" PRIx64 "\n", ldr_init_block_addr); @@ -422,14 +441,16 @@ void module_manager::install_wow64_heaven_gate(const logger& logger) } } -// Refactored map_main_modules with execution mode detection -void module_manager::map_main_modules(const windows_path& executable_path, const windows_path& system32_path, - const windows_path& syswow64_path, const logger& logger) +void module_manager::map_main_modules(const windows_path& executable_path, windows_version_manager& version, process_context& context, + const logger& logger) { - // Detect execution mode based on executable architecture - current_execution_mode_ = detect_execution_mode(executable_path, logger); + 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); - // Load modules based on detected execution mode switch (current_execution_mode_) { case execution_mode::native_64bit: @@ -437,7 +458,8 @@ void module_manager::map_main_modules(const windows_path& executable_path, const break; case execution_mode::wow64_32bit: - load_wow64_modules(executable_path, system32_path / "ntdll.dll", system32_path / "win32u.dll", syswow64_path / "ntdll.dll", logger); + load_wow64_modules(executable_path, system32_path / "ntdll.dll", system32_path / "win32u.dll", syswow64_path / "ntdll.dll", version, + logger); break; case execution_mode::unknown: diff --git a/src/windows-emulator/module/module_manager.hpp b/src/windows-emulator/module/module_manager.hpp index dfbaaebe..0cc9d475 100644 --- a/src/windows-emulator/module/module_manager.hpp +++ b/src/windows-emulator/module/module_manager.hpp @@ -7,6 +7,9 @@ #include "platform/win_pefile.hpp" class logger; +class registry_manager; +class windows_version_manager; +struct process_context; // Execution mode for the emulated process enum class execution_mode @@ -91,7 +94,7 @@ class module_manager module_manager(memory_manager& memory, file_system& file_sys, callbacks& cb); - void map_main_modules(const windows_path& executable_path, const windows_path& system32_path, const windows_path& syswow64_path, + 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); @@ -190,7 +193,7 @@ class module_manager 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, 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 1ab58bb6..8fd5a138 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 { @@ -176,43 +177,15 @@ namespace return env_map; } - - uint32_t read_windows_build(registry_manager& registry) - { - const auto key = registry.get_key({R"(\Registry\Machine\Software\Microsoft\Windows NT\CurrentVersion)"}); - - if (!key) - { - return 0; - } - - for (size_t i = 0; const auto value = registry.get_value(*key, i); ++i) - { - if (value->type != REG_SZ) - { - continue; - } - - if (value->name == "CurrentBuildNumber" || value->name == "CurrentBuild") - { - const auto* s = reinterpret_cast(value->data.data()); - return static_cast(std::strtoul(u16_to_u8(s).c_str(), nullptr, 10)); - } - } - - return 0; - } } -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) { - this->windows_build_number = read_windows_build(registry); - 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; @@ -304,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(); @@ -395,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 @@ -428,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_older_windows_build()) + if (version.is_build_before(26040)) { monitor.b20.monitorDpi = 96; monitor.b20.nativeDpi = monitor.b20.monitorDpi; @@ -524,7 +499,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->ntdll_image_base); buffer.write(this->ldr_initialize_thunk); buffer.write(this->rtl_user_thread_start); @@ -575,7 +549,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->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 2ffbe89f..77323284 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); void setup_callback_hook(windows_emulator& win_emu, memory_manager& memory); @@ -95,13 +96,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}; - - bool is_older_windows_build() const - { - return windows_build_number < 26040; - } - 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..cc1c93f8 --- /dev/null +++ b/src/windows-emulator/version/windows_version_manager.cpp @@ -0,0 +1,117 @@ +#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); +} + +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..9f2c6c5d --- /dev/null +++ b/src/windows-emulator/version/windows_version_manager.hpp @@ -0,0 +1,82 @@ +#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; + + 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 987b6fb2..185779e3 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -351,10 +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, R"(C:\Windows\System32)", R"(C:\Windows\SysWOW64)", this->log); + this->version.load_from_registry(this->registry, this->log); - // Set WOW64 flag based on the detected execution mode - context.is_wow64_process = (this->mod_manager.get_execution_mode() == execution_mode::wow64_32bit); + 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; @@ -362,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)); @@ -631,6 +630,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); @@ -654,6 +655,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); @@ -671,6 +674,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); @@ -698,6 +703,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;