mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-11 16:46:16 +00:00
Cleanup process context
This commit is contained in:
117
src/windows-emulator/process_context.cpp
Normal file
117
src/windows-emulator/process_context.cpp
Normal 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();
|
||||
});
|
||||
}
|
||||
@@ -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};
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user