Cleanup process context

This commit is contained in:
momo5502
2025-02-10 17:28:00 +01:00
parent 04ca0981a1
commit c1aa260f8f
3 changed files with 127 additions and 116 deletions

View File

@@ -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<uint64_t>(GDT_ADDR + 6 * (sizeof(uint64_t)), 0xEFFE000000FFFF);
emu.reg<uint16_t>(x64_register::cs, 0x33);
emu.write_memory<uint64_t>(GDT_ADDR + 5 * (sizeof(uint64_t)), 0xEFF6000000FFFF);
emu.reg<uint16_t>(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<PEB64>();
/* 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<RTL_USER_PROCESS_PARAMETERS64>();
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<std::uint64_t*>(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<uint32_t>(std::max(static_cast<uint64_t>(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<CPTABLEINFO>().value();
// peb.OemCodePageData = allocator.reserve<CPTABLEINFO>().value();
peb.UnicodeCaseTableData = allocator.reserve<NLSTABLEINFO>().value();
});
}

View File

@@ -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};

View File

@@ -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<uint64_t>(GDT_ADDR + 6 * (sizeof(uint64_t)), 0xEFFE000000FFFF);
emu.reg<uint16_t>(x64_register::cs, 0x33);
emu.write_memory<uint64_t>(GDT_ADDR + 5 * (sizeof(uint64_t)), 0xEFF6000000FFFF);
emu.reg<uint16_t>(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<PEB64>();
/* 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<RTL_USER_PROCESS_PARAMETERS64>();
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<std::uint64_t*>(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<uint32_t>(std::max(static_cast<uint64_t>(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<CPTABLEINFO>().value();
// peb.OemCodePageData = allocator.reserve<CPTABLEINFO>().value();
peb.UnicodeCaseTableData = allocator.reserve<NLSTABLEINFO>().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);