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

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