mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-19 03:33:56 +00:00
Add Support for KnownDLLs
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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<uint64_t> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<uint64_t> 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<windows_path, uint64_t> module_load_count;
|
||||
|
||||
// WOW64-specific modules (for validation and future use)
|
||||
struct wow64_modules
|
||||
|
||||
@@ -176,6 +176,61 @@ namespace
|
||||
|
||||
return env_map;
|
||||
}
|
||||
|
||||
void create_known_dlls_section_objects(std::unordered_map<std::u16string, section>& 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<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)
|
||||
{
|
||||
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");
|
||||
|
||||
@@ -129,6 +129,7 @@ struct process_context
|
||||
handle_store<handle_types::timer, timer> timers{};
|
||||
handle_store<handle_types::registry, registry_key, 2> registry_keys{};
|
||||
std::map<uint16_t, atom_entry> atoms{};
|
||||
std::unordered_map<std::u16string, section> knowndlls_sections;
|
||||
|
||||
std::vector<std::byte> default_register_set{};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user