minidump support: dump loading and process reconstruction

This commit is contained in:
redthing1
2025-06-09 23:12:45 -07:00
parent 906cec808a
commit 5d9dd122d2
14 changed files with 914 additions and 6 deletions

View File

@@ -139,6 +139,41 @@ mapped_module* module_manager::map_local_module(const std::filesystem::path& fil
}
}
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)
{
for (auto& mod : this->modules_ | std::views::values)
{
if (mod.image_base == base_address)
{
return &mod;
}
}
try
{
auto mod = ::map_module_from_memory(*this->memory_, base_address, image_size, module_name);
mod.is_static = is_static;
const auto image_base = mod.image_base;
const auto entry = this->modules_.try_emplace(image_base, std::move(mod));
this->callbacks_->on_module_load(entry.first->second);
return &entry.first->second;
}
catch (const std::exception& e)
{
logger.error("Failed to map module from memory %s at 0x%016llX: %s\n", module_name.c_str(), base_address,
e.what());
return nullptr;
}
catch (...)
{
logger.error("Failed to map module from memory %s at 0x%016llX: Unknown error\n", module_name.c_str(),
base_address);
return nullptr;
}
}
void module_manager::serialize(utils::buffer_serializer& buffer) const
{
buffer.write_map(this->modules_);

View File

@@ -25,6 +25,8 @@ class module_manager
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);
mapped_module* find_by_address(const uint64_t address)
{

View File

@@ -265,6 +265,69 @@ mapped_module map_module_from_file(memory_manager& memory, std::filesystem::path
return map_module_from_data(memory, data, std::move(file));
}
mapped_module map_module_from_memory(memory_manager& memory, uint64_t base_address, uint64_t image_size,
const std::string& module_name)
{
mapped_module binary{};
binary.name = module_name;
binary.path = module_name;
binary.image_base = base_address;
binary.size_of_image = image_size;
auto mapped_memory = read_mapped_memory(memory, binary);
utils::safe_buffer_accessor<const std::byte> buffer{mapped_memory};
try
{
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<std::uint64_t>>(nt_headers_offset).get();
const auto& optional_header = nt_headers.OptionalHeader;
binary.entry_point = binary.image_base + optional_header.AddressOfEntryPoint;
const auto section_offset = get_first_section_offset(nt_headers, nt_headers_offset);
const auto sections = buffer.as<IMAGE_SECTION_HEADER>(section_offset);
for (size_t i = 0; i < nt_headers.FileHeader.NumberOfSections; ++i)
{
const auto section = sections.get(i);
mapped_section section_info{};
section_info.region.start = binary.image_base + section.VirtualAddress;
section_info.region.length =
static_cast<size_t>(page_align_up(std::max(section.SizeOfRawData, section.Misc.VirtualSize)));
auto permissions = memory_permission::none;
if (section.Characteristics & IMAGE_SCN_MEM_EXECUTE)
permissions |= memory_permission::exec;
if (section.Characteristics & IMAGE_SCN_MEM_READ)
permissions |= memory_permission::read;
if (section.Characteristics & IMAGE_SCN_MEM_WRITE)
permissions |= memory_permission::write;
section_info.region.permissions = permissions;
for (size_t j = 0; j < sizeof(section.Name) && section.Name[j]; ++j)
{
section_info.name.push_back(static_cast<char>(section.Name[j]));
}
binary.sections.push_back(std::move(section_info));
}
collect_exports(binary, buffer, optional_header);
}
catch (const std::exception&)
{
// bad!
throw std::runtime_error("Failed to map module from memory at " + std::to_string(base_address) + " with size " +
std::to_string(image_size) + " for module " + module_name);
}
return binary;
}
bool unmap_module(memory_manager& memory, const mapped_module& mod)
{
return memory.release_memory(mod.image_base, static_cast<size_t>(mod.size_of_image));

View File

@@ -5,5 +5,7 @@
mapped_module map_module_from_data(memory_manager& memory, std::span<const uint8_t> data, std::filesystem::path file);
mapped_module map_module_from_file(memory_manager& memory, std::filesystem::path file);
mapped_module map_module_from_memory(memory_manager& memory, uint64_t base_address, uint64_t image_size,
const std::string& module_name);
bool unmap_module(memory_manager& memory, const mapped_module& mod);