From e054702ebdbf8704e8af1231c649c826b69ec186 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 9 Sep 2024 18:38:25 +0200 Subject: [PATCH] Small fixes and adjustments --- src/emulator/memory_manager.cpp | 6 +- src/windows_emulator/main.cpp | 22 ++-- .../module/module_manager.cpp | 7 +- .../module/module_manager.hpp | 2 +- .../module/module_mapping.cpp | 100 ++++++++++-------- src/windows_emulator/syscalls.cpp | 64 ++++++++--- 6 files changed, 127 insertions(+), 74 deletions(-) diff --git a/src/emulator/memory_manager.cpp b/src/emulator/memory_manager.cpp index df90d2e8..f55b2dde 100644 --- a/src/emulator/memory_manager.cpp +++ b/src/emulator/memory_manager.cpp @@ -10,8 +10,8 @@ namespace { - constexpr auto MIN_ALLOCATION_ADDRESS = 0x0000000000010000; - constexpr auto MAX_ALLOCATION_ADDRESS = 0x00007ffffffeffff; + constexpr auto MIN_ALLOCATION_ADDRESS = 0x0000000000010000ULL; + constexpr auto MAX_ALLOCATION_ADDRESS = 0x00007ffffffeffffULL; void split_regions(memory_manager::committed_region_map& regions, const std::vector& split_points) { @@ -287,7 +287,7 @@ bool memory_manager::release_memory(const uint64_t address, size_t size) uint64_t memory_manager::find_free_allocation_base(const size_t size) const { - uint64_t start_address = MIN_ALLOCATION_ADDRESS; + uint64_t start_address = std::max(MIN_ALLOCATION_ADDRESS, 0x1000000000ULL); for (const auto& region : this->reserved_regions_) { diff --git a/src/windows_emulator/main.cpp b/src/windows_emulator/main.cpp index 1fa0e9b6..3af46db7 100644 --- a/src/windows_emulator/main.cpp +++ b/src/windows_emulator/main.cpp @@ -287,7 +287,7 @@ namespace emu.reg(x64_register::ss, 0x2B); } - process_context setup_context(x64_emulator& emu) + process_context setup_context(x64_emulator& emu, const std::filesystem::path& file) { process_context context{}; @@ -325,9 +325,9 @@ namespace proc_params.StandardInput = STDIN_HANDLE.h; proc_params.StandardError = proc_params.StandardOutput; - gs.make_unicode_string(proc_params.CurrentDirectory.DosPath, L"C:\\Users\\mauri\\Desktop"); - gs.make_unicode_string(proc_params.ImagePathName, L"C:\\Users\\mauri\\Desktop\\ConsoleApplication6.exe"); - gs.make_unicode_string(proc_params.CommandLine, L"C:\\Users\\mauri\\Desktop\\ConsoleApplication6.exe"); + gs.make_unicode_string(proc_params.CurrentDirectory.DosPath, file.parent_path().wstring()); + gs.make_unicode_string(proc_params.ImagePathName, file.wstring()); + gs.make_unicode_string(proc_params.CommandLine, file.wstring()); }); context.peb.access([&](PEB& peb) @@ -518,10 +518,13 @@ namespace { const auto emu = unicorn::create_x64_emulator(); - auto context = setup_context(*emu); + const std::filesystem::path application = + R"(C:\Program Files (x86)\Steam\steamapps\common\Hogwarts Legacy\Phoenix\Binaries\Win64\HogwartsLegacy.exe)"; + + auto context = setup_context(*emu, application); context.module_manager = module_manager(*emu); - context.executable = context.module_manager.map_module(R"(C:\Users\mauri\Desktop\ConsoleApplication6.exe)"); + context.executable = context.module_manager.map_module(application); context.peb.access([&](PEB& peb) { @@ -574,18 +577,19 @@ 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 auto* binary = context.module_manager.find_by_address(address); + /*const auto* binary = context.module_manager.find_by_address(address); if (binary) { @@ -595,7 +599,7 @@ namespace printf("Executing function: %s - %s (%llX)\n", binary->name.c_str(), export_entry->second.c_str(), address); } - } + }*/ if (!context.verbose) { diff --git a/src/windows_emulator/module/module_manager.cpp b/src/windows_emulator/module/module_manager.cpp index 05afbec7..689f2129 100644 --- a/src/windows_emulator/module/module_manager.cpp +++ b/src/windows_emulator/module/module_manager.cpp @@ -7,14 +7,17 @@ module_manager::module_manager(emulator& emu) { } -mapped_module* module_manager::map_module(std::filesystem::path file) +mapped_module* module_manager::map_module(const std::filesystem::path& file) { - auto mod = map_module_from_file(*this->emu_, std::move(file)); + auto mod = map_module_from_file(*this->emu_, file); if (!mod) { + printf("Failed to map %s\n", file.generic_string().c_str()); return nullptr; } + printf("Mapped %s at %llX\n", mod->path.generic_string().c_str(), mod->image_base); + 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 index 4c8591b4..39af5e69 100644 --- a/src/windows_emulator/module/module_manager.hpp +++ b/src/windows_emulator/module/module_manager.hpp @@ -8,7 +8,7 @@ public: module_manager() = default; // TODO: Get rid of that module_manager(emulator& emu); - mapped_module* map_module(std::filesystem::path file); + mapped_module* map_module(const std::filesystem::path& file); mapped_module* find_by_address(const uint64_t address) { diff --git a/src/windows_emulator/module/module_mapping.cpp b/src/windows_emulator/module/module_mapping.cpp index a4233636..9a29ef9b 100644 --- a/src/windows_emulator/module/module_mapping.cpp +++ b/src/windows_emulator/module/module_mapping.cpp @@ -178,58 +178,68 @@ namespace std::ifstream stream(file, std::ios::in | std::ios::binary); return {(std::istreambuf_iterator(stream)), std::istreambuf_iterator()}; } -} + std::optional map_module(emulator& emu, const std::span data, + std::filesystem::path file) + { + mapped_module binary{}; + binary.path = std::move(file); + binary.name = binary.path.filename().string(); + + utils::safe_buffer_accessor buffer{data}; + + const auto dos_header = buffer.as(0).get(); + const auto nt_headers_offset = dos_header.e_lfanew; + + const auto nt_headers = buffer.as(nt_headers_offset).get(); + auto& optional_header = nt_headers.OptionalHeader; + + binary.image_base = optional_header.ImageBase; + binary.size_of_image = optional_header.SizeOfImage; // TODO: Sanitize + + 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)) + { + return {}; + } + } + + binary.entry_point = binary.image_base + optional_header.AddressOfEntryPoint; + + const auto* header_buffer = buffer.get_pointer_for_range(0, optional_header.SizeOfHeaders); + emu.write_memory(binary.image_base, header_buffer, + optional_header.SizeOfHeaders); + + map_sections(emu, binary, buffer, nt_headers, nt_headers_offset); + + auto mapped_memory = read_mapped_memory(emu, binary); + utils::safe_buffer_accessor mapped_buffer{mapped_memory}; + + apply_relocations(binary, mapped_buffer, optional_header); + collect_exports(binary, mapped_buffer, optional_header); + + emu.write_memory(binary.image_base, mapped_memory.data(), mapped_memory.size()); + + return binary; + } +} std::optional map_module_from_data(emulator& emu, const std::span data, std::filesystem::path file) { - mapped_module binary{}; - binary.path = std::move(file); - binary.name = binary.path.filename().string(); - - utils::safe_buffer_accessor buffer{data}; - - const auto dos_header = buffer.as(0).get(); - const auto nt_headers_offset = dos_header.e_lfanew; - - const auto nt_headers = buffer.as(nt_headers_offset).get(); - auto& optional_header = nt_headers.OptionalHeader; - - binary.image_base = optional_header.ImageBase; - binary.size_of_image = optional_header.SizeOfImage; // TODO: Sanitize - - if (!emu.allocate_memory(binary.image_base, binary.size_of_image, memory_permission::read)) + try { - 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)) - { - return {}; - } + return map_module(emu, data, std::move(file)); + } + catch (...) + { + 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); - - const auto* header_buffer = buffer.get_pointer_for_range(0, optional_header.SizeOfHeaders); - emu.write_memory(binary.image_base, header_buffer, - optional_header.SizeOfHeaders); - - map_sections(emu, binary, buffer, nt_headers, nt_headers_offset); - - auto mapped_memory = read_mapped_memory(emu, binary); - utils::safe_buffer_accessor mapped_buffer{mapped_memory}; - - apply_relocations(binary, mapped_buffer, optional_header); - collect_exports(binary, mapped_buffer, optional_header); - - emu.write_memory(binary.image_base, mapped_memory.data(), mapped_memory.size()); - - return binary; } std::optional map_module_from_file(emulator& emu, std::filesystem::path file) diff --git a/src/windows_emulator/syscalls.cpp b/src/windows_emulator/syscalls.cpp index d226e5c4..fe744e7b 100644 --- a/src/windows_emulator/syscalls.cpp +++ b/src/windows_emulator/syscalls.cpp @@ -719,28 +719,46 @@ namespace return STATUS_NOT_SUPPORTED; } - if (info_class != ProcessCookie) + if (info_class == ProcessCookie) { - printf("Unsupported process info class: %X\n", info_class); - c.emu.stop(); + if (return_length) + { + return_length.write(sizeof(uint32_t)); + } - return STATUS_NOT_SUPPORTED; + if (process_information_length != sizeof(uint32_t)) + { + return STATUS_BUFFER_OVERFLOW; + } + + const emulator_object info{c.emu, process_information}; + info.write(0x01234567); + + return STATUS_SUCCESS; } - if (return_length) + if (info_class == ProcessDebugPort) { - return_length.write(sizeof(uint32_t)); + if (return_length) + { + return_length.write(sizeof(DWORD_PTR)); + } + + if (process_information_length != sizeof(DWORD_PTR)) + { + return STATUS_BUFFER_OVERFLOW; + } + + const emulator_object info{c.emu, process_information}; + info.write(0); + + return STATUS_SUCCESS; } - if (process_information_length != sizeof(uint32_t)) - { - return STATUS_BUFFER_OVERFLOW; - } + printf("Unsupported process info class: %X\n", info_class); + c.emu.stop(); - const emulator_object info{c.emu, process_information}; - info.write(0x01234567); - - return STATUS_SUCCESS; + return STATUS_NOT_SUPPORTED; } NTSTATUS handle_NtSetInformationProcess(const syscall_context& c, const uint64_t process_handle, @@ -1097,6 +1115,23 @@ namespace throw std::runtime_error("Unsupported file"); } + + NTSTATUS handle_NtRaiseHardError(const syscall_context& c, const NTSTATUS error_status, + const ULONG /*number_of_parameters*/, + const emulator_object /*unicode_string_parameter_mask*/, + const emulator_object /*parameters*/, + const HARDERROR_RESPONSE_OPTION /*valid_response_option*/, + const emulator_object response) + { + if (response) + { + response.write(ResponseAbort); + } + + printf("Hard error: %X\n", error_status); + c.emu.stop(); + return STATUS_SUCCESS; + } } syscall_dispatcher::syscall_dispatcher(const exported_symbols& ntdll_exports) @@ -1154,6 +1189,7 @@ syscall_dispatcher::syscall_dispatcher(const exported_symbols& ntdll_exports) add_handler(NtContinue); add_handler(NtTerminateProcess); add_handler(NtWriteFile); + add_handler(NtRaiseHardError); #undef add_handler }