Support for KnownDLLs and Some Refactoring

This commit is contained in:
ahm3dgg
2026-01-07 07:34:34 +02:00
parent 67e130a3b8
commit f54bc3467f
8 changed files with 371 additions and 200 deletions

View File

@@ -6,6 +6,8 @@
#include <fstream>
#include <system_error>
#include <variant>
#include <array>
#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<char, 7> _padding{};
};
enum class pe_arch
{
pe32,
pe64
};
template <typename T>
inline uint64_t get_first_section_offset(const PENTHeaders_t<T>& nt_headers, const uint64_t nt_headers_offset)
{
const auto* nt_headers_addr = reinterpret_cast<const uint8_t*>(&nt_headers);
const size_t optional_header_offset =
reinterpret_cast<uintptr_t>(&(nt_headers.OptionalHeader)) - reinterpret_cast<uintptr_t>(&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<uint64_t>(first_section_addr);
const auto absolute_base = reinterpret_cast<uint64_t>(&nt_headers);
return nt_headers_offset + (first_section_absolute - absolute_base);
}
template <typename T>
inline PEDirectory_t2 get_data_directory_by_index(const PENTHeaders_t<T>& nt_headers, uint64_t directory_index)
{
return nt_headers.OptionalHeader.DataDirectory[directory_index];
}
template <typename T>
IMAGE_SECTION_HEADER get_section_header_by_rva(const utils::safe_buffer_accessor<const std::byte>& buffer, const PENTHeaders_t<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<IMAGE_SECTION_HEADER>(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<pe_arch, std::error_code> 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 <typename T>
inline bool parse_pe_headers(const std::vector<std::byte>& file_data, pe_image_basic_info& info)
{
if (file_data.size() < sizeof(PEDosHeader_t))
{
return false;
}
const auto* dos_header = reinterpret_cast<const PEDosHeader_t*>(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<const uint16_t*>(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<uint16_t>(PEOptionalHeader_t<std::uint32_t>::k_Magic)
: static_cast<uint16_t>(PEOptionalHeader_t<std::uint64_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<T>))
{
return false;
}
const auto* nt_headers = reinterpret_cast<const PENTHeaders_t<T>*>(file_data.data() + dos_header->e_lfanew);
if (nt_headers->Signature != PENTHeaders_t<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<uint16_t>(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<const IMAGE_SECTION_HEADER*>(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)

View File

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

View File

@@ -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<const std::byte*>(api_set_map);

View File

@@ -3,6 +3,7 @@
#include <vector>
#include <cstdint>
#include <filesystem>
#include <optional>
#include "../emulator_utils.hpp"
@@ -33,4 +34,4 @@ namespace apiset
const API_SET_NAMESPACE& orig_api_set_map);
emulator_object<API_SET_NAMESPACE> clone(x86_64_emulator& emu, emulator_allocator& allocator, const container& container);
}
}

View File

@@ -4,23 +4,10 @@
#include <utils/io.hpp>
#include <utils/buffer_accessor.hpp>
#include <platform/win_pefile.hpp>
namespace
{
template <typename T>
uint64_t get_first_section_offset(const PENTHeaders_t<T>& nt_headers, const uint64_t nt_headers_offset)
{
const auto* nt_headers_addr = reinterpret_cast<const uint8_t*>(&nt_headers);
const size_t optional_header_offset =
reinterpret_cast<uintptr_t>(&(nt_headers.OptionalHeader)) - reinterpret_cast<uintptr_t>(&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<uint64_t>(first_section_addr);
const auto absolute_base = reinterpret_cast<uint64_t>(&nt_headers);
return nt_headers_offset + (first_section_absolute - absolute_base);
}
template <typename T>
std::vector<std::byte> 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<const std::byte> buffer,
const PENTHeaders_t<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<IMAGE_SECTION_HEADER>(static_cast<size_t>(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<IMAGE_SECTION_HEADER>(static_cast<size_t>(section_offset));
for (size_t i = 0; i < nt_headers.FileHeader.NumberOfSections; ++i)

View File

@@ -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<std::u16string, section>& knowndlls_sections, const file_system& file_system,
bool is_wow64)
std::unordered_map<std::u16string, std::u16string> 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<std::u16string, std::u16string> apiset;
for (size_t i = 0; i < api_set_map->Count; i++)
{
const auto entry = reinterpret_cast<PAPI_SET_NAMESPACE_ENTRY>(reinterpret_cast<ULONG_PTR>(api_set_map) +
api_set_map->EntryOffset + i * sizeof(API_SET_NAMESPACE_ENTRY));
std::u16string name(reinterpret_cast<const char16_t*>(reinterpret_cast<ULONG_PTR>(api_set_map) + entry->NameOffset),
entry->NameLength / sizeof(char16_t));
const auto value = reinterpret_cast<PAPI_SET_VALUE_ENTRY>(reinterpret_cast<ULONG_PTR>(api_set_map) + entry->ValueOffset +
(entry->ValueCount - 1) * sizeof(API_SET_VALUE_ENTRY));
std::u16string base_name(reinterpret_cast<const char16_t*>(reinterpret_cast<ULONG_PTR>(api_set_map) + value->ValueOffset),
value->ValueLength / sizeof(char16_t));
apiset[name + u".dll"] = base_name;
}
return apiset;
}
template <typename T>
void create_known_dlls_section_objects(
std::unordered_map<std::u16string, section>& 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<const API_SET_NAMESPACE*>(apiset_container.data.data());
auto apiset = get_apiset_namespace_table(api_set_data);
std::unordered_set<std::u16string> 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<std::u16string> 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<registry_key> 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<const char16_t*>(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<const std::byte> buffer{file};
const auto dos_header = buffer.as<PEDosHeader_t>(0).get();
const auto nt_headers_offset = dos_header.e_lfanew;
const auto nt_headers = buffer.as<PENTHeaders_t<T>>(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<IMAGE_IMPORT_DESCRIPTOR>(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<uint32_t>(this->knowndlls_sections, registry, apiset_container, file_system, is_wow64_process);
}
else
{
create_known_dlls_section_objects<uint64_t>(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");

View File

@@ -7,94 +7,6 @@
namespace syscalls
{
// Helper function to parse PE headers and extract image information
template <typename T>
static bool parse_pe_headers(const std::vector<std::byte>& file_data, section::image_info& info)
{
if (file_data.size() < sizeof(PEDosHeader_t))
{
return false;
}
const auto* dos_header = reinterpret_cast<const PEDosHeader_t*>(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<const uint16_t*>(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<uint16_t>(PEOptionalHeader_t<std::uint32_t>::k_Magic)
: static_cast<uint16_t>(PEOptionalHeader_t<std::uint64_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<T>))
{
return false;
}
const auto* nt_headers = reinterpret_cast<const PENTHeaders_t<T>*>(file_data.data() + dos_header->e_lfanew);
if (nt_headers->Signature != PENTHeaders_t<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<uint16_t>(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<const IMAGE_SECTION_HEADER*>(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<handle> section_handle,
const ACCESS_MASK /*desired_access*/,
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
@@ -141,36 +53,7 @@ namespace syscalls
std::vector<std::byte> 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<const PEDosHeader_t*>(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<const uint16_t*>(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<std::uint32_t>::k_Magic)
{
parsed = parse_pe_headers<uint32_t>(file_data, info);
}
else if (magic == PEOptionalHeader_t<std::uint64_t>::k_Magic)
{
parsed = parse_pe_headers<uint64_t>(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;

View File

@@ -5,6 +5,7 @@
#include <serialization_helper.hpp>
#include <utils/file_handle.hpp>
#include <platform/synchronisation.hpp>
#include <platform/win_pefile.hpp>
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<char, 7> _padding{};
};
std::optional<image_info> cached_image_info{};
std::optional<winpe::pe_image_basic_info> cached_image_info{};
bool is_image() const
{
return this->allocation_attributes & SEC_IMAGE;
}
void cache_image_info_from_filedata(const std::vector<std::byte>& 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<const PEDosHeader_t*>(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<const uint16_t*>(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<std::uint32_t>::k_Magic)
{
parsed = winpe::parse_pe_headers<uint32_t>(file_data, info);
}
else if (magic == PEOptionalHeader_t<std::uint64_t>::k_Magic)
{
parsed = winpe::parse_pe_headers<uint64_t>(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<image_info>(this->cached_image_info);
buffer.write_optional<winpe::pe_image_basic_info>(this->cached_image_info);
}
void deserialize_object(utils::buffer_deserializer& buffer) override