Improve Windows version detection and LdrSystemDllInitBlock initialization (#697)

- Add WINDOWS_VERSION enum and PS_SYSTEM_DLL_INIT_BLOCK sizes for WOW64
support across different Windows builds.
- Read system information (SystemRoot, BuildNumber, UpdateBuildRevision)
from registry instead of hardcoded paths.
- Add build comparison helpers in process_context for precise build
checks.
This commit is contained in:
Maurice Heumann
2026-01-14 07:14:06 +01:00
committed by GitHub
13 changed files with 336 additions and 84 deletions

View File

@@ -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)

View File

@@ -30,6 +30,21 @@ namespace utils::string
array[std::min(Size - 1, size)] = {};
}
template <typename T, size_t Size, class Traits = std::char_traits<T>>
requires(std::is_trivially_copyable_v<T>)
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
void copy(T (&array)[Size], const std::basic_string_view<T, Traits> 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<char>(std::tolower(static_cast<unsigned char>(val)));

View File

@@ -1,7 +1,9 @@
#include "std_include.hpp"
#include "kusd_mmio.hpp"
#include <utils/time.hpp>
#include <utils/string.hpp>
#include "windows_emulator.hpp"
#include "version/windows_version_manager.hpp"
#include <address_utils.hpp>
@@ -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<void*>(&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();
}

View File

@@ -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_{};

View File

@@ -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;

View File

@@ -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 <serialization_helper.hpp>
#include <cinttypes>
@@ -11,6 +13,30 @@
#include <algorithm>
#include <vector>
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<ULONG>(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<size_t>(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:

View File

@@ -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);

View File

@@ -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<const char16_t*>(value->data.data());
return static_cast<uint32_t>(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<USHORT>(version.get_windows_build_number());
// p.AnsiCodePageData = allocator.reserve<CPTABLEINFO>().value();
// p.OemCodePageData = allocator.reserve<CPTABLEINFO>().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<USHORT>(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);

View File

@@ -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};

View File

@@ -0,0 +1,117 @@
#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);
}
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);
}

View File

@@ -0,0 +1,82 @@
#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;
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_{};
};

View File

@@ -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<size_t>(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);

View File

@@ -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;