From b642486bc4de5d260c749c0852efecdb92620ad6 Mon Sep 17 00:00:00 2001 From: ahm3dgg Date: Tue, 6 Jan 2026 08:34:41 +0200 Subject: [PATCH] Add Support for KnownDLLs --- src/common/platform/status.hpp | 1 + .../module/module_manager.cpp | 47 +++++++++++---- .../module/module_manager.hpp | 12 ++-- src/windows-emulator/process_context.cpp | 57 +++++++++++++++++++ src/windows-emulator/process_context.hpp | 1 + src/windows-emulator/syscalls/section.cpp | 28 ++++++++- 6 files changed, 125 insertions(+), 21 deletions(-) diff --git a/src/common/platform/status.hpp b/src/common/platform/status.hpp index a1321ad0..de8706ee 100644 --- a/src/common/platform/status.hpp +++ b/src/common/platform/status.hpp @@ -83,6 +83,7 @@ using NTSTATUS = std::uint32_t; #define STATUS_ADDRESS_ALREADY_ASSOCIATED ((NTSTATUS)0xC0000328L) #define STATUS_PORT_NOT_SET ((NTSTATUS)0xC0000353L) #define STATUS_DEBUGGER_INACTIVE ((NTSTATUS)0xC0000354L) +#define STATUS_IMAGE_NOT_AT_BASE ((NTSTATUS)0x40000003L) #define FILE_DEVICE_NETWORK 0x00000012 #define FSCTL_AFD_BASE FILE_DEVICE_NETWORK diff --git a/src/windows-emulator/module/module_manager.cpp b/src/windows-emulator/module/module_manager.cpp index fb6610e4..867fae25 100644 --- a/src/windows-emulator/module/module_manager.cpp +++ b/src/windows-emulator/module/module_manager.cpp @@ -220,6 +220,11 @@ mapped_module* module_manager::map_module_core(const pe_detection_result& detect [[maybe_unused]] auto& strategy = strategy_factory_.get_strategy(detection_result.architecture); mapped_module mod = mapper(); mod.is_static = is_static; + + if (!mod.path.empty()) + { + this->module_load_count[mod.path]++; + } const auto image_base = mod.image_base; const auto entry = this->modules_.try_emplace(image_base, std::move(mod)); @@ -446,22 +451,37 @@ void module_manager::map_main_modules(const windows_path& executable_path, const } } -mapped_module* module_manager::map_module(const windows_path& file, const logger& logger, const bool is_static) +std::optional module_manager::get_module_load_count_by_path(const std::filesystem::path& path) { - return this->map_local_module(this->file_sys_->translate(file), logger, is_static); + auto local_file = weakly_canonical(absolute(path)); + + if (!module_load_count.contains(local_file)) + { + return {}; + } + + return module_load_count[local_file]; +} + +mapped_module* module_manager::map_module(const windows_path& file, const logger& logger, const bool is_static, bool allow_duplicate) +{ + return this->map_local_module(this->file_sys_->translate(file), logger, is_static, allow_duplicate); } // Refactored map_local_module using the new architecture -mapped_module* module_manager::map_local_module(const std::filesystem::path& file, const logger& logger, const bool is_static) +mapped_module* module_manager::map_local_module(const std::filesystem::path& file, const logger& logger, const bool is_static, bool allow_duplicate) { auto local_file = weakly_canonical(absolute(file)); - // Check if module is already loaded - for (auto& mod : this->modules_ | std::views::values) + if (!allow_duplicate) { - if (mod.path == local_file) + // Check if module is already loaded + for (auto& mod : this->modules_ | std::views::values) { - return &mod; + if (mod.path == local_file) + { + return &mod; + } } } @@ -480,14 +500,17 @@ mapped_module* module_manager::map_local_module(const std::filesystem::path& fil // Refactored map_memory_module using the new architecture mapped_module* module_manager::map_memory_module(uint64_t base_address, uint64_t image_size, const std::string& module_name, - const logger& logger, bool is_static) + const logger& logger, bool is_static, bool allow_duplicate) { - // Check if module is already loaded at this address - for (auto& mod : this->modules_ | std::views::values) + if (!allow_duplicate) { - if (mod.image_base == base_address) + // Check if module is already loaded at this address + for (auto& mod : this->modules_ | std::views::values) { - return &mod; + if (mod.image_base == base_address) + { + return &mod; + } } } diff --git a/src/windows-emulator/module/module_manager.hpp b/src/windows-emulator/module/module_manager.hpp index dfbaaebe..95fae0fe 100644 --- a/src/windows-emulator/module/module_manager.hpp +++ b/src/windows-emulator/module/module_manager.hpp @@ -91,13 +91,12 @@ 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, - const logger& logger); + void map_main_modules(const windows_path& executable_path, const windows_path& system32_path, const windows_path& syswow64_path, 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); - mapped_module* map_memory_module(uint64_t base_address, uint64_t image_size, const std::string& module_name, const logger& logger, - bool is_static = false); + std::optional get_module_load_count_by_path(const std::filesystem::path& path); + mapped_module* map_module(const windows_path& file, const logger& logger, bool is_static = false, bool allow_duplicate = false); + mapped_module* map_local_module(const std::filesystem::path& file, const logger& logger, bool is_static = false, bool allow_duplicate = false); + mapped_module* map_memory_module(uint64_t base_address, uint64_t image_size, const std::string& module_name, const logger& logger, bool is_static = false, bool allow_duplicate = false); mapped_module* find_by_address(const uint64_t address) { @@ -157,6 +156,7 @@ class module_manager mapped_module* executable{}; mapped_module* ntdll{}; mapped_module* win32u{}; + std::unordered_map module_load_count; // WOW64-specific modules (for validation and future use) struct wow64_modules diff --git a/src/windows-emulator/process_context.cpp b/src/windows-emulator/process_context.cpp index eb911eeb..db62e749 100644 --- a/src/windows-emulator/process_context.cpp +++ b/src/windows-emulator/process_context.cpp @@ -176,6 +176,61 @@ namespace return env_map; } + + void create_known_dlls_section_objects(std::unordered_map& knowndlls_sections, bool is_wow64) + { + std::filesystem::path known_dlls_fs_root_path; + std::u16string known_dlls_objmgn_root_path; + + if (is_wow64) + { + known_dlls_fs_root_path = "C:\\Windows\\SysWOW64"; + known_dlls_objmgn_root_path = u"\\KnownDlls32"; + } + else + { + known_dlls_fs_root_path = "C:\\Windows\\System32"; + known_dlls_objmgn_root_path = u"\\KnownDlls"; + } + + std::vector known_dll_names = {u"advapi32.dll", u"bcrypt.dll", u"bcryptPrimitives.dll", + u"cfgmgr32.dll", u"clbcatq.dll", u"combase.dll", + u"COMCTL32.dll", u"COMDLG32.dll", u"coml2.dll", + u"CRYPT32.dll", u"difxapi.dll", u"gdi32.dll", + u"gdi32full.dll", u"gdiplus.dll", u"IMAGEHLP.dll", + u"IMM32.dll", u"kernel32.dll", u"kernelbase.dll", + u"MSCTF.dll", u"msvcp_win.dll", u"MSVCRT.dll", + u"NORMALIZ.dll", u"NSI.dll", u"ntdll.dll", + u"ole32.dll", u"OLEAUT32.dll", u"PSAPI.DLL", + u"rpcrt4.dll", u"sechost.dll", u"Setupapi.dll", + u"SHCORE.dll", u"SHELL32.dll", u"SHLWAPI.dll", + u"ucrtbase.dll", u"user32.dll", u"win32u.dll", + u"WINTRUST.dll", u"WLDAP32.dll", u"wow64.dll", + u"wow64cpu.dll", u"wow64win.dll", u"WS2_32.dll"}; + + for (const auto& known_dll_name : known_dll_names) + { + if (is_wow64 && known_dll_name.starts_with(u"wow64")) + { + continue; + } + + section s{}; + + const auto known_dll_fs_path = known_dlls_fs_root_path / known_dll_name; + auto known_dll_objmgn_path = known_dlls_objmgn_root_path + u"\\" + known_dll_name; + const auto file_size = std::filesystem::file_size(known_dll_fs_path); + + utils::string::to_lower_inplace(known_dll_objmgn_path); + s.name = known_dll_objmgn_path; + s.file_name = known_dll_fs_path.u16string(); + s.maximum_size = file_size; + s.section_page_protection = PAGE_EXECUTE_READ; + s.allocation_attributes = SEC_IMAGE; + + knowndlls_sections[known_dll_objmgn_path] = s; + } + } } void process_context::setup(x86_64_emulator& emu, memory_manager& memory, registry_manager& registry, @@ -383,6 +438,8 @@ void process_context::setup(x86_64_emulator& emu, memory_manager& memory, regist } } + create_known_dlls_section_objects(this->knowndlls_sections, is_wow64_process); + this->ntdll_image_base = ntdll.image_base; this->ldr_initialize_thunk = ntdll.find_export("LdrInitializeThunk"); this->rtl_user_thread_start = ntdll.find_export("RtlUserThreadStart"); diff --git a/src/windows-emulator/process_context.hpp b/src/windows-emulator/process_context.hpp index 25a6c1f5..fc39204b 100644 --- a/src/windows-emulator/process_context.hpp +++ b/src/windows-emulator/process_context.hpp @@ -129,6 +129,7 @@ struct process_context handle_store timers{}; handle_store registry_keys{}; std::map atoms{}; + std::unordered_map knowndlls_sections; std::vector default_register_set{}; diff --git a/src/windows-emulator/syscalls/section.cpp b/src/windows-emulator/syscalls/section.cpp index 441d31bb..4c7e7d1e 100644 --- a/src/windows-emulator/syscalls/section.cpp +++ b/src/windows-emulator/syscalls/section.cpp @@ -225,8 +225,12 @@ namespace syscalls return STATUS_NOT_SUPPORTED; } - if (attributes.RootDirectory != KNOWN_DLLS_DIRECTORY && attributes.RootDirectory != KNOWN_DLLS32_DIRECTORY && - attributes.RootDirectory != BASE_NAMED_OBJECTS_DIRECTORY && !filename.starts_with(u"\\KnownDlls")) + bool is_known_dll = (attributes.RootDirectory == KNOWN_DLLS_DIRECTORY + || attributes.RootDirectory == KNOWN_DLLS32_DIRECTORY + || filename.starts_with(u"\\KnownDlls") + || filename.starts_with(u"\\KnownDlls32")); + + if (!is_known_dll && attributes.RootDirectory != BASE_NAMED_OBJECTS_DIRECTORY) { c.win_emu.log.error("Unsupported section\n"); c.emu.stop(); @@ -235,6 +239,19 @@ namespace syscalls utils::string::to_lower_inplace(filename); + if (is_known_dll) + { + auto& knowndlls_sections = c.win_emu.process.knowndlls_sections; + if (!knowndlls_sections.contains(filename)) + { + return STATUS_OBJECT_NAME_NOT_FOUND; + } + + auto knowndll_section = knowndlls_sections[filename]; + section_handle.write(c.proc.sections.store(knowndll_section)); + return STATUS_SUCCESS; + } + for (auto& section_entry : c.proc.sections) { if (section_entry.second.is_image() && section_entry.second.name == filename) @@ -334,7 +351,7 @@ namespace syscalls if (section_entry->is_image()) { - const auto* binary = c.win_emu.mod_manager.map_module(section_entry->file_name, c.win_emu.log); + const auto* binary = c.win_emu.mod_manager.map_module(section_entry->file_name, c.win_emu.log, false, true); if (!binary) { return STATUS_FILE_INVALID; @@ -350,6 +367,11 @@ namespace syscalls base_address.write(binary->image_base); + if (c.win_emu.mod_manager.get_module_load_count_by_path(section_entry->file_name) > 1) + { + return STATUS_IMAGE_NOT_AT_BASE; + } + return STATUS_SUCCESS; }