From f54bc3467f97116300bfdd7413146c59196ea176 Mon Sep 17 00:00:00 2001 From: ahm3dgg Date: Wed, 7 Jan 2026 07:34:34 +0200 Subject: [PATCH] Support for KnownDLLs and Some Refactoring --- src/common/platform/win_pefile.hpp | 152 ++++++++++++++ src/emulator/address_utils.hpp | 5 + src/tools/dump-apiset/dump-apiset.cpp | 2 +- src/windows-emulator/apiset/apiset.hpp | 3 +- .../module/module_mapping.cpp | 19 +- src/windows-emulator/process_context.cpp | 195 ++++++++++++++---- src/windows-emulator/syscalls/section.cpp | 136 ++---------- src/windows-emulator/windows_objects.hpp | 59 ++++-- 8 files changed, 371 insertions(+), 200 deletions(-) diff --git a/src/common/platform/win_pefile.hpp b/src/common/platform/win_pefile.hpp index 8bae3298..f4c60630 100644 --- a/src/common/platform/win_pefile.hpp +++ b/src/common/platform/win_pefile.hpp @@ -6,6 +6,8 @@ #include #include #include +#include +#include "../utils/buffer_accessor.hpp" // NOLINTBEGIN(modernize-use-using,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) @@ -478,12 +480,75 @@ struct SECTION_IMAGE_INFORMATION namespace winpe { + struct pe_image_basic_info + { + uint64_t entry_point_rva{}; + uint64_t image_base{}; + uint64_t size_of_stack_reserve{}; + uint64_t size_of_stack_commit{}; + uint32_t size_of_code{}; + uint32_t loader_flags{}; + uint32_t checksum{}; + uint16_t machine{}; + uint16_t subsystem{}; + uint16_t subsystem_major_version{}; + uint16_t subsystem_minor_version{}; + uint16_t image_characteristics{}; + uint16_t dll_characteristics{}; + bool has_code{false}; + std::array _padding{}; + }; enum class pe_arch { pe32, pe64 }; + + template + inline uint64_t get_first_section_offset(const PENTHeaders_t& nt_headers, const uint64_t nt_headers_offset) + { + const auto* nt_headers_addr = reinterpret_cast(&nt_headers); + const size_t optional_header_offset = + reinterpret_cast(&(nt_headers.OptionalHeader)) - reinterpret_cast(&nt_headers); + const size_t optional_header_size = nt_headers.FileHeader.SizeOfOptionalHeader; + const auto* first_section_addr = nt_headers_addr + optional_header_offset + optional_header_size; + + const auto first_section_absolute = reinterpret_cast(first_section_addr); + const auto absolute_base = reinterpret_cast(&nt_headers); + return nt_headers_offset + (first_section_absolute - absolute_base); + } + + template + inline PEDirectory_t2 get_data_directory_by_index(const PENTHeaders_t& nt_headers, uint64_t directory_index) + { + return nt_headers.OptionalHeader.DataDirectory[directory_index]; + } + + template + IMAGE_SECTION_HEADER get_section_header_by_rva(const utils::safe_buffer_accessor& buffer, const PENTHeaders_t& nt_headers, + uint64_t nt_headers_offset, uint64_t rva) + { + IMAGE_SECTION_HEADER section_header = {}; + + auto next_section_offset = winpe::get_first_section_offset(nt_headers, nt_headers_offset); + for (size_t i = 0; i < nt_headers.FileHeader.NumberOfSections; i++) + { + const auto section = buffer.as(next_section_offset).get(); + auto section_va_start = section.VirtualAddress; + auto section_va_end = section.VirtualAddress + section.Misc.VirtualSize; + + if (section_va_start <= rva && rva <= section_va_end) + { + section_header = section; + break; + } + + next_section_offset += sizeof(IMAGE_SECTION_HEADER); + } + + return section_header; + } inline std::variant get_pe_arch(const std::filesystem::path& file) { @@ -591,6 +656,93 @@ namespace winpe return std::make_error_code(std::errc::executable_format_error); } + // Helper function to parse PE headers and extract image information + template + inline bool parse_pe_headers(const std::vector& file_data, pe_image_basic_info& info) + { + if (file_data.size() < sizeof(PEDosHeader_t)) + { + return false; + } + + const auto* dos_header = reinterpret_cast(file_data.data()); + if (dos_header->e_magic != PEDosHeader_t::k_Magic) + { + return false; + } + + // First check if we can read up to the optional header magic + if (file_data.size() < dos_header->e_lfanew + sizeof(uint32_t) + sizeof(PEFileHeader_t) + sizeof(uint16_t)) + { + return false; + } + + // Read the magic number from the optional header + const auto* magic_ptr = + reinterpret_cast(file_data.data() + dos_header->e_lfanew + sizeof(uint32_t) + sizeof(PEFileHeader_t)); + const uint16_t magic = *magic_ptr; + + // Check if the magic matches the expected type + constexpr uint16_t expected_magic = (sizeof(T) == sizeof(uint32_t)) + ? static_cast(PEOptionalHeader_t::k_Magic) + : static_cast(PEOptionalHeader_t::k_Magic); + + if (magic != expected_magic) + { + return false; + } + + // Now check the full NT headers size + if (file_data.size() < dos_header->e_lfanew + sizeof(PENTHeaders_t)) + { + return false; + } + + const auto* nt_headers = reinterpret_cast*>(file_data.data() + dos_header->e_lfanew); + if (nt_headers->Signature != PENTHeaders_t::k_Signature) + { + return false; + } + + const auto& file_header = nt_headers->FileHeader; + const auto& optional_header = nt_headers->OptionalHeader; + + // Extract information from headers + info.machine = static_cast(file_header.Machine); + info.image_characteristics = file_header.Characteristics; + + info.entry_point_rva = optional_header.AddressOfEntryPoint; + info.image_base = optional_header.ImageBase; + info.subsystem = optional_header.Subsystem; + info.subsystem_major_version = optional_header.MajorSubsystemVersion; + info.subsystem_minor_version = optional_header.MinorSubsystemVersion; + info.dll_characteristics = optional_header.DllCharacteristics; + info.size_of_stack_reserve = optional_header.SizeOfStackReserve; + info.size_of_stack_commit = optional_header.SizeOfStackCommit; + info.size_of_code = optional_header.SizeOfCode; + info.loader_flags = optional_header.LoaderFlags; + info.checksum = optional_header.CheckSum; + + // Check if image contains code + info.has_code = (optional_header.SizeOfCode > 0) || (optional_header.AddressOfEntryPoint != 0); + + // Also check section characteristics for code sections + const auto sections_offset = dos_header->e_lfanew + sizeof(uint32_t) + sizeof(PEFileHeader_t) + file_header.SizeOfOptionalHeader; + if (file_data.size() >= sections_offset + sizeof(IMAGE_SECTION_HEADER) * file_header.NumberOfSections) + { + const auto* sections = reinterpret_cast(file_data.data() + sections_offset); + for (uint16_t i = 0; i < file_header.NumberOfSections; ++i) + { + if (sections[i].Characteristics & IMAGE_SCN_CNT_CODE) + { + info.has_code = true; + break; + } + } + } + + return true; + } } // NOLINTEND(modernize-use-using,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) diff --git a/src/emulator/address_utils.hpp b/src/emulator/address_utils.hpp index 224f2831..3edc0b98 100644 --- a/src/emulator/address_utils.hpp +++ b/src/emulator/address_utils.hpp @@ -52,3 +52,8 @@ constexpr uint64_t page_align_up(const uint64_t value, const uint64_t page_size { return align_up(value, page_size); } + +constexpr uint64_t rva_to_raw(uint64_t va_base, uint64_t raw_base, uint64_t rva) +{ + return rva - (va_base - raw_base); +} diff --git a/src/tools/dump-apiset/dump-apiset.cpp b/src/tools/dump-apiset/dump-apiset.cpp index 5388e6b2..a829a7b3 100644 --- a/src/tools/dump-apiset/dump-apiset.cpp +++ b/src/tools/dump-apiset/dump-apiset.cpp @@ -32,7 +32,7 @@ int main() printf("EntryOffset: %08lX\n", api_set_map->EntryOffset); printf("HashOffset: %08lX\n", api_set_map->HashOffset); printf("HashFactor: %08lX\n", api_set_map->HashFactor); - // print_apiset(apiSetMap); + print_apiset(api_set_map); // Compress the API-SET binary blob const auto* data_ptr = reinterpret_cast(api_set_map); diff --git a/src/windows-emulator/apiset/apiset.hpp b/src/windows-emulator/apiset/apiset.hpp index 99422c46..d6d83e58 100644 --- a/src/windows-emulator/apiset/apiset.hpp +++ b/src/windows-emulator/apiset/apiset.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "../emulator_utils.hpp" @@ -33,4 +34,4 @@ namespace apiset const API_SET_NAMESPACE& orig_api_set_map); emulator_object clone(x86_64_emulator& emu, emulator_allocator& allocator, const container& container); -} +} \ No newline at end of file diff --git a/src/windows-emulator/module/module_mapping.cpp b/src/windows-emulator/module/module_mapping.cpp index 6e179b24..e4a24802 100644 --- a/src/windows-emulator/module/module_mapping.cpp +++ b/src/windows-emulator/module/module_mapping.cpp @@ -4,23 +4,10 @@ #include #include +#include namespace { - template - uint64_t get_first_section_offset(const PENTHeaders_t& nt_headers, const uint64_t nt_headers_offset) - { - const auto* nt_headers_addr = reinterpret_cast(&nt_headers); - const size_t optional_header_offset = - reinterpret_cast(&(nt_headers.OptionalHeader)) - reinterpret_cast(&nt_headers); - const size_t optional_header_size = nt_headers.FileHeader.SizeOfOptionalHeader; - const auto* first_section_addr = nt_headers_addr + optional_header_offset + optional_header_size; - - const auto first_section_absolute = reinterpret_cast(first_section_addr); - const auto absolute_base = reinterpret_cast(&nt_headers); - return nt_headers_offset + (first_section_absolute - absolute_base); - } - template std::vector read_mapped_memory(const memory_manager& memory, const mapped_module& binary) { @@ -210,7 +197,7 @@ namespace void map_sections(memory_manager& memory, mapped_module& binary, const utils::safe_buffer_accessor buffer, const PENTHeaders_t& nt_headers, const uint64_t nt_headers_offset) { - const auto first_section_offset = get_first_section_offset(nt_headers, nt_headers_offset); + const auto first_section_offset = winpe::get_first_section_offset(nt_headers, nt_headers_offset); const auto sections = buffer.as(static_cast(first_section_offset)); for (size_t i = 0; i < nt_headers.FileHeader.NumberOfSections; ++i) @@ -384,7 +371,7 @@ mapped_module map_module_from_memory(memory_manager& memory, uint64_t base_addre binary.size_of_heap_reserve = optional_header.SizeOfHeapReserve; binary.size_of_heap_commit = optional_header.SizeOfHeapCommit; - const auto section_offset = get_first_section_offset(nt_headers, nt_headers_offset); + const auto section_offset = winpe::get_first_section_offset(nt_headers, nt_headers_offset); const auto sections = buffer.as(static_cast(section_offset)); for (size_t i = 0; i < nt_headers.FileHeader.NumberOfSections; ++i) diff --git a/src/windows-emulator/process_context.cpp b/src/windows-emulator/process_context.cpp index 2573252c..8a759737 100644 --- a/src/windows-emulator/process_context.cpp +++ b/src/windows-emulator/process_context.cpp @@ -3,6 +3,8 @@ #include "emulator_utils.hpp" #include "windows_emulator.hpp" +#include "utils/io.hpp" +#include "utils/buffer_accessor.hpp" namespace { @@ -177,66 +179,170 @@ namespace return env_map; } - void create_known_dlls_section_objects(std::unordered_map& knowndlls_sections, const file_system& file_system, - bool is_wow64) + std::unordered_map get_apiset_namespace_table(const API_SET_NAMESPACE* api_set_map) { - windows_path known_dlls_fs_root_path; - std::u16string known_dlls_objmgn_root_path; + std::unordered_map apiset; + + for (size_t i = 0; i < api_set_map->Count; i++) + { + const auto entry = reinterpret_cast(reinterpret_cast(api_set_map) + + api_set_map->EntryOffset + i * sizeof(API_SET_NAMESPACE_ENTRY)); + + std::u16string name(reinterpret_cast(reinterpret_cast(api_set_map) + entry->NameOffset), + entry->NameLength / sizeof(char16_t)); + + const auto value = reinterpret_cast(reinterpret_cast(api_set_map) + entry->ValueOffset + + (entry->ValueCount - 1) * sizeof(API_SET_VALUE_ENTRY)); + std::u16string base_name(reinterpret_cast(reinterpret_cast(api_set_map) + value->ValueOffset), + value->ValueLength / sizeof(char16_t)); + + apiset[name + u".dll"] = base_name; + } + + return apiset; + } + + template + void create_known_dlls_section_objects( + std::unordered_map& knowndlls_section_objects, + registry_manager& registry, + const apiset::container& apiset_container, + const file_system& file_system, + bool is_wow64) + { + const auto* api_set_data = reinterpret_cast(apiset_container.data.data()); + auto apiset = get_apiset_namespace_table(api_set_data); + + std::unordered_set visited_dlls; + windows_path system_root_path; + std::filesystem::path local_system_root_path; if (is_wow64) { - known_dlls_fs_root_path = "C:\\Windows\\SysWOW64"; - known_dlls_objmgn_root_path = u"\\KnownDlls32"; + system_root_path = "C:\\Windows\\SysWOW64"; } else { - known_dlls_fs_root_path = "C:\\Windows\\System32"; - known_dlls_objmgn_root_path = u"\\KnownDlls"; + system_root_path = "C:\\Windows\\System32"; } - 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) + std::optional knowndlls_key = registry.get_key({R"(\Registry\Machine\System\CurrentControlSet\Control\Session Manager\KnownDLLs)"}); + if (!knowndlls_key) { - if (is_wow64 && known_dll_name.starts_with(u"wow64")) + return; + } + + local_system_root_path = file_system.translate(system_root_path); + for (size_t i = 0; const auto value_opt = registry.get_value(*knowndlls_key, i); i++) + { + const auto& value = *value_opt; + + if (value.type != REG_SZ && value.type != REG_EXPAND_SZ) { continue; } - section s{}; - - const auto known_dll_fs_path = known_dlls_fs_root_path / known_dll_name; - - auto local_file = file_system.translate(known_dll_fs_path); - if (!std::filesystem::exists(local_file)) + if (value.data.empty() || value.data.size() % 2 != 0) { continue; } - auto known_dll_objmgn_path = known_dlls_objmgn_root_path + u"\\" + known_dll_name; - const auto file_size = std::filesystem::file_size(local_file); + const auto char_count = value.data.size() / sizeof(char16_t); + const auto* data_ptr = reinterpret_cast(value.data.data()); + if (data_ptr[char_count - 1] != u'\0') + { + continue; + } - 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; + auto known_dll_name = std::u16string(data_ptr, char_count - 1); + auto known_dll_path = local_system_root_path / known_dll_name; - knowndlls_sections[known_dll_objmgn_path] = s; + if (!std::filesystem::exists(known_dll_path)) + { + continue; + } + + utils::string::to_lower_inplace(known_dll_name); + if (visited_dlls.contains(known_dll_name)) + { + continue; + } + + auto file = utils::io::read_file(known_dll_path); + { + section s; + s.file_name = known_dll_path.u16string(); + s.maximum_size = page_align_up(std::filesystem::file_size(s.file_name)); + s.allocation_attributes = SEC_IMAGE; + s.section_page_protection = PAGE_EXECUTE; + s.cache_image_info_from_filedata(file); + knowndlls_section_objects[known_dll_name] = s; + } + + utils::safe_buffer_accessor buffer{file}; + + const auto dos_header = buffer.as(0).get(); + const auto nt_headers_offset = dos_header.e_lfanew; + const auto nt_headers = buffer.as>(nt_headers_offset).get(); + + const auto& import_directory_entry = winpe::get_data_directory_by_index(nt_headers, IMAGE_DIRECTORY_ENTRY_IMPORT); + if (!import_directory_entry.VirtualAddress) + { + continue; + } + + const auto section_with_import_descs = winpe::get_section_header_by_rva(buffer, nt_headers, nt_headers_offset, import_directory_entry.VirtualAddress); + auto import_directory_vbase = section_with_import_descs.VirtualAddress; + auto import_directory_rbase = section_with_import_descs.PointerToRawData; + + uint64_t import_directory_raw = rva_to_raw(import_directory_vbase, import_directory_rbase, import_directory_entry.VirtualAddress); + auto import_descriptors = buffer.as(import_directory_raw); + for (size_t import_desc_index = 0;; import_desc_index++) + { + const auto descriptor = import_descriptors.get(import_desc_index); + if (!descriptor.Name) + { + break; + } + + auto known_dll_dep_name = buffer.as_string(rva_to_raw(import_directory_vbase, import_directory_rbase, descriptor.Name)); + + utils::string::to_lower_inplace(known_dll_dep_name); + auto known_dll_dep_name_16 = u8_to_u16(known_dll_dep_name); + + if (known_dll_dep_name_16.starts_with(u"api-") || known_dll_dep_name_16.starts_with(u"ext-")) + { + if (apiset.contains(known_dll_dep_name_16)) + { + known_dll_dep_name_16 = apiset[known_dll_dep_name_16]; + } + else + { + continue; + } + } + + if (knowndlls_section_objects.contains(known_dll_dep_name_16)) + { + continue; + } + + { + auto known_dll_dep_path = local_system_root_path / known_dll_dep_name_16; + auto file = utils::io::read_file(known_dll_dep_path); + + section s; + s.file_name = known_dll_dep_path.u16string(); + s.maximum_size = page_align_up(std::filesystem::file_size(s.file_name)); + s.allocation_attributes = SEC_IMAGE; + s.section_page_protection = PAGE_EXECUTE; + s.cache_image_info_from_filedata(file); + + knowndlls_section_objects[known_dll_dep_name_16] = s; + } + } + + visited_dlls.insert(known_dll_name); } } } @@ -446,7 +552,14 @@ void process_context::setup(x86_64_emulator& emu, memory_manager& memory, regist } } - create_known_dlls_section_objects(this->knowndlls_sections, file_system, is_wow64_process); + if (is_wow64_process) + { + create_known_dlls_section_objects(this->knowndlls_sections, registry, apiset_container, file_system, is_wow64_process); + } + else + { + create_known_dlls_section_objects(this->knowndlls_sections, registry, apiset_container, file_system, is_wow64_process); + } this->ntdll_image_base = ntdll.image_base; this->ldr_initialize_thunk = ntdll.find_export("LdrInitializeThunk"); diff --git a/src/windows-emulator/syscalls/section.cpp b/src/windows-emulator/syscalls/section.cpp index b013b0d3..783d1f62 100644 --- a/src/windows-emulator/syscalls/section.cpp +++ b/src/windows-emulator/syscalls/section.cpp @@ -7,94 +7,6 @@ namespace syscalls { - // Helper function to parse PE headers and extract image information - template - static bool parse_pe_headers(const std::vector& file_data, section::image_info& info) - { - if (file_data.size() < sizeof(PEDosHeader_t)) - { - return false; - } - - const auto* dos_header = reinterpret_cast(file_data.data()); - if (dos_header->e_magic != PEDosHeader_t::k_Magic) - { - return false; - } - - // First check if we can read up to the optional header magic - if (file_data.size() < dos_header->e_lfanew + sizeof(uint32_t) + sizeof(PEFileHeader_t) + sizeof(uint16_t)) - { - return false; - } - - // Read the magic number from the optional header - const auto* magic_ptr = - reinterpret_cast(file_data.data() + dos_header->e_lfanew + sizeof(uint32_t) + sizeof(PEFileHeader_t)); - const uint16_t magic = *magic_ptr; - - // Check if the magic matches the expected type - constexpr uint16_t expected_magic = (sizeof(T) == sizeof(uint32_t)) - ? static_cast(PEOptionalHeader_t::k_Magic) - : static_cast(PEOptionalHeader_t::k_Magic); - - if (magic != expected_magic) - { - return false; - } - - // Now check the full NT headers size - if (file_data.size() < dos_header->e_lfanew + sizeof(PENTHeaders_t)) - { - return false; - } - - const auto* nt_headers = reinterpret_cast*>(file_data.data() + dos_header->e_lfanew); - if (nt_headers->Signature != PENTHeaders_t::k_Signature) - { - return false; - } - - const auto& file_header = nt_headers->FileHeader; - const auto& optional_header = nt_headers->OptionalHeader; - - // Extract information from headers - info.machine = static_cast(file_header.Machine); - info.image_characteristics = file_header.Characteristics; - - info.entry_point_rva = optional_header.AddressOfEntryPoint; - info.image_base = optional_header.ImageBase; - info.subsystem = optional_header.Subsystem; - info.subsystem_major_version = optional_header.MajorSubsystemVersion; - info.subsystem_minor_version = optional_header.MinorSubsystemVersion; - info.dll_characteristics = optional_header.DllCharacteristics; - info.size_of_stack_reserve = optional_header.SizeOfStackReserve; - info.size_of_stack_commit = optional_header.SizeOfStackCommit; - info.size_of_code = optional_header.SizeOfCode; - info.loader_flags = optional_header.LoaderFlags; - info.checksum = optional_header.CheckSum; - - // Check if image contains code - info.has_code = (optional_header.SizeOfCode > 0) || (optional_header.AddressOfEntryPoint != 0); - - // Also check section characteristics for code sections - const auto sections_offset = dos_header->e_lfanew + sizeof(uint32_t) + sizeof(PEFileHeader_t) + file_header.SizeOfOptionalHeader; - if (file_data.size() >= sections_offset + sizeof(IMAGE_SECTION_HEADER) * file_header.NumberOfSections) - { - const auto* sections = reinterpret_cast(file_data.data() + sections_offset); - for (uint16_t i = 0; i < file_header.NumberOfSections; ++i) - { - if (sections[i].Characteristics & IMAGE_SCN_CNT_CODE) - { - info.has_code = true; - break; - } - } - } - - return true; - } - NTSTATUS handle_NtCreateSection(const syscall_context& c, const emulator_object section_handle, const ACCESS_MASK /*desired_access*/, const emulator_object>> object_attributes, @@ -141,36 +53,7 @@ namespace syscalls std::vector file_data; if (utils::io::read_file(c.win_emu.file_sys.translate(s.file_name), &file_data)) { - section::image_info info{}; - - // Read the PE magic to determine if it's 32-bit or 64-bit - bool parsed = false; - if (file_data.size() >= sizeof(PEDosHeader_t)) - { - const auto* dos_header = reinterpret_cast(file_data.data()); - if (dos_header->e_magic == PEDosHeader_t::k_Magic && - file_data.size() >= dos_header->e_lfanew + sizeof(uint32_t) + sizeof(PEFileHeader_t) + sizeof(uint16_t)) - { - const auto* magic_ptr = reinterpret_cast(file_data.data() + dos_header->e_lfanew + - sizeof(uint32_t) + sizeof(PEFileHeader_t)); - const uint16_t magic = *magic_ptr; - - // Parse based on the actual PE type - if (magic == PEOptionalHeader_t::k_Magic) - { - parsed = parse_pe_headers(file_data, info); - } - else if (magic == PEOptionalHeader_t::k_Magic) - { - parsed = parse_pe_headers(file_data, info); - } - } - } - - if (parsed) - { - s.cached_image_info = info; - } + s.cache_image_info_from_filedata(file_data); } } @@ -236,10 +119,25 @@ namespace syscalls } utils::string::to_lower_inplace(filename); - + if (is_known_dll) { auto& knowndlls_sections = c.win_emu.process.knowndlls_sections; + + if (filename.starts_with(u"\\knowndlls\\")) + { + filename = std::u16string_view(filename).substr(11, filename.length() - 11); + } + else if (filename.starts_with(u"\\knowndlls32\\")) + { + filename = std::u16string_view(filename).substr(13, filename.length() - 13); + } + + if (filename == u"win32u.dll") + { + return STATUS_OBJECT_NAME_NOT_FOUND; + } + if (!knowndlls_sections.contains(filename)) { return STATUS_OBJECT_NAME_NOT_FOUND; diff --git a/src/windows-emulator/windows_objects.hpp b/src/windows-emulator/windows_objects.hpp index b4db799a..43af154d 100644 --- a/src/windows-emulator/windows_objects.hpp +++ b/src/windows-emulator/windows_objects.hpp @@ -5,6 +5,7 @@ #include #include #include +#include struct timer : ref_counted_object { @@ -220,33 +221,47 @@ struct section : ref_counted_object uint64_t maximum_size{}; uint32_t section_page_protection{}; uint32_t allocation_attributes{}; - - // Cached PE image information for image sections - struct image_info - { - uint64_t entry_point_rva{}; - uint64_t image_base{}; - uint64_t size_of_stack_reserve{}; - uint64_t size_of_stack_commit{}; - uint32_t size_of_code{}; - uint32_t loader_flags{}; - uint32_t checksum{}; - uint16_t machine{}; - uint16_t subsystem{}; - uint16_t subsystem_major_version{}; - uint16_t subsystem_minor_version{}; - uint16_t image_characteristics{}; - uint16_t dll_characteristics{}; - bool has_code{false}; - std::array _padding{}; - }; - std::optional cached_image_info{}; + std::optional cached_image_info{}; bool is_image() const { return this->allocation_attributes & SEC_IMAGE; } + void cache_image_info_from_filedata(const std::vector& file_data) + { + winpe::pe_image_basic_info info{}; + + // Read the PE magic to determine if it's 32-bit or 64-bit + bool parsed = false; + if (file_data.size() >= sizeof(PEDosHeader_t)) + { + const auto* dos_header = reinterpret_cast(file_data.data()); + if (dos_header->e_magic == PEDosHeader_t::k_Magic && + file_data.size() >= dos_header->e_lfanew + sizeof(uint32_t) + sizeof(PEFileHeader_t) + sizeof(uint16_t)) + { + const auto* magic_ptr = + reinterpret_cast(file_data.data() + dos_header->e_lfanew + sizeof(uint32_t) + sizeof(PEFileHeader_t)); + const uint16_t magic = *magic_ptr; + + // Parse based on the actual PE type + if (magic == PEOptionalHeader_t::k_Magic) + { + parsed = winpe::parse_pe_headers(file_data, info); + } + else if (magic == PEOptionalHeader_t::k_Magic) + { + parsed = winpe::parse_pe_headers(file_data, info); + } + } + } + + if (parsed) + { + this->cached_image_info = info; + } + } + void serialize_object(utils::buffer_serializer& buffer) const override { buffer.write(this->name); @@ -254,7 +269,7 @@ struct section : ref_counted_object buffer.write(this->maximum_size); buffer.write(this->section_page_protection); buffer.write(this->allocation_attributes); - buffer.write_optional(this->cached_image_info); + buffer.write_optional(this->cached_image_info); } void deserialize_object(utils::buffer_deserializer& buffer) override