From c1aa260f8ff2c5e48fd1c5547c1572d3c734b196 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 10 Feb 2025 17:28:00 +0100 Subject: [PATCH] Cleanup process context --- src/windows-emulator/process_context.cpp | 117 ++++++++++++++++++++++ src/windows-emulator/process_context.hpp | 9 ++ src/windows-emulator/windows_emulator.cpp | 117 +--------------------- 3 files changed, 127 insertions(+), 116 deletions(-) create mode 100644 src/windows-emulator/process_context.cpp diff --git a/src/windows-emulator/process_context.cpp b/src/windows-emulator/process_context.cpp new file mode 100644 index 00000000..79181698 --- /dev/null +++ b/src/windows-emulator/process_context.cpp @@ -0,0 +1,117 @@ +#include "process_context.hpp" + +#include "emulator_utils.hpp" +#include "windows_emulator.hpp" + +namespace +{ + emulator_allocator create_allocator(memory_manager& memory, const size_t size) + { + const auto base = memory.find_free_allocation_base(size); + memory.allocate_memory(base, size, memory_permission::read_write); + + return emulator_allocator{memory, base, size}; + } + + void setup_gdt(x64_emulator& emu, memory_manager& memory) + { + constexpr uint64_t gdtr[4] = {0, GDT_ADDR, GDT_LIMIT, 0}; + emu.write_register(x64_register::gdtr, &gdtr, sizeof(gdtr)); + memory.allocate_memory(GDT_ADDR, GDT_LIMIT, memory_permission::read); + + emu.write_memory(GDT_ADDR + 6 * (sizeof(uint64_t)), 0xEFFE000000FFFF); + emu.reg(x64_register::cs, 0x33); + + emu.write_memory(GDT_ADDR + 5 * (sizeof(uint64_t)), 0xEFF6000000FFFF); + emu.reg(x64_register::ss, 0x2B); + } +} + +void process_context::setup(x64_emulator& emu, memory_manager& memory, const application_settings& app_settings, + const emulator_settings& emu_settings, const uint64_t process_image_base, + const apiset::container& apiset_container) +{ + setup_gdt(emu, memory); + + this->kusd.setup(emu_settings.use_relative_time); + + this->base_allocator = create_allocator(memory, PEB_SEGMENT_SIZE); + auto& allocator = this->base_allocator; + + this->peb = allocator.reserve(); + + /* Values of the following fields must be + * allocated relative to the process_params themselves + * and included in the length: + * + * CurrentDirectory + * DllPath + * ImagePathName + * CommandLine + * WindowTitle + * DesktopInfo + * ShellInfo + * RuntimeData + * RedirectionDllName + */ + + this->process_params = allocator.reserve(); + + this->process_params.access([&](RTL_USER_PROCESS_PARAMETERS64& proc_params) { + proc_params.Flags = 0x6001; //| 0x80000000; // Prevent CsrClientConnectToServer + + proc_params.ConsoleHandle = CONSOLE_HANDLE.h; + proc_params.StandardOutput = STDOUT_HANDLE.h; + proc_params.StandardInput = STDIN_HANDLE.h; + proc_params.StandardError = proc_params.StandardOutput; + + proc_params.Environment = reinterpret_cast(allocator.copy_string(u"=::=::\\")); + allocator.copy_string(u"EMULATOR=1"); + allocator.copy_string(u"COMPUTERNAME=momo"); + allocator.copy_string(u"SystemRoot=C:\\WINDOWS"); + allocator.copy_string(u""); + + const auto application_str = app_settings.application.u16string(); + + std::u16string command_line = u"\"" + application_str + u"\""; + + for (const auto& arg : app_settings.arguments) + { + command_line.push_back(u' '); + command_line.append(arg); + } + + allocator.make_unicode_string(proc_params.CommandLine, command_line); + allocator.make_unicode_string(proc_params.CurrentDirectory.DosPath, + app_settings.working_directory.u16string() + u"\\", 1024); + allocator.make_unicode_string(proc_params.ImagePathName, application_str); + + const auto total_length = allocator.get_next_address() - this->process_params.value(); + + proc_params.Length = static_cast(std::max(static_cast(sizeof(proc_params)), total_length)); + proc_params.MaximumLength = proc_params.Length; + }); + + this->peb.access([&](PEB64& peb) { + peb.ImageBaseAddress = process_image_base; + peb.ProcessParameters = this->process_params.ptr(); + peb.ApiSetMap = apiset::clone(emu, allocator, apiset_container).ptr(); + + peb.ProcessHeap = nullptr; + peb.ProcessHeaps = nullptr; + peb.HeapSegmentReserve = 0x0000000000100000; // TODO: Read from executable + peb.HeapSegmentCommit = 0x0000000000002000; + peb.HeapDeCommitTotalFreeThreshold = 0x0000000000010000; + peb.HeapDeCommitFreeBlockThreshold = 0x0000000000001000; + peb.NumberOfHeaps = 0x00000000; + peb.MaximumNumberOfHeaps = 0x00000010; + + peb.OSPlatformId = 2; + peb.OSMajorVersion = 0x0000000a; + peb.OSBuildNumber = 0x00006c51; + + // peb.AnsiCodePageData = allocator.reserve().value(); + // peb.OemCodePageData = allocator.reserve().value(); + peb.UnicodeCaseTableData = allocator.reserve().value(); + }); +} diff --git a/src/windows-emulator/process_context.hpp b/src/windows-emulator/process_context.hpp index 4c47c2f4..005a7e67 100644 --- a/src/windows-emulator/process_context.hpp +++ b/src/windows-emulator/process_context.hpp @@ -14,6 +14,8 @@ #include "windows_objects.hpp" #include "emulator_thread.hpp" +#include "apiset/apiset.hpp" + #define PEB_SEGMENT_SIZE (20 << 20) // 20 MB #define GS_SEGMENT_SIZE (1 << 20) // 1 MB @@ -25,6 +27,9 @@ #define GDT_LIMIT 0x1000 #define GDT_ENTRY_SIZE 0x8 +struct emulator_settings; +struct application_settings; + struct process_context { process_context(x64_emulator& emu, memory_manager& memory) @@ -35,6 +40,10 @@ struct process_context { } + void setup(x64_emulator& emu, memory_manager& memory, const application_settings& app_settings, + const emulator_settings& emu_settings, const uint64_t process_image_base, + const apiset::container& apiset_container); + uint64_t executed_instructions{0}; uint64_t current_ip{0}; uint64_t previous_ip{0}; diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index 64c63cca..8e1a59f5 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -49,121 +49,6 @@ namespace adjust_application(app_settings); } - emulator_allocator create_allocator(memory_manager& memory, const size_t size) - { - const auto base = memory.find_free_allocation_base(size); - memory.allocate_memory(base, size, memory_permission::read_write); - - return emulator_allocator{memory, base, size}; - } - - void setup_gdt(x64_emulator& emu, memory_manager& memory) - { - constexpr uint64_t gdtr[4] = {0, GDT_ADDR, GDT_LIMIT, 0}; - emu.write_register(x64_register::gdtr, &gdtr, sizeof(gdtr)); - memory.allocate_memory(GDT_ADDR, GDT_LIMIT, memory_permission::read); - - emu.write_memory(GDT_ADDR + 6 * (sizeof(uint64_t)), 0xEFFE000000FFFF); - emu.reg(x64_register::cs, 0x33); - - emu.write_memory(GDT_ADDR + 5 * (sizeof(uint64_t)), 0xEFF6000000FFFF); - emu.reg(x64_register::ss, 0x2B); - } - - void setup_context(windows_emulator& win_emu, const application_settings& app_settings, - const emulator_settings& emu_settings, const uint64_t process_image_base, - const apiset::container& apiset_container) - { - auto& emu = win_emu.emu(); - auto& context = win_emu.process; - auto& memory = win_emu.memory; - - setup_gdt(emu, memory); - - context.kusd.setup(emu_settings.use_relative_time); - - context.base_allocator = create_allocator(memory, PEB_SEGMENT_SIZE); - auto& allocator = context.base_allocator; - - context.peb = allocator.reserve(); - - /* Values of the following fields must be - * allocated relative to the process_params themselves - * and included in the length: - * - * CurrentDirectory - * DllPath - * ImagePathName - * CommandLine - * WindowTitle - * DesktopInfo - * ShellInfo - * RuntimeData - * RedirectionDllName - */ - - context.process_params = allocator.reserve(); - - context.process_params.access([&](RTL_USER_PROCESS_PARAMETERS64& proc_params) { - proc_params.Flags = 0x6001; //| 0x80000000; // Prevent CsrClientConnectToServer - - proc_params.ConsoleHandle = CONSOLE_HANDLE.h; - proc_params.StandardOutput = STDOUT_HANDLE.h; - proc_params.StandardInput = STDIN_HANDLE.h; - proc_params.StandardError = proc_params.StandardOutput; - - proc_params.Environment = reinterpret_cast(allocator.copy_string(u"=::=::\\")); - allocator.copy_string(u"EMULATOR=1"); - allocator.copy_string(u"COMPUTERNAME=momo"); - allocator.copy_string(u"SystemRoot=C:\\WINDOWS"); - allocator.copy_string(u""); - - const auto application_str = app_settings.application.u16string(); - - std::u16string command_line = u"\"" + application_str + u"\""; - - for (const auto& arg : app_settings.arguments) - { - command_line.push_back(u' '); - command_line.append(arg); - } - - allocator.make_unicode_string(proc_params.CommandLine, command_line); - allocator.make_unicode_string(proc_params.CurrentDirectory.DosPath, - app_settings.working_directory.u16string() + u"\\", 1024); - allocator.make_unicode_string(proc_params.ImagePathName, application_str); - - const auto total_length = allocator.get_next_address() - context.process_params.value(); - - proc_params.Length = - static_cast(std::max(static_cast(sizeof(proc_params)), total_length)); - proc_params.MaximumLength = proc_params.Length; - }); - - context.peb.access([&](PEB64& peb) { - peb.ImageBaseAddress = process_image_base; - peb.ProcessParameters = context.process_params.ptr(); - peb.ApiSetMap = apiset::clone(emu, allocator, apiset_container).ptr(); - - peb.ProcessHeap = nullptr; - peb.ProcessHeaps = nullptr; - peb.HeapSegmentReserve = 0x0000000000100000; // TODO: Read from executable - peb.HeapSegmentCommit = 0x0000000000002000; - peb.HeapDeCommitTotalFreeThreshold = 0x0000000000010000; - peb.HeapDeCommitFreeBlockThreshold = 0x0000000000001000; - peb.NumberOfHeaps = 0x00000000; - peb.MaximumNumberOfHeaps = 0x00000010; - - peb.OSPlatformId = 2; - peb.OSMajorVersion = 0x0000000a; - peb.OSBuildNumber = 0x00006c51; - - // peb.AnsiCodePageData = allocator.reserve().value(); - // peb.OemCodePageData = allocator.reserve().value(); - peb.UnicodeCaseTableData = allocator.reserve().value(); - }); - } - void perform_context_switch_work(windows_emulator& win_emu) { auto& devices = win_emu.process.devices; @@ -340,7 +225,7 @@ void windows_emulator::setup_process(const application_settings& app_settings, c const auto apiset_data = apiset::obtain(this->emulation_root); - setup_context(*this, app_settings, emu_settings, exe->image_base, apiset_data); + this->process.setup(this->emu(), this->memory, app_settings, emu_settings, exe->image_base, apiset_data); context.executable = exe; context.ntdll = this->mod_manager.map_module(R"(C:\Windows\System32\ntdll.dll)", this->log, true);