From 73b15557e859b1d5d52bd6cc2cebb7b1fb90003b Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 9 Sep 2024 12:14:22 +0200 Subject: [PATCH] Cleanup gdb stub and module mapping --- src/emulator/scoped_hook.hpp | 54 ++++ .../{ => debugging}/gdb_stub.cpp | 2 +- .../{ => debugging}/gdb_stub.hpp | 0 .../debugging/x64_gdb_stub_handler.hpp | 215 +++++++++++++ src/windows_emulator/main.cpp | 304 +----------------- src/windows_emulator/module/mapped_module.hpp | 25 ++ .../module/module_manager.cpp | 21 ++ .../module/module_manager.hpp | 46 +++ .../module_mapping.cpp} | 98 +++--- .../module/module_mapping.hpp | 10 + src/windows_emulator/module_mapper.hpp | 6 - src/windows_emulator/process_context.hpp | 27 +- src/windows_emulator/syscalls.cpp | 3 +- 13 files changed, 437 insertions(+), 374 deletions(-) create mode 100644 src/emulator/scoped_hook.hpp rename src/windows_emulator/{ => debugging}/gdb_stub.cpp (98%) rename src/windows_emulator/{ => debugging}/gdb_stub.hpp (100%) create mode 100644 src/windows_emulator/debugging/x64_gdb_stub_handler.hpp create mode 100644 src/windows_emulator/module/mapped_module.hpp create mode 100644 src/windows_emulator/module/module_manager.cpp create mode 100644 src/windows_emulator/module/module_manager.hpp rename src/windows_emulator/{module_mapper.cpp => module/module_mapping.cpp} (67%) create mode 100644 src/windows_emulator/module/module_mapping.hpp delete mode 100644 src/windows_emulator/module_mapper.hpp diff --git a/src/emulator/scoped_hook.hpp b/src/emulator/scoped_hook.hpp new file mode 100644 index 0000000..610c57e --- /dev/null +++ b/src/emulator/scoped_hook.hpp @@ -0,0 +1,54 @@ +#pragma once +#include "emulator.hpp" + +class scoped_hook +{ +public: + scoped_hook() = default; + + scoped_hook(emulator& emu, emulator_hook* hook) + : emu_(&emu) + , hook_(hook) + { + } + + ~scoped_hook() + { + this->remove(); + } + + scoped_hook(const scoped_hook&) = delete; + scoped_hook& operator=(const scoped_hook&) = delete; + + scoped_hook(scoped_hook&& obj) noexcept + { + this->operator=(std::move(obj)); + } + + scoped_hook& operator=(scoped_hook&& obj) noexcept + { + if (this != &obj) + { + this->remove(); + this->emu_ = obj.emu_; + this->hook_ = obj.hook_; + + obj.hook_ = {}; + } + + return *this; + } + + void remove() + { + if (this->hook_) + { + this->emu_->delete_hook(this->hook_); + this->hook_ = {}; + } + } + +private: + emulator* emu_{}; + emulator_hook* hook_{}; +}; diff --git a/src/windows_emulator/gdb_stub.cpp b/src/windows_emulator/debugging/gdb_stub.cpp similarity index 98% rename from src/windows_emulator/gdb_stub.cpp rename to src/windows_emulator/debugging/gdb_stub.cpp index 9af1651..7d1d2fc 100644 --- a/src/windows_emulator/gdb_stub.cpp +++ b/src/windows_emulator/debugging/gdb_stub.cpp @@ -1,4 +1,4 @@ -#include "std_include.hpp" +#include "../std_include.hpp" #include "gdb_stub.hpp" #include diff --git a/src/windows_emulator/gdb_stub.hpp b/src/windows_emulator/debugging/gdb_stub.hpp similarity index 100% rename from src/windows_emulator/gdb_stub.hpp rename to src/windows_emulator/debugging/gdb_stub.hpp diff --git a/src/windows_emulator/debugging/x64_gdb_stub_handler.hpp b/src/windows_emulator/debugging/x64_gdb_stub_handler.hpp new file mode 100644 index 0000000..9279bf3 --- /dev/null +++ b/src/windows_emulator/debugging/x64_gdb_stub_handler.hpp @@ -0,0 +1,215 @@ +#pragma once +#include +#include "gdb_stub.hpp" +#include "scoped_hook.hpp" + +inline std::vector gdb_registers{ + x64_register::rax, + x64_register::rbx, + x64_register::rcx, + x64_register::rdx, + x64_register::rsi, + x64_register::rdi, + x64_register::rbp, + x64_register::rsp, + x64_register::r8, + x64_register::r9, + x64_register::r10, + x64_register::r11, + x64_register::r12, + x64_register::r13, + x64_register::r14, + x64_register::r15, + x64_register::rip, + x64_register::rflags, + /*x64_register::cs, + x64_register::ss, + x64_register::ds, + x64_register::es, + x64_register::fs, + x64_register::gs,*/ +}; + +inline memory_operation map_breakpoint_type(const breakpoint_type type) +{ + switch (type) + { + case breakpoint_type::software: + case breakpoint_type::hardware_exec: + return memory_operation::exec; + case breakpoint_type::hardware_read: + return memory_permission::read; + case breakpoint_type::hardware_write: + return memory_permission::write; + case breakpoint_type::hardware_read_write: + return memory_permission::read_write; + default: + throw std::runtime_error("Bad bp type"); + } +} + +struct breakpoint_key +{ + size_t addr{}; + size_t size{}; + breakpoint_type type{}; + + bool operator==(const breakpoint_key& other) const + { + return this->addr == other.addr && this->size == other.size && this->type == other.type; + } +}; + +template <> +struct std::hash +{ + std::size_t operator()(const breakpoint_key& k) const noexcept + { + return ((std::hash()(k.addr) + ^ (std::hash()(k.size) << 1)) >> 1) + ^ (std::hash()(static_cast(k.type)) << 1); + } +}; + +class x64_gdb_stub_handler : public gdb_stub_handler +{ +public: + x64_gdb_stub_handler(x64_emulator& emu) + : emu_(&emu) + { + } + + ~x64_gdb_stub_handler() override = default; + + gdb_action cont() override + { + try + { + this->emu_->start_from_ip(); + } + catch (const std::exception& e) + { + puts(e.what()); + } + + return gdb_action::resume; + } + + gdb_action stepi() override + { + try + { + this->emu_->start_from_ip({}, 1); + } + catch (const std::exception& e) + { + puts(e.what()); + } + + return gdb_action::resume; + } + + bool read_reg(const int regno, size_t* value) override + { + *value = 0; + + try + { + if (static_cast(regno) >= gdb_registers.size()) + { + return true; + } + + this->emu_->read_register(gdb_registers[regno], value, sizeof(*value)); + return true; + } + catch (...) + { + return true; + } + } + + bool write_reg(const int regno, const size_t value) override + { + try + { + if (static_cast(regno) >= gdb_registers.size()) + { + return true; + } + + this->emu_->write_register(gdb_registers[regno], &value, sizeof(value)); + return true; + } + catch (...) + { + return false; + } + } + + bool read_mem(const size_t addr, const size_t len, void* val) override + { + return this->emu_->try_read_memory(addr, val, len); + } + + bool write_mem(const size_t addr, const size_t len, void* val) override + { + try + { + this->emu_->write_memory(addr, val, len); + return true; + } + catch (...) + { + return false; + } + } + + bool set_bp(const breakpoint_type type, const size_t addr, const size_t size) override + { + try + { + this->hooks_[{addr, size, type}] = scoped_hook(*this->emu_, this->emu_->hook_memory_access( + addr, size, map_breakpoint_type(type), + [this](uint64_t, size_t, memory_operation) + { + this->on_interrupt(); + })); + + return true; + } + catch (...) + { + return false; + } + } + + bool del_bp(const breakpoint_type type, const size_t addr, const size_t size) override + { + try + { + const auto entry = this->hooks_.find({addr, size, type}); + if (entry == this->hooks_.end()) + { + return false; + } + + this->hooks_.erase(entry); + + return true; + } + catch (...) + { + return false; + } + } + + void on_interrupt() override + { + this->emu_->stop(); + } + +private: + x64_emulator* emu_{}; + std::unordered_map hooks_{}; +}; diff --git a/src/windows_emulator/main.cpp b/src/windows_emulator/main.cpp index cd55464..1fa0e9b 100644 --- a/src/windows_emulator/main.cpp +++ b/src/windows_emulator/main.cpp @@ -12,10 +12,10 @@ #include #include -#include "gdb_stub.hpp" -#include "module_mapper.hpp" #include "context_frame.hpp" +#include "debugging/x64_gdb_stub_handler.hpp" + #define GS_SEGMENT_ADDR 0x6000000ULL #define GS_SEGMENT_SIZE (20 << 20) // 20 MB @@ -32,30 +32,6 @@ bool use_gdb = false; -struct breakpoint_key -{ - size_t addr{}; - size_t size{}; - breakpoint_type type{}; - - bool operator==(const breakpoint_key& other) const - { - return this->addr == other.addr && this->size == other.size && this->type == other.type; - } -}; - -template <> -struct std::hash -{ - std::size_t operator()(const breakpoint_key& k) const noexcept - { - return ((std::hash()(k.addr) - ^ (std::hash()(k.size) << 1)) >> 1) - ^ (std::hash()(static_cast(k.type)) << 1); - } -}; - - namespace { template @@ -366,245 +342,6 @@ namespace return context; } - std::vector gdb_registers{ - x64_register::rax, - x64_register::rbx, - x64_register::rcx, - x64_register::rdx, - x64_register::rsi, - x64_register::rdi, - x64_register::rbp, - x64_register::rsp, - x64_register::r8, - x64_register::r9, - x64_register::r10, - x64_register::r11, - x64_register::r12, - x64_register::r13, - x64_register::r14, - x64_register::r15, - x64_register::rip, - x64_register::rflags, - /*x64_register::cs, - x64_register::ss, - x64_register::ds, - x64_register::es, - x64_register::fs, - x64_register::gs,*/ - }; - - memory_operation map_breakpoint_type(const breakpoint_type type) - { - switch (type) - { - case breakpoint_type::software: - case breakpoint_type::hardware_exec: - return memory_operation::exec; - case breakpoint_type::hardware_read: - return memory_permission::read; - case breakpoint_type::hardware_write: - return memory_permission::write; - case breakpoint_type::hardware_read_write: - return memory_permission::read_write; - default: - throw std::runtime_error("Bad bp type"); - } - } - - class scoped_emulator_hook - { - public: - scoped_emulator_hook() = default; - - scoped_emulator_hook(emulator& emu, emulator_hook* hook) - : emu_(&emu) - , hook_(hook) - { - } - - ~scoped_emulator_hook() - { - this->remove(); - } - - scoped_emulator_hook(const scoped_emulator_hook&) = delete; - scoped_emulator_hook& operator=(const scoped_emulator_hook&) = delete; - - scoped_emulator_hook(scoped_emulator_hook&& obj) noexcept - { - this->operator=(std::move(obj)); - } - - scoped_emulator_hook& operator=(scoped_emulator_hook&& obj) noexcept - { - if (this != &obj) - { - this->remove(); - this->emu_ = obj.emu_; - this->hook_ = obj.hook_; - - obj.hook_ = {}; - } - return *this; - } - - void remove() - { - if (this->hook_) - { - this->emu_->delete_hook(this->hook_); - this->hook_ = {}; - } - } - - private: - emulator* emu_{}; - emulator_hook* hook_{}; - }; - - class x64_gdb_stub_handler : public gdb_stub_handler - { - public: - x64_gdb_stub_handler(x64_emulator& emu) - : emu_(&emu) - { - } - - ~x64_gdb_stub_handler() override = default; - - gdb_action cont() override - { - try - { - this->emu_->start_from_ip(); - } - catch (const std::exception& e) - { - puts(e.what()); - } - - return gdb_action::resume; - } - - gdb_action stepi() override - { - try - { - this->emu_->start_from_ip({}, 1); - } - catch (const std::exception& e) - { - puts(e.what()); - } - - return gdb_action::resume; - } - - bool read_reg(const int regno, size_t* value) override - { - *value = 0; - - try - { - if (static_cast(regno) >= gdb_registers.size()) - { - return true; - } - - this->emu_->read_register(gdb_registers[regno], value, sizeof(*value)); - return true; - } - catch (...) - { - return true; - } - } - - bool write_reg(const int regno, const size_t value) override - { - try - { - if (static_cast(regno) >= gdb_registers.size()) - { - return true; - } - - this->emu_->write_register(gdb_registers[regno], &value, sizeof(value)); - return true; - } - catch (...) - { - return false; - } - } - - bool read_mem(const size_t addr, const size_t len, void* val) override - { - return this->emu_->try_read_memory(addr, val, len); - } - - bool write_mem(const size_t addr, const size_t len, void* val) override - { - try - { - this->emu_->write_memory(addr, val, len); - return true; - } - catch (...) - { - return false; - } - } - - bool set_bp(const breakpoint_type type, const size_t addr, const size_t size) override - { - try - { - this->hooks_[{addr, size, type}] = scoped_emulator_hook(*this->emu_, this->emu_->hook_memory_access( - addr, size, map_breakpoint_type(type), - [this](uint64_t, size_t, memory_operation) - { - this->on_interrupt(); - })); - - return true; - } - catch (...) - { - return false; - } - } - - bool del_bp(const breakpoint_type type, const size_t addr, const size_t size) override - { - try - { - const auto entry = this->hooks_.find({addr, size, type}); - if (entry == this->hooks_.end()) - { - return false; - } - - this->hooks_.erase(entry); - - return true; - } - catch (...) - { - return false; - } - } - - void on_interrupt() override - { - this->emu_->stop(); - } - - private: - x64_emulator* emu_{}; - std::unordered_map hooks_{}; - }; - uint64_t find_exported_function(const std::vector& exports, const std::string_view name) { for (auto& symbol : exports) @@ -782,15 +519,16 @@ namespace const auto emu = unicorn::create_x64_emulator(); auto context = setup_context(*emu); + context.module_manager = module_manager(*emu); - context.executable = map_file(context, *emu, R"(C:\Users\mauri\Desktop\boiii.exe)"); + context.executable = context.module_manager.map_module(R"(C:\Users\mauri\Desktop\ConsoleApplication6.exe)"); context.peb.access([&](PEB& peb) { peb.ImageBaseAddress = reinterpret_cast(context.executable->image_base); }); - context.ntdll = map_file(context, *emu, R"(C:\Windows\System32\ntdll.dll)"); + context.ntdll = context.module_manager.map_module(R"(C:\Windows\System32\ntdll.dll)"); const auto ldr_initialize_thunk = find_exported_function(context.ntdll->exports, "LdrInitializeThunk"); const auto rtl_user_thread_start = find_exported_function(context.ntdll->exports, "RtlUserThreadStart"); @@ -805,12 +543,6 @@ namespace return instruction_hook_continuation::skip_instruction; }); - emu->hook_instruction(x64_hookable_instructions::rdtsc, [&] - { - emu->reg(x64_register::rax, 0x0011223344556677); - return instruction_hook_continuation::skip_instruction; - }); - emu->hook_instruction(x64_hookable_instructions::invalid, [&] { const auto ip = emu->read_instruction_pointer(); @@ -842,37 +574,23 @@ namespace return memory_violation_continuation::resume; }); - /* watch_object(*emu, context.teb); watch_object(*emu, context.peb); watch_object(*emu, context.process_params); watch_object(*emu, context.kusd); - */ + + context.verbose = false; emu->hook_memory_execution(0, std::numeric_limits::max(), [&](const uint64_t address, const size_t) { ++context.executed_instructions; - const mapped_binary* binary{nullptr}; - for (const auto& entry : context.mapped_binaries) - { - const auto& mod = entry.second; - if (is_within_start_and_length(address, mod->image_base, mod->size_of_image)) - { - binary = mod.get(); - break; - } - - if (address < mod->image_base) - { - break; - } - } + const auto* binary = context.module_manager.find_by_address(address); if (binary) { - const auto export_entry = binary->export_remap.find(address); - if (export_entry != binary->export_remap.end()) + const auto export_entry = binary->address_names.find(address); + if (export_entry != binary->address_names.end()) { printf("Executing function: %s - %s (%llX)\n", binary->name.c_str(), export_entry->second.c_str(), address); @@ -937,6 +655,8 @@ namespace int main(int /*argc*/, char** /*argv*/) { + //setvbuf(stdout, nullptr, _IOFBF, 0x10000); + try { do diff --git a/src/windows_emulator/module/mapped_module.hpp b/src/windows_emulator/module/mapped_module.hpp new file mode 100644 index 0000000..2600636 --- /dev/null +++ b/src/windows_emulator/module/mapped_module.hpp @@ -0,0 +1,25 @@ +#pragma once + +struct exported_symbol +{ + std::string name{}; + uint64_t ordinal{}; + uint64_t rva{}; + uint64_t address{}; +}; + +using exported_symbols = std::vector; +using address_name_mapping = std::unordered_map; + +struct mapped_module +{ + std::string name{}; + std::filesystem::path path{}; + + uint64_t image_base{}; + uint64_t size_of_image{}; + uint64_t entry_point{}; + + exported_symbols exports{}; + address_name_mapping address_names{}; +}; diff --git a/src/windows_emulator/module/module_manager.cpp b/src/windows_emulator/module/module_manager.cpp new file mode 100644 index 0000000..05afbec --- /dev/null +++ b/src/windows_emulator/module/module_manager.cpp @@ -0,0 +1,21 @@ +#include "../std_include.hpp" +#include "module_manager.hpp" +#include "module_mapping.hpp" + +module_manager::module_manager(emulator& emu) + : emu_(&emu) +{ +} + +mapped_module* module_manager::map_module(std::filesystem::path file) +{ + auto mod = map_module_from_file(*this->emu_, std::move(file)); + if (!mod) + { + return nullptr; + } + + const auto image_base = mod->image_base; + const auto entry = this->modules_.try_emplace(image_base, std::move(*mod)); + return &entry.first->second; +} diff --git a/src/windows_emulator/module/module_manager.hpp b/src/windows_emulator/module/module_manager.hpp new file mode 100644 index 0000000..4c8591b --- /dev/null +++ b/src/windows_emulator/module/module_manager.hpp @@ -0,0 +1,46 @@ +#pragma once +#include "mapped_module.hpp" +#include + +class module_manager +{ +public: + module_manager() = default; // TODO: Get rid of that + module_manager(emulator& emu); + + mapped_module* map_module(std::filesystem::path file); + + mapped_module* find_by_address(const uint64_t address) + { + const auto entry = this->get_module(address); + if(entry != this->modules_.end()) + { + return &entry->second; + } + + return nullptr; + } + +private: + emulator* emu_{}; + + using module_map = std::map; + module_map modules_{}; + + module_map::iterator get_module(const uint64_t address) + { + if (this->modules_.empty()) + { + return this->modules_.end(); + } + + auto upper_bound = this->modules_.upper_bound(address); + if (upper_bound == this->modules_.begin()) + { + return this->modules_.end(); + } + + std::advance(upper_bound, -1); + return upper_bound; + } +}; \ No newline at end of file diff --git a/src/windows_emulator/module_mapper.cpp b/src/windows_emulator/module/module_mapping.cpp similarity index 67% rename from src/windows_emulator/module_mapper.cpp rename to src/windows_emulator/module/module_mapping.cpp index 3f71e9e..6280e1c 100644 --- a/src/windows_emulator/module_mapper.cpp +++ b/src/windows_emulator/module/module_mapping.cpp @@ -1,10 +1,10 @@ -#include "std_include.hpp" -#include "module_mapper.hpp" +#include "../std_include.hpp" +#include "module_mapping.hpp" #include namespace { - void collect_exports(emulator& emu, mapped_binary& binary, const IMAGE_OPTIONAL_HEADER& optional_header) + void collect_exports(emulator& emu, mapped_module& binary, const IMAGE_OPTIONAL_HEADER& optional_header) { auto& export_directory_entry = optional_header.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; if (export_directory_entry.VirtualAddress == 0 || export_directory_entry.Size == 0) @@ -41,11 +41,11 @@ namespace for (const auto& symbol : binary.exports) { - binary.export_remap.try_emplace(symbol.address, symbol.name); + binary.address_names.try_emplace(symbol.address, symbol.name); } } - void apply_relocations(x64_emulator& emu, const mapped_binary& binary, + void apply_relocations(emulator& emu, const mapped_module& binary, const IMAGE_OPTIONAL_HEADER& optional_header) { const auto delta = binary.image_base - optional_header.ImageBase; @@ -113,7 +113,7 @@ namespace emu.write_memory(binary.image_base, memory.data(), memory.size()); } - void map_sections(x64_emulator& emu, const mapped_binary& binary, const unsigned char* ptr, + void map_sections(emulator& emu, const mapped_module& binary, const unsigned char* ptr, const IMAGE_NT_HEADERS& nt_headers) { const std::span sections(IMAGE_FIRST_SECTION(&nt_headers), nt_headers.FileHeader.NumberOfSections); @@ -153,68 +153,66 @@ namespace } } - mapped_binary map_module(x64_emulator& emu, const std::vector& module_data, - std::filesystem::path file) + std::vector load_file(const std::filesystem::path& file) { - mapped_binary binary{}; - binary.path = std::move(file); - binary.name = binary.path.filename().string(); + std::ifstream stream(file, std::ios::in | std::ios::binary); + return {(std::istreambuf_iterator(stream)), std::istreambuf_iterator()}; + } +} - // TODO: Range checks - auto* ptr = module_data.data(); - auto* dos_header = reinterpret_cast(ptr); - auto* nt_headers = reinterpret_cast(ptr + dos_header->e_lfanew); - auto& optional_header = nt_headers->OptionalHeader; +std::optional map_module_from_data(emulator& emu, const std::vector& data, + std::filesystem::path file) +{ + mapped_module binary{}; + binary.path = std::move(file); + binary.name = binary.path.filename().string(); - binary.image_base = optional_header.ImageBase; - binary.size_of_image = optional_header.SizeOfImage; + // TODO: Range checks + auto* ptr = data.data(); + auto* dos_header = reinterpret_cast(ptr); + auto* nt_headers = reinterpret_cast(ptr + dos_header->e_lfanew); + auto& optional_header = nt_headers->OptionalHeader; - if (!emu.allocate_memory(binary.image_base, binary.size_of_image, memory_permission::read)) + binary.image_base = optional_header.ImageBase; + binary.size_of_image = optional_header.SizeOfImage; + + if (!emu.allocate_memory(binary.image_base, binary.size_of_image, memory_permission::read)) + { + binary.image_base = emu.find_free_allocation_base(binary.size_of_image); + if ((optional_header.DllCharacteristics & + IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) == 0 || // + !emu.allocate_memory( + binary.image_base, binary.size_of_image, memory_permission::read)) { - binary.image_base = emu.find_free_allocation_base(binary.size_of_image); - if ((optional_header.DllCharacteristics & - IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) == 0 || // - !emu.allocate_memory( - binary.image_base, binary.size_of_image, memory_permission::read)) - { - throw std::runtime_error("Failed to map binary"); - } + return {}; } + } - binary.entry_point = binary.image_base + optional_header.AddressOfEntryPoint; - - printf("Mapping %s at %llX\n", binary.path.generic_string().c_str(), binary.image_base); + binary.entry_point = binary.image_base + optional_header.AddressOfEntryPoint; - emu.write_memory(binary.image_base, ptr, optional_header.SizeOfHeaders); + printf("Mapping %s at %llX\n", binary.path.generic_string().c_str(), binary.image_base); - map_sections(emu, binary, ptr, *nt_headers); - apply_relocations(emu, binary, optional_header); - collect_exports(emu, binary, optional_header); + emu.write_memory(binary.image_base, ptr, optional_header.SizeOfHeaders); - return binary; - } + map_sections(emu, binary, ptr, *nt_headers); + apply_relocations(emu, binary, optional_header); + collect_exports(emu, binary, optional_header); - std::vector load_file(const std::filesystem::path& file) - { - std::ifstream stream(file, std::ios::in | std::ios::binary); - return {(std::istreambuf_iterator(stream)), std::istreambuf_iterator()}; - } + return binary; } -mapped_binary* map_file(process_context& context, x64_emulator& emu, std::filesystem::path file) +std::optional map_module_from_file(emulator& emu, std::filesystem::path file) { const auto data = load_file(file); if (data.empty()) { - return nullptr; + return {}; } - auto binary = map_module(emu, data, std::move(file)); - auto binary_ptr = std::make_unique(std::move(binary)); - auto* res = binary_ptr.get(); - - const auto image_base = binary_ptr->image_base; - context.mapped_binaries[image_base] = std::move(binary_ptr); + return map_module_from_data(emu, data, std::move(file)); +} - return res; +bool unmap_module(emulator& emu, const mapped_module& mod) +{ + return emu.release_memory(mod.image_base, mod.size_of_image); } diff --git a/src/windows_emulator/module/module_mapping.hpp b/src/windows_emulator/module/module_mapping.hpp new file mode 100644 index 0000000..b1813a6 --- /dev/null +++ b/src/windows_emulator/module/module_mapping.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include +#include "mapped_module.hpp" + +std::optional map_module_from_data(emulator& emu, const std::vector& data, + std::filesystem::path file); +std::optional map_module_from_file(emulator& emu, std::filesystem::path file); + +bool unmap_module(emulator& emu, const mapped_module& mod); diff --git a/src/windows_emulator/module_mapper.hpp b/src/windows_emulator/module_mapper.hpp deleted file mode 100644 index ba84412..0000000 --- a/src/windows_emulator/module_mapper.hpp +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include "process_context.hpp" -#include - -mapped_binary* map_file(process_context& context, x64_emulator& emu, std::filesystem::path file); diff --git a/src/windows_emulator/process_context.hpp b/src/windows_emulator/process_context.hpp index c42c4f9..301efaa 100644 --- a/src/windows_emulator/process_context.hpp +++ b/src/windows_emulator/process_context.hpp @@ -2,26 +2,7 @@ #include "emulator_utils.hpp" #include "handles.hpp" -struct exported_symbol -{ - std::string name{}; - uint64_t ordinal{}; - uint64_t rva{}; - uint64_t address{}; -}; - -using exported_symbols = std::vector; - -struct mapped_binary -{ - std::filesystem::path path{}; - std::string name{}; - uint64_t image_base{}; - uint64_t size_of_image{}; - uint64_t entry_point{}; - exported_symbols exports{}; - std::unordered_map export_remap{}; -}; +#include "module/module_manager.hpp" struct event { @@ -54,10 +35,10 @@ struct process_context emulator_object process_params{}; emulator_object kusd{}; - std::map> mapped_binaries{}; + module_manager module_manager{}; - mapped_binary* executable{}; - mapped_binary* ntdll{}; + mapped_module* executable{}; + mapped_module* ntdll{}; handle_store events{}; handle_store files{}; diff --git a/src/windows_emulator/syscalls.cpp b/src/windows_emulator/syscalls.cpp index 54156f1..d226e5c 100644 --- a/src/windows_emulator/syscalls.cpp +++ b/src/windows_emulator/syscalls.cpp @@ -1,6 +1,5 @@ #include "std_include.hpp" #include "syscalls.hpp" -#include "module_mapper.hpp" #include "context_frame.hpp" struct syscall_context @@ -396,7 +395,7 @@ namespace return STATUS_INVALID_HANDLE; } - const auto binary = map_file(c.proc, c.emu, section_entry->name); + const auto binary = c.proc.module_manager.map_module(section_entry->name); if (!binary) { return STATUS_FILE_INVALID;