Update module_load_count when unmapping

This commit is contained in:
ahm3dgg
2026-01-13 01:44:36 +02:00
parent 0eae0cac56
commit 0438b7a62b
6 changed files with 83 additions and 40 deletions

View File

@@ -170,6 +170,12 @@ namespace utils::string
return data;
}
template <class Elem, class Traits, class Alloc>
bool equals_ignore_case(const std::basic_string<Elem, Traits, Alloc>& lhs, const std::basic_string_view<Elem, Traits> rhs)
{
return std::ranges::equal(lhs, rhs, [](const auto c1, const auto c2) { return char_to_lower(c1) == char_to_lower(c2); });
}
template <class Elem, class Traits, class Alloc>
bool equals_ignore_case(const std::basic_string<Elem, Traits, Alloc>& lhs, const std::basic_string<Elem, Traits, Alloc>& rhs)
{
@@ -182,6 +188,18 @@ namespace utils::string
return std::ranges::equal(lhs, rhs, [](const auto c1, const auto c2) { return char_to_lower(c1) == char_to_lower(c2); });
}
template <class Elem, class Traits, class Alloc>
bool starts_with_ignore_case(const std::basic_string<Elem, Traits, Alloc>& lhs, const std::basic_string_view<Elem, Traits> rhs)
{
if (lhs.length() < rhs.length())
{
return false;
}
return std::ranges::equal(lhs.substr(0, rhs.length()), rhs,
[](const auto c1, const auto c2) { return char_to_lower(c1) == char_to_lower(c2); });
}
template <class Elem, class Traits, class Alloc>
bool starts_with_ignore_case(const std::basic_string<Elem, Traits, Alloc>& lhs, const std::basic_string<Elem, Traits, Alloc>& rhs)
{
@@ -206,6 +224,19 @@ namespace utils::string
[](const auto c1, const auto c2) { return char_to_lower(c1) == char_to_lower(c2); });
}
template <class Elem, class Traits, class Alloc>
bool ends_with_ignore_case(const std::basic_string<Elem, Traits, Alloc>& lhs, const std::basic_string_view<Elem, Traits>& rhs)
{
if (lhs.length() < rhs.length())
{
return false;
}
auto start = lhs.length() - rhs.length();
return std::ranges::equal(lhs.substr(start, rhs.length()), rhs,
[](const auto c1, const auto c2) { return char_to_lower(c1) == char_to_lower(c2); });
}
template <class Elem, class Traits, class Alloc>
bool ends_with_ignore_case(const std::basic_string<Elem, Traits, Alloc>& lhs, const std::basic_string<Elem, Traits, Alloc>& rhs)
{

View File

@@ -223,7 +223,7 @@ mapped_module* module_manager::map_module_core(const pe_detection_result& detect
if (!mod.path.empty())
{
this->module_load_count[mod.path]++;
this->modules_load_count[mod.path]++;
}
const auto image_base = mod.image_base;
@@ -455,12 +455,12 @@ std::optional<uint64_t> module_manager::get_module_load_count_by_path(const wind
{
auto local_file = std::filesystem::weakly_canonical(std::filesystem::absolute(this->file_sys_->translate(path)));
if (!module_load_count.contains(local_file))
if (!modules_load_count.contains(local_file))
{
return {};
}
return module_load_count[local_file];
return modules_load_count[local_file];
}
mapped_module* module_manager::map_module(const windows_path& file, const logger& logger, const bool is_static, bool allow_duplicate)
@@ -538,7 +538,7 @@ mapped_module* module_manager::map_memory_module(uint64_t base_address, uint64_t
void module_manager::serialize(utils::buffer_serializer& buffer) const
{
buffer.write_map(this->modules_);
buffer.write_map(this->module_load_count);
buffer.write_map(this->modules_load_count);
buffer.write(this->executable ? this->executable->image_base : 0);
buffer.write(this->ntdll ? this->ntdll->image_base : 0);
@@ -556,7 +556,7 @@ void module_manager::serialize(utils::buffer_serializer& buffer) const
void module_manager::deserialize(utils::buffer_deserializer& buffer)
{
buffer.read_map(this->modules_);
buffer.read_map(this->module_load_count);
buffer.read_map(this->modules_load_count);
this->last_module_cache_ = this->modules_.end();
const auto executable_base = buffer.read<uint64_t>();
@@ -595,6 +595,17 @@ bool module_manager::unmap(const uint64_t address)
this->callbacks_->on_module_unload(mod->second);
unmap_module(*this->memory_, mod->second);
auto module_load_count = this->modules_load_count[mod->second.path] - 1;
if (module_load_count == 0)
{
this->modules_load_count.erase(mod->second.path);
}
else
{
this->modules_load_count[mod->second.path] = module_load_count;
}
this->modules_.erase(mod);
this->last_module_cache_ = this->modules_.end();

View File

@@ -159,7 +159,7 @@ class module_manager
mapped_module* executable{};
mapped_module* ntdll{};
mapped_module* win32u{};
std::map<std::filesystem::path, uint64_t> module_load_count;
std::map<std::filesystem::path, uint64_t> modules_load_count;
// WOW64-specific modules (for validation and future use)
struct wow64_modules

View File

@@ -3,8 +3,9 @@
#include "emulator_utils.hpp"
#include "windows_emulator.hpp"
#include "utils/io.hpp"
#include "utils/buffer_accessor.hpp"
#include <utils/io.hpp>
#include <utils/buffer_accessor.hpp>
namespace
{
@@ -205,9 +206,9 @@ namespace
return 0;
}
std::unordered_map<std::u16string, std::u16string> get_apiset_namespace_table(const API_SET_NAMESPACE* api_set_map)
apiset_map get_apiset_namespace_table(const API_SET_NAMESPACE* api_set_map)
{
std::unordered_map<std::u16string, std::u16string> apiset;
apiset_map apiset;
for (size_t i = 0; i < api_set_map->Count; i++)
{
@@ -580,6 +581,7 @@ void process_context::serialize(utils::buffer_serializer& buffer) const
buffer.write(this->timers);
buffer.write(this->registry_keys);
buffer.write_map(this->atoms);
buffer.write_map(this->apiset);
buffer.write_map(this->knowndlls32_sections);
buffer.write_map(this->knowndlls64_sections);
@@ -633,6 +635,7 @@ void process_context::deserialize(utils::buffer_deserializer& buffer)
buffer.read(this->timers);
buffer.read(this->registry_keys);
buffer.read_map(this->atoms);
buffer.read_map(this->apiset);
buffer.read_map(this->knowndlls32_sections);
buffer.read_map(this->knowndlls64_sections);
@@ -814,7 +817,6 @@ void process_context::build_knowndlls_section_table(registry_manager& registry,
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;
@@ -838,7 +840,7 @@ void process_context::build_knowndlls_section_table(registry_manager& registry,
auto known_dll_name = std::u16string(data_ptr, char_count - 1);
auto known_dll_path = system_root_path / known_dll_name;
auto local_known_dll_path = local_system_root_path / known_dll_name;
auto local_known_dll_path = file_system.translate(system_root_path / known_dll_name);
if (!std::filesystem::exists(local_known_dll_path))
{
@@ -884,16 +886,14 @@ void process_context::build_knowndlls_section_table(registry_manager& registry,
break;
}
auto known_dll_dep_name =
buffer.as_string(static_cast<size_t>(rva_to_file_offset(import_directory_vbase, import_directory_rbase, descriptor.Name)));
auto known_dll_dep_name = u8_to_u16(
buffer.as_string(static_cast<size_t>(rva_to_file_offset(import_directory_vbase, import_directory_rbase, descriptor.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 (known_dll_dep_name.starts_with(u"api-") || known_dll_dep_name.starts_with(u"ext-"))
{
if (this->apiset.contains(known_dll_dep_name_16))
if (this->apiset.contains(known_dll_dep_name))
{
known_dll_dep_name_16 = apiset[known_dll_dep_name_16];
known_dll_dep_name = apiset[known_dll_dep_name];
}
else
{
@@ -901,14 +901,14 @@ void process_context::build_knowndlls_section_table(registry_manager& registry,
}
}
if (is_knowndll_section_exists(known_dll_dep_name_16, is_32bit))
if (is_knowndll_section_exists(known_dll_dep_name, is_32bit))
{
continue;
}
{
auto local_known_dll_dep_path = local_system_root_path / known_dll_dep_name_16;
auto known_dll_dep_path = system_root_path / known_dll_dep_name_16;
auto known_dll_dep_path = system_root_path / known_dll_dep_name;
auto local_known_dll_dep_path = file_system.translate(system_root_path / known_dll_dep_name);
auto known_dll_dep_file = utils::io::read_file(local_known_dll_dep_path);
section s;
@@ -917,7 +917,7 @@ void process_context::build_knowndlls_section_table(registry_manager& registry,
s.allocation_attributes = SEC_IMAGE;
s.section_page_protection = PAGE_EXECUTE;
s.cache_image_info_from_filedata(known_dll_dep_file);
this->add_knowndll_section(known_dll_dep_name_16, s, is_32bit);
this->add_knowndll_section(known_dll_dep_name, s, is_32bit);
}
}
}

View File

@@ -35,7 +35,7 @@ struct emulator_settings;
struct application_settings;
using knowndlls_map = std::map<std::u16string, section>;
using apiset_map = std::unordered_map<std::u16string, std::u16string>;
using apiset_map = std::map<std::u16string, std::u16string>;
struct process_context
{
struct callbacks

View File

@@ -72,10 +72,9 @@ namespace syscalls
const auto attributes = object_attributes.read();
auto filename = read_unicode_string(c.emu, attributes.ObjectName);
auto filename_sv = std::u16string_view(filename);
c.win_emu.callbacks.on_generic_access("Opening section", filename);
if (utils::string::equals_ignore_case(filename_sv, u"\\Windows\\SharedSection"sv))
if (utils::string::equals_ignore_case(filename, u"\\Windows\\SharedSection"sv))
{
constexpr auto shared_section_size = 0x10000;
@@ -89,7 +88,7 @@ namespace syscalls
return STATUS_SUCCESS;
}
if (utils::string::equals_ignore_case(filename_sv, u"DBWIN_BUFFER"sv))
if (utils::string::equals_ignore_case(filename, u"DBWIN_BUFFER"sv))
{
constexpr auto dbwin_buffer_section_size = 0x1000;
@@ -103,18 +102,18 @@ namespace syscalls
return STATUS_SUCCESS;
}
if (utils::string::equals_ignore_case(filename_sv, u"windows_shell_global_counters"sv) ||
utils::string::equals_ignore_case(filename_sv, u"Global\\__ComCatalogCache__"sv) ||
utils::string::equals_ignore_case(filename_sv, u"{00020000-0000-1005-8005-0000C06B5161}"sv) ||
utils::string::equals_ignore_case(filename_sv, u"Global\\{00020000-0000-1005-8005-0000C06B5161}"sv))
if (utils::string::equals_ignore_case(filename, u"windows_shell_global_counters"sv) ||
utils::string::equals_ignore_case(filename, u"Global\\__ComCatalogCache__"sv) ||
utils::string::equals_ignore_case(filename, u"{00020000-0000-1005-8005-0000C06B5161}"sv) ||
utils::string::equals_ignore_case(filename, u"Global\\{00020000-0000-1005-8005-0000C06B5161}"sv))
{
return STATUS_NOT_SUPPORTED;
}
bool is_knowndll = (attributes.RootDirectory == KNOWN_DLLS32_DIRECTORY ||
utils::string::starts_with_ignore_case(filename_sv, u"\\KnownDlls32\\"sv)) ||
utils::string::starts_with_ignore_case(filename, u"\\KnownDlls32\\"sv)) ||
attributes.RootDirectory == KNOWN_DLLS_DIRECTORY ||
utils::string::starts_with_ignore_case(filename_sv, u"\\KnownDlls\\"sv);
utils::string::starts_with_ignore_case(filename, u"\\KnownDlls\\"sv);
if (!is_knowndll && attributes.RootDirectory != BASE_NAMED_OBJECTS_DIRECTORY)
{
@@ -126,19 +125,21 @@ namespace syscalls
if (is_knowndll)
{
bool is_knowndll32 = attributes.RootDirectory == KNOWN_DLLS32_DIRECTORY ||
utils::string::starts_with_ignore_case(filename_sv, u"\\KnownDlls32"sv);
utils::string::starts_with_ignore_case(filename, u"\\KnownDlls32\\"sv);
if (utils::string::starts_with_ignore_case(filename_sv, u"\\KnownDlls32\\"sv))
std::u16string knowndll_name = filename;
if (utils::string::starts_with_ignore_case(filename, u"\\KnownDlls32\\"sv))
{
filename = filename_sv.substr(13, filename.length() - 13);
knowndll_name = filename.substr(13, filename.length() - 13);
}
else if (utils::string::starts_with_ignore_case(filename_sv, u"\\KnownDlls\\"sv))
else if (utils::string::starts_with_ignore_case(filename, u"\\KnownDlls\\"sv))
{
filename = filename_sv.substr(11, filename.length() - 11);
knowndll_name = filename.substr(11, filename.length() - 11);
}
auto section = c.win_emu.process.get_knowndll_section_by_name(filename, is_knowndll32);
auto section = c.win_emu.process.get_knowndll_section_by_name(knowndll_name, is_knowndll32);
if (!section.has_value())
{
return STATUS_OBJECT_NAME_NOT_FOUND;
@@ -150,7 +151,7 @@ namespace syscalls
for (auto& [handle, section] : c.proc.sections)
{
if (section.is_image() && utils::string::equals_ignore_case(section.file_name, filename))
if (section.is_image() && utils::string::equals_ignore_case(section.name, filename))
{
section_handle.write(c.proc.sections.make_handle(handle));
return STATUS_SUCCESS;