diff --git a/src/analyzer/analysis.cpp b/src/analyzer/analysis.cpp index 5b538d2f..aa13dc7f 100644 --- a/src/analyzer/analysis.cpp +++ b/src/analyzer/analysis.cpp @@ -209,54 +209,6 @@ namespace } } - bool is_thread_alive(const analysis_context& c, const uint32_t thread_id) - { - for (const auto& t : c.win_emu->process.threads | std::views::values) - { - if (t.id == thread_id) - { - return true; - } - } - - return false; - } - - void update_import_access(analysis_context& c, const uint64_t address) - { - if (c.accessed_imports.empty()) - { - return; - } - - const auto& t = c.win_emu->current_thread(); - for (auto entry = c.accessed_imports.begin(); entry != c.accessed_imports.end();) - { - auto& a = *entry; - const auto is_same_thread = t.id == a.thread_id; - - if (is_same_thread && address == a.address) - { - entry = c.accessed_imports.erase(entry); - continue; - } - - constexpr auto inst_delay = 100u; - const auto execution_delay_reached = is_same_thread && a.access_inst_count + inst_delay <= t.executed_instructions; - - if (!execution_delay_reached && is_thread_alive(c, a.thread_id)) - { - ++entry; - continue; - } - - c.win_emu->log.print(color::green, "Import read access without execution: %s (%s) at 0x%" PRIx64 " (%s)\n", - a.import_name.c_str(), a.import_module.c_str(), a.access_rip, a.accessor_module.c_str()); - - entry = c.accessed_imports.erase(entry); - } - } - bool is_return(const disassembler& d, const emulator& emu, const uint64_t address) { std::array instruction_bytes{}; @@ -297,7 +249,6 @@ namespace void handle_instruction(analysis_context& c, const uint64_t address) { auto& win_emu = *c.win_emu; - update_import_access(c, address); #if defined(OS_EMSCRIPTEN) && !defined(MOMO_EMSCRIPTEN_SUPPORT_NODEJS) if ((win_emu.get_executed_instructions() % 0x20000) == 0) @@ -501,52 +452,33 @@ namespace auto min = std::numeric_limits::max(); auto max = std::numeric_limits::min(); - for (const auto& imports : import_list | std::views::values) + for (const auto& import_thunk : import_list | std::views::keys) { - for (const auto& import : imports) - { - min = std::min(import.address, min); - max = std::max(import.address, max); - } + min = std::min(import_thunk, min); + max = std::max(import_thunk, max); } c.win_emu->emu().hook_memory_read(min, max - min, [&c](const uint64_t address, const void*, size_t) { - const auto& import_list = c.win_emu->mod_manager.executable->imports; + const auto& watched_module = *c.win_emu->mod_manager.executable; + const auto& accessor_module = *c.win_emu->mod_manager.executable; const auto rip = c.win_emu->emu().read_instruction_pointer(); - if (!c.win_emu->mod_manager.executable->contains(rip)) + + if (!accessor_module.contains(rip)) { return; } - for (const auto& [module_name, imports] : import_list) + const auto sym = watched_module.imports.find(address); + if (sym == watched_module.imports.end()) { - for (const auto& import : imports) - { - if (address != import.address) - { - continue; - } - - accessed_import access{}; - - access.address = c.win_emu->emu().read_memory(address); - - access.access_rip = c.win_emu->emu().read_instruction_pointer(); - access.accessor_module = c.win_emu->mod_manager.find_name(access.access_rip); - - access.import_name = import.name; - access.import_module = module_name; - - const auto& t = c.win_emu->current_thread(); - access.thread_id = t.id; - access.access_inst_count = t.executed_instructions; - - c.accessed_imports.push_back(std::move(access)); - - return; - } + return; } + + const auto& module_name = watched_module.imported_modules[sym->second.module_index]; + + c.win_emu->log.print(color::green, "Import read access: %s (%s) at 0x%" PRIx64 " (%s)\n", sym->second.name.c_str(), + module_name.c_str(), rip, accessor_module.name.c_str()); }); } } diff --git a/src/analyzer/analysis.hpp b/src/analyzer/analysis.hpp index 388e2ed6..a5140b0b 100644 --- a/src/analyzer/analysis.hpp +++ b/src/analyzer/analysis.hpp @@ -22,17 +22,6 @@ struct analysis_settings string_set ignored_functions{}; }; -struct accessed_import -{ - uint64_t address{}; - uint32_t thread_id{}; - uint64_t access_rip{}; - uint64_t access_inst_count{}; - std::string accessor_module{}; - std::string import_name{}; - std::string import_module{}; -}; - struct analysis_context { const analysis_settings* settings{}; @@ -43,7 +32,6 @@ struct analysis_context disassembler d{}; std::unordered_map instructions{}; - std::vector accessed_imports{}; std::set rdtsc_cache{}; std::set rdtscp_cache{}; std::set> cpuid_cache{}; diff --git a/src/windows-emulator/module/mapped_module.hpp b/src/windows-emulator/module/mapped_module.hpp index 2cb8a7ad..aaabaee8 100644 --- a/src/windows-emulator/module/mapped_module.hpp +++ b/src/windows-emulator/module/mapped_module.hpp @@ -12,11 +12,12 @@ struct exported_symbol struct imported_symbol { std::string name{}; - uint64_t address{}; + size_t module_index{}; }; using exported_symbols = std::vector; -using imported_symbols = std::map>; +using imported_symbols = std::unordered_map; +using imported_module_list = std::vector; using address_name_mapping = std::map; struct mapped_section @@ -36,6 +37,7 @@ struct mapped_module exported_symbols exports{}; imported_symbols imports{}; + imported_module_list imported_modules{}; address_name_mapping address_names{}; std::vector sections{}; diff --git a/src/windows-emulator/module/module_mapping.cpp b/src/windows-emulator/module/module_mapping.cpp index 6fa298f1..95e2958c 100644 --- a/src/windows-emulator/module/module_mapping.cpp +++ b/src/windows-emulator/module/module_mapping.cpp @@ -48,8 +48,8 @@ namespace break; } - const auto module_name = buffer.as_string(descriptor.Name); - auto& imports = binary.imports[module_name]; + const auto module_index = binary.imported_modules.size(); + binary.imported_modules.push_back(buffer.as_string(descriptor.Name)); auto original_thunk_data = buffer.as(descriptor.FirstThunk); if (descriptor.OriginalFirstThunk) @@ -65,11 +65,12 @@ namespace break; } - imported_symbol sym{}; - static_assert(sizeof(IMAGE_THUNK_DATA64) == sizeof(uint64_t)); const auto thunk_rva = descriptor.FirstThunk + sizeof(IMAGE_THUNK_DATA64) * j; - sym.address = thunk_rva + binary.image_base; + const auto thunk_address = thunk_rva + binary.image_base; + + auto& sym = binary.imports[thunk_address]; + sym.module_index = module_index; if (IMAGE_SNAP_BY_ORDINAL64(original_thunk.u1.Ordinal)) { @@ -80,8 +81,6 @@ namespace sym.name = buffer.as_string(static_cast(original_thunk.u1.AddressOfData + offsetof(IMAGE_IMPORT_BY_NAME, Name))); } - - imports.push_back(std::move(sym)); } } }