prepare 32bit support with name and class inheritance modifications

This commit is contained in:
robert-yates
2025-04-19 22:45:07 +02:00
parent 719a350626
commit b2296930d3
31 changed files with 623 additions and 575 deletions

View File

@@ -5,7 +5,7 @@
#include "../emulator_utils.hpp"
#include <x64_emulator.hpp>
#include <arch_emulator.hpp>
#include <utils/io.hpp>
#include <utils/compression.hpp>
@@ -14,7 +14,7 @@ namespace apiset
{
namespace
{
uint64_t copy_string(x64_emulator& emu, emulator_allocator& allocator, const void* base_ptr,
uint64_t copy_string(x86_64_emulator& emu, emulator_allocator& allocator, const void* base_ptr,
const uint64_t offset, const size_t length)
{
if (!length)
@@ -29,7 +29,7 @@ namespace apiset
return str_obj;
}
ULONG copy_string_as_relative(x64_emulator& emu, emulator_allocator& allocator, const uint64_t result_base,
ULONG copy_string_as_relative(x86_64_emulator& emu, emulator_allocator& allocator, const uint64_t result_base,
const void* base_ptr, const uint64_t offset, const size_t length)
{
const auto address = copy_string(emu, allocator, base_ptr, offset, length);
@@ -115,13 +115,13 @@ namespace apiset
return obtain(apiset_loc, root);
}
emulator_object<API_SET_NAMESPACE> clone(x64_emulator& emu, emulator_allocator& allocator,
emulator_object<API_SET_NAMESPACE> clone(x86_64_emulator& emu, emulator_allocator& allocator,
const container& container)
{
return clone(emu, allocator, container.get());
}
emulator_object<API_SET_NAMESPACE> clone(x64_emulator& emu, emulator_allocator& allocator,
emulator_object<API_SET_NAMESPACE> clone(x86_64_emulator& emu, emulator_allocator& allocator,
const API_SET_NAMESPACE& orig_api_set_map)
{
const auto api_set_map_obj = allocator.reserve<API_SET_NAMESPACE>();

View File

@@ -29,9 +29,9 @@ namespace apiset
container obtain(location location, const std::filesystem::path& root);
container obtain(const std::filesystem::path& root);
emulator_object<API_SET_NAMESPACE> clone(x64_emulator& emu, emulator_allocator& allocator,
emulator_object<API_SET_NAMESPACE> clone(x86_64_emulator& emu, emulator_allocator& allocator,
const API_SET_NAMESPACE& orig_api_set_map);
emulator_object<API_SET_NAMESPACE> clone(x64_emulator& emu, emulator_allocator& allocator,
emulator_object<API_SET_NAMESPACE> clone(x86_64_emulator& emu, emulator_allocator& allocator,
const container& container);
}

View File

@@ -3,147 +3,147 @@
namespace cpu_context
{
void restore(x64_emulator& emu, const CONTEXT64& context)
void restore(x86_64_emulator& emu, const CONTEXT64& context)
{
if ((context.ContextFlags & CONTEXT_DEBUG_REGISTERS_64) == CONTEXT_DEBUG_REGISTERS_64)
{
emu.reg(x64_register::dr0, context.Dr0);
emu.reg(x64_register::dr1, context.Dr1);
emu.reg(x64_register::dr2, context.Dr2);
emu.reg(x64_register::dr3, context.Dr3);
emu.reg(x64_register::dr6, context.Dr6);
emu.reg(x64_register::dr7, context.Dr7);
emu.reg(x86_register::dr0, context.Dr0);
emu.reg(x86_register::dr1, context.Dr1);
emu.reg(x86_register::dr2, context.Dr2);
emu.reg(x86_register::dr3, context.Dr3);
emu.reg(x86_register::dr6, context.Dr6);
emu.reg(x86_register::dr7, context.Dr7);
}
if ((context.ContextFlags & CONTEXT_CONTROL_64) == CONTEXT_CONTROL_64)
{
emu.reg<uint16_t>(x64_register::ss, context.SegSs);
emu.reg<uint16_t>(x64_register::cs, context.SegCs);
emu.reg<uint16_t>(x86_register::ss, context.SegSs);
emu.reg<uint16_t>(x86_register::cs, context.SegCs);
emu.reg(x64_register::rip, context.Rip);
emu.reg(x64_register::rsp, context.Rsp);
emu.reg(x86_register::rip, context.Rip);
emu.reg(x86_register::rsp, context.Rsp);
emu.reg<uint32_t>(x64_register::eflags, context.EFlags);
emu.reg<uint32_t>(x86_register::eflags, context.EFlags);
}
if ((context.ContextFlags & CONTEXT_INTEGER_64) == CONTEXT_INTEGER_64)
{
emu.reg(x64_register::rax, context.Rax);
emu.reg(x64_register::rbx, context.Rbx);
emu.reg(x64_register::rcx, context.Rcx);
emu.reg(x64_register::rdx, context.Rdx);
emu.reg(x64_register::rbp, context.Rbp);
emu.reg(x64_register::rsi, context.Rsi);
emu.reg(x64_register::rdi, context.Rdi);
emu.reg(x64_register::r8, context.R8);
emu.reg(x64_register::r9, context.R9);
emu.reg(x64_register::r10, context.R10);
emu.reg(x64_register::r11, context.R11);
emu.reg(x64_register::r12, context.R12);
emu.reg(x64_register::r13, context.R13);
emu.reg(x64_register::r14, context.R14);
emu.reg(x64_register::r15, context.R15);
emu.reg(x86_register::rax, context.Rax);
emu.reg(x86_register::rbx, context.Rbx);
emu.reg(x86_register::rcx, context.Rcx);
emu.reg(x86_register::rdx, context.Rdx);
emu.reg(x86_register::rbp, context.Rbp);
emu.reg(x86_register::rsi, context.Rsi);
emu.reg(x86_register::rdi, context.Rdi);
emu.reg(x86_register::r8, context.R8);
emu.reg(x86_register::r9, context.R9);
emu.reg(x86_register::r10, context.R10);
emu.reg(x86_register::r11, context.R11);
emu.reg(x86_register::r12, context.R12);
emu.reg(x86_register::r13, context.R13);
emu.reg(x86_register::r14, context.R14);
emu.reg(x86_register::r15, context.R15);
}
/*if ((context.ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
{
emu.reg<uint16_t>(x64_register::ds, context.SegDs);
emu.reg<uint16_t>(x64_register::es, context.SegEs);
emu.reg<uint16_t>(x64_register::fs, context.SegFs);
emu.reg<uint16_t>(x64_register::gs, context.SegGs);
emu.reg<uint16_t>(x86_register::ds, context.SegDs);
emu.reg<uint16_t>(x86_register::es, context.SegEs);
emu.reg<uint16_t>(x86_register::fs, context.SegFs);
emu.reg<uint16_t>(x86_register::gs, context.SegGs);
}*/
if ((context.ContextFlags & CONTEXT_FLOATING_POINT_64) == CONTEXT_FLOATING_POINT_64)
{
emu.reg<uint16_t>(x64_register::fpcw, context.FltSave.ControlWord);
emu.reg<uint16_t>(x64_register::fpsw, context.FltSave.StatusWord);
emu.reg<uint16_t>(x64_register::fptag, context.FltSave.TagWord);
emu.reg<uint16_t>(x86_register::fpcw, context.FltSave.ControlWord);
emu.reg<uint16_t>(x86_register::fpsw, context.FltSave.StatusWord);
emu.reg<uint16_t>(x86_register::fptag, context.FltSave.TagWord);
for (int i = 0; i < 8; i++)
{
const auto reg = static_cast<x64_register>(static_cast<int>(x64_register::st0) + i);
const auto reg = static_cast<x86_register>(static_cast<int>(x86_register::st0) + i);
emu.reg<M128A>(reg, context.FltSave.FloatRegisters[i]);
}
}
if ((context.ContextFlags & CONTEXT_XSTATE_64) == CONTEXT_XSTATE_64)
{
emu.reg<uint32_t>(x64_register::mxcsr, context.MxCsr);
emu.reg<uint32_t>(x86_register::mxcsr, context.MxCsr);
for (int i = 0; i < 16; i++)
{
const auto reg = static_cast<x64_register>(static_cast<int>(x64_register::xmm0) + i);
const auto reg = static_cast<x86_register>(static_cast<int>(x86_register::xmm0) + i);
emu.reg<M128A>(reg, (&context.Xmm0)[i]);
}
}
}
void save(x64_emulator& emu, CONTEXT64& context)
void save(x86_64_emulator& emu, CONTEXT64& context)
{
if ((context.ContextFlags & CONTEXT_DEBUG_REGISTERS_64) == CONTEXT_DEBUG_REGISTERS_64)
{
context.Dr0 = emu.reg(x64_register::dr0);
context.Dr1 = emu.reg(x64_register::dr1);
context.Dr2 = emu.reg(x64_register::dr2);
context.Dr3 = emu.reg(x64_register::dr3);
context.Dr6 = emu.reg(x64_register::dr6);
context.Dr7 = emu.reg(x64_register::dr7);
context.Dr0 = emu.reg(x86_register::dr0);
context.Dr1 = emu.reg(x86_register::dr1);
context.Dr2 = emu.reg(x86_register::dr2);
context.Dr3 = emu.reg(x86_register::dr3);
context.Dr6 = emu.reg(x86_register::dr6);
context.Dr7 = emu.reg(x86_register::dr7);
}
if ((context.ContextFlags & CONTEXT_CONTROL_64) == CONTEXT_CONTROL_64)
{
context.SegSs = emu.reg<uint16_t>(x64_register::ss);
context.SegCs = emu.reg<uint16_t>(x64_register::cs);
context.Rip = emu.reg(x64_register::rip);
context.Rsp = emu.reg(x64_register::rsp);
context.EFlags = emu.reg<uint32_t>(x64_register::eflags);
context.SegSs = emu.reg<uint16_t>(x86_register::ss);
context.SegCs = emu.reg<uint16_t>(x86_register::cs);
context.Rip = emu.reg(x86_register::rip);
context.Rsp = emu.reg(x86_register::rsp);
context.EFlags = emu.reg<uint32_t>(x86_register::eflags);
}
if ((context.ContextFlags & CONTEXT_INTEGER_64) == CONTEXT_INTEGER_64)
{
context.Rax = emu.reg(x64_register::rax);
context.Rbx = emu.reg(x64_register::rbx);
context.Rcx = emu.reg(x64_register::rcx);
context.Rdx = emu.reg(x64_register::rdx);
context.Rbp = emu.reg(x64_register::rbp);
context.Rsi = emu.reg(x64_register::rsi);
context.Rdi = emu.reg(x64_register::rdi);
context.R8 = emu.reg(x64_register::r8);
context.R9 = emu.reg(x64_register::r9);
context.R10 = emu.reg(x64_register::r10);
context.R11 = emu.reg(x64_register::r11);
context.R12 = emu.reg(x64_register::r12);
context.R13 = emu.reg(x64_register::r13);
context.R14 = emu.reg(x64_register::r14);
context.R15 = emu.reg(x64_register::r15);
context.Rax = emu.reg(x86_register::rax);
context.Rbx = emu.reg(x86_register::rbx);
context.Rcx = emu.reg(x86_register::rcx);
context.Rdx = emu.reg(x86_register::rdx);
context.Rbp = emu.reg(x86_register::rbp);
context.Rsi = emu.reg(x86_register::rsi);
context.Rdi = emu.reg(x86_register::rdi);
context.R8 = emu.reg(x86_register::r8);
context.R9 = emu.reg(x86_register::r9);
context.R10 = emu.reg(x86_register::r10);
context.R11 = emu.reg(x86_register::r11);
context.R12 = emu.reg(x86_register::r12);
context.R13 = emu.reg(x86_register::r13);
context.R14 = emu.reg(x86_register::r14);
context.R15 = emu.reg(x86_register::r15);
}
if ((context.ContextFlags & CONTEXT_SEGMENTS_64) == CONTEXT_SEGMENTS_64)
{
context.SegDs = emu.reg<uint16_t>(x64_register::ds);
context.SegEs = emu.reg<uint16_t>(x64_register::es);
context.SegFs = emu.reg<uint16_t>(x64_register::fs);
context.SegGs = emu.reg<uint16_t>(x64_register::gs);
context.SegDs = emu.reg<uint16_t>(x86_register::ds);
context.SegEs = emu.reg<uint16_t>(x86_register::es);
context.SegFs = emu.reg<uint16_t>(x86_register::fs);
context.SegGs = emu.reg<uint16_t>(x86_register::gs);
}
if ((context.ContextFlags & CONTEXT_FLOATING_POINT_64) == CONTEXT_FLOATING_POINT_64)
{
context.FltSave.ControlWord = emu.reg<uint16_t>(x64_register::fpcw);
context.FltSave.StatusWord = emu.reg<uint16_t>(x64_register::fpsw);
context.FltSave.TagWord = static_cast<BYTE>(emu.reg<uint16_t>(x64_register::fptag));
context.FltSave.ControlWord = emu.reg<uint16_t>(x86_register::fpcw);
context.FltSave.StatusWord = emu.reg<uint16_t>(x86_register::fpsw);
context.FltSave.TagWord = static_cast<BYTE>(emu.reg<uint16_t>(x86_register::fptag));
for (int i = 0; i < 8; i++)
{
const auto reg = static_cast<x64_register>(static_cast<int>(x64_register::st0) + i);
const auto reg = static_cast<x86_register>(static_cast<int>(x86_register::st0) + i);
context.FltSave.FloatRegisters[i] = emu.reg<M128A>(reg);
}
}
if ((context.ContextFlags & CONTEXT_INTEGER_64) == CONTEXT_INTEGER_64)
{
context.MxCsr = emu.reg<uint32_t>(x64_register::mxcsr);
context.MxCsr = emu.reg<uint32_t>(x86_register::mxcsr);
for (int i = 0; i < 16; i++)
{
const auto reg = static_cast<x64_register>(static_cast<int>(x64_register::xmm0) + i);
const auto reg = static_cast<x86_register>(static_cast<int>(x86_register::xmm0) + i);
(&context.Xmm0)[i] = emu.reg<M128A>(reg);
}
}

View File

@@ -1,8 +1,8 @@
#pragma once
#include "x64_emulator.hpp"
#include "arch_emulator.hpp"
namespace cpu_context
{
void save(x64_emulator& emu, CONTEXT64& context);
void restore(x64_emulator& emu, const CONTEXT64& context);
void save(x86_64_emulator& emu, CONTEXT64& context);
void restore(x86_64_emulator& emu, const CONTEXT64& context);
}

View File

@@ -7,25 +7,26 @@
namespace
{
template <typename T>
emulator_object<T> allocate_object_on_stack(x64_emulator& emu)
emulator_object<T> allocate_object_on_stack(x86_64_emulator& emu)
{
const auto old_sp = emu.reg(x64_register::rsp);
const auto new_sp = align_down(old_sp - sizeof(T), std::max(alignof(T), alignof(x64_emulator::pointer_type)));
emu.reg(x64_register::rsp, new_sp);
const auto old_sp = emu.reg(x86_register::rsp);
const auto new_sp =
align_down(old_sp - sizeof(T), std::max(alignof(T), alignof(x86_64_emulator::pointer_type)));
emu.reg(x86_register::rsp, new_sp);
return {emu, new_sp};
}
void unalign_stack(x64_emulator& emu)
void unalign_stack(x86_64_emulator& emu)
{
auto sp = emu.reg(x64_register::rsp);
auto sp = emu.reg(x86_register::rsp);
sp = align_down(sp - 0x10, 0x10) + 8;
emu.reg(x64_register::rsp, sp);
emu.reg(x86_register::rsp, sp);
}
void setup_stack(x64_emulator& emu, const uint64_t stack_base, const size_t stack_size)
void setup_stack(x86_64_emulator& emu, const uint64_t stack_base, const size_t stack_size)
{
const uint64_t stack_end = stack_base + stack_size;
emu.reg(x64_register::rsp, stack_end);
emu.reg(x86_register::rsp, stack_end);
}
bool is_object_signaled(process_context& c, const handle h, const uint32_t current_thread_id)
@@ -207,7 +208,7 @@ bool emulator_thread::is_thread_ready(process_context& process, utils::clock& cl
return true;
}
void emulator_thread::setup_registers(x64_emulator& emu, const process_context& context) const
void emulator_thread::setup_registers(x86_64_emulator& emu, const process_context& context) const
{
if (!this->gs_segment)
{
@@ -215,7 +216,7 @@ void emulator_thread::setup_registers(x64_emulator& emu, const process_context&
}
setup_stack(emu, this->stack_base, static_cast<size_t>(this->stack_size));
emu.set_segment_base(x64_register::gs, this->gs_segment->get_base());
emu.set_segment_base(x86_register::gs, this->gs_segment->get_base());
CONTEXT64 ctx{};
ctx.ContextFlags = CONTEXT64_ALL;
@@ -232,7 +233,7 @@ void emulator_thread::setup_registers(x64_emulator& emu, const process_context&
unalign_stack(emu);
emu.reg(x64_register::rcx, ctx_obj.value());
emu.reg(x64_register::rdx, context.ntdll_image_base);
emu.reg(x64_register::rip, context.ldr_initialize_thunk);
emu.reg(x86_register::rcx, ctx_obj.value());
emu.reg(x86_register::rdx, context.ntdll_image_base);
emu.reg(x86_register::rip, context.ldr_initialize_thunk);
}

View File

@@ -105,17 +105,17 @@ class emulator_thread : public ref_counted_object
bool is_thread_ready(process_context& process, utils::clock& clock);
void save(x64_emulator& emu)
void save(x86_64_emulator& emu)
{
this->last_registers = emu.save_registers();
}
void restore(x64_emulator& emu) const
void restore(x86_64_emulator& emu) const
{
emu.restore_registers(this->last_registers);
}
void setup_if_necessary(x64_emulator& emu, const process_context& context)
void setup_if_necessary(x86_64_emulator& emu, const process_context& context)
{
if (!this->executed_instructions)
{
@@ -127,7 +127,7 @@ class emulator_thread : public ref_counted_object
const auto status = *this->pending_status;
this->pending_status = {};
emu.reg<uint64_t>(x64_register::rax, static_cast<uint64_t>(status));
emu.reg<uint64_t>(x86_register::rax, static_cast<uint64_t>(status));
}
}
@@ -211,7 +211,7 @@ class emulator_thread : public ref_counted_object
}
private:
void setup_registers(x64_emulator& emu, const process_context& context) const;
void setup_registers(x86_64_emulator& emu, const process_context& context) const;
void release()
{

View File

@@ -1,6 +1,6 @@
#pragma once
#include <x64_emulator.hpp>
#include <arch_emulator.hpp>
#include "memory_manager.hpp"
#include "memory_utils.hpp"
@@ -51,7 +51,7 @@ class module_manager;
struct process_context;
using clock_wrapper = object_wrapper<utils::clock>;
using x64_emulator_wrapper = object_wrapper<x64_emulator>;
using x64_emulator_wrapper = object_wrapper<x86_64_emulator>;
using memory_manager_wrapper = object_wrapper<memory_manager>;
using module_manager_wrapper = object_wrapper<module_manager>;
using process_context_wrapper = object_wrapper<process_context>;

View File

@@ -89,7 +89,7 @@ namespace
uint64_t ss;
};
void dispatch_exception_pointers(x64_emulator& emu, const uint64_t dispatcher,
void dispatch_exception_pointers(x86_64_emulator& emu, const uint64_t dispatcher,
const EMU_EXCEPTION_POINTERS<EmulatorTraits<Emu64>> pointers)
{
constexpr auto mach_frame_size = 0x40;
@@ -102,7 +102,7 @@ namespace
const auto allocation_size = combined_size + mach_frame_size;
const auto initial_sp = emu.reg(x64_register::rsp);
const auto initial_sp = emu.reg(x86_register::rsp);
const auto new_sp = align_down(initial_sp - allocation_size, 0x100);
const auto total_size = initial_sp - new_sp;
@@ -113,8 +113,8 @@ namespace
emu.write_memory(new_sp, zero_memory.data(), zero_memory.size());
emu.reg(x64_register::rsp, new_sp);
emu.reg(x64_register::rip, dispatcher);
emu.reg(x86_register::rsp, new_sp);
emu.reg(x86_register::rip, dispatcher);
const emulator_object<CONTEXT64> context_record_obj{emu, new_sp};
context_record_obj.write(*reinterpret_cast<CONTEXT64*>(pointers.ContextRecord));
@@ -140,7 +140,7 @@ namespace
}
}
void dispatch_exception(x64_emulator& emu, const process_context& proc, const DWORD status,
void dispatch_exception(x86_64_emulator& emu, const process_context& proc, const DWORD status,
const std::vector<EmulatorTraits<Emu64>::ULONG_PTR>& parameters)
{
CONTEXT64 ctx{};
@@ -172,7 +172,7 @@ void dispatch_exception(x64_emulator& emu, const process_context& proc, const DW
dispatch_exception_pointers(emu, proc.ki_user_exception_dispatcher, pointers);
}
void dispatch_access_violation(x64_emulator& emu, const process_context& proc, const uint64_t address,
void dispatch_access_violation(x86_64_emulator& emu, const process_context& proc, const uint64_t address,
const memory_operation operation)
{
dispatch_exception(emu, proc, STATUS_ACCESS_VIOLATION,
@@ -182,22 +182,22 @@ void dispatch_access_violation(x64_emulator& emu, const process_context& proc, c
});
}
void dispatch_illegal_instruction_violation(x64_emulator& emu, const process_context& proc)
void dispatch_illegal_instruction_violation(x86_64_emulator& emu, const process_context& proc)
{
dispatch_exception(emu, proc, STATUS_ILLEGAL_INSTRUCTION, {});
}
void dispatch_integer_division_by_zero(x64_emulator& emu, const process_context& proc)
void dispatch_integer_division_by_zero(x86_64_emulator& emu, const process_context& proc)
{
dispatch_exception(emu, proc, STATUS_INTEGER_DIVIDE_BY_ZERO, {});
}
void dispatch_single_step(x64_emulator& emu, const process_context& proc)
void dispatch_single_step(x86_64_emulator& emu, const process_context& proc)
{
dispatch_exception(emu, proc, STATUS_SINGLE_STEP, {});
}
void dispatch_breakpoint(x64_emulator& emu, const process_context& proc)
void dispatch_breakpoint(x86_64_emulator& emu, const process_context& proc)
{
dispatch_exception(emu, proc, STATUS_BREAKPOINT, {});
}

View File

@@ -1,25 +1,25 @@
#pragma once
#include <x64_emulator.hpp>
#include <arch_emulator.hpp>
#include <platform/traits.hpp>
#include <platform/primitives.hpp>
struct process_context;
void dispatch_exception(x64_emulator& emu, const process_context& proc, DWORD status,
void dispatch_exception(x86_64_emulator& emu, const process_context& proc, DWORD status,
const std::vector<EmulatorTraits<Emu64>::ULONG_PTR>& parameters);
template <typename T>
requires(std::is_integral_v<T> && !std::is_same_v<T, DWORD>)
void dispatch_exception(x64_emulator& emu, const process_context& proc, const T status,
void dispatch_exception(x86_64_emulator& emu, const process_context& proc, const T status,
const std::vector<EmulatorTraits<Emu64>::ULONG_PTR>& parameters)
{
dispatch_exception(emu, proc, static_cast<DWORD>(status), parameters);
}
void dispatch_access_violation(x64_emulator& emu, const process_context& proc, uint64_t address,
void dispatch_access_violation(x86_64_emulator& emu, const process_context& proc, uint64_t address,
memory_operation operation);
void dispatch_illegal_instruction_violation(x64_emulator& emu, const process_context& proc);
void dispatch_integer_division_by_zero(x64_emulator& emu, const process_context& proc);
void dispatch_single_step(x64_emulator& emu, const process_context& proc);
void dispatch_breakpoint(x64_emulator& emu, const process_context& proc);
void dispatch_illegal_instruction_violation(x86_64_emulator& emu, const process_context& proc);
void dispatch_integer_division_by_zero(x86_64_emulator& emu, const process_context& proc);
void dispatch_single_step(x86_64_emulator& emu, const process_context& proc);
void dispatch_breakpoint(x86_64_emulator& emu, const process_context& proc);

View File

@@ -1,7 +1,7 @@
#pragma once
#include <memory>
#include <x64_emulator.hpp>
#include <arch_emulator.hpp>
#include <serialization.hpp>
#include "emulator_utils.hpp"
@@ -22,7 +22,7 @@ struct io_device_context
emulator_pointer output_buffer{};
ULONG output_buffer_length{};
io_device_context(x64_emulator& emu)
io_device_context(x86_64_emulator& emu)
: io_status_block(emu)
{
}

View File

@@ -3,7 +3,7 @@
#include "std_include.hpp"
#include <serialization.hpp>
#include "x64_emulator.hpp"
#include "arch_emulator.hpp"
#include <utils/time.hpp>

View File

@@ -14,20 +14,20 @@ namespace
return emulator_allocator{memory, base, size};
}
void setup_gdt(x64_emulator& emu, memory_manager& memory)
void setup_gdt(x86_64_emulator& emu, memory_manager& memory)
{
memory.allocate_memory(GDT_ADDR, GDT_LIMIT, memory_permission::read);
emu.load_gdt(GDT_ADDR, GDT_LIMIT);
emu.write_memory<uint64_t>(GDT_ADDR + 6 * (sizeof(uint64_t)), 0xEFFE000000FFFF);
emu.reg<uint16_t>(x64_register::cs, 0x33);
emu.reg<uint16_t>(x86_register::cs, 0x33);
emu.write_memory<uint64_t>(GDT_ADDR + 5 * (sizeof(uint64_t)), 0xEFF6000000FFFF);
emu.reg<uint16_t>(x64_register::ss, 0x2B);
emu.reg<uint16_t>(x86_register::ss, 0x2B);
}
}
void process_context::setup(x64_emulator& emu, memory_manager& memory, const application_settings& app_settings,
void process_context::setup(x86_64_emulator& emu, memory_manager& memory, const application_settings& app_settings,
const mapped_module& executable, const mapped_module& ntdll,
const apiset::container& apiset_container)
{

View File

@@ -7,7 +7,7 @@
#include "module/module_manager.hpp"
#include <utils/nt_handle.hpp>
#include <x64_emulator.hpp>
#include <arch_emulator.hpp>
#include "io_device.hpp"
#include "kusd_mmio.hpp"
@@ -50,7 +50,7 @@ struct process_context
atom_entry() = default;
};
process_context(x64_emulator& emu, memory_manager& memory, utils::clock& clock, callbacks& cb)
process_context(x86_64_emulator& emu, memory_manager& memory, utils::clock& clock, callbacks& cb)
: callbacks_(&cb),
base_allocator(emu),
peb(emu),
@@ -59,7 +59,7 @@ struct process_context
{
}
void setup(x64_emulator& emu, memory_manager& memory, const application_settings& app_settings,
void setup(x86_64_emulator& emu, memory_manager& memory, const application_settings& app_settings,
const mapped_module& executable, const mapped_module& ntdll, const apiset::container& apiset_container);
handle create_thread(memory_manager& memory, uint64_t start_address, uint64_t argument, uint64_t stack_size,

View File

@@ -65,7 +65,7 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu)
auto& context = win_emu.process;
const auto address = emu.read_instruction_pointer();
const auto syscall_id = emu.reg<uint32_t>(x64_register::eax);
const auto syscall_id = emu.reg<uint32_t>(x86_register::eax);
const syscall_context c{
.win_emu = win_emu,
@@ -82,7 +82,7 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu)
if (entry == this->handlers_.end())
{
win_emu.log.error("Unknown syscall: 0x%X\n", syscall_id);
c.emu.reg<uint64_t>(x64_register::rax, STATUS_NOT_SUPPORTED);
c.emu.reg<uint64_t>(x86_register::rax, STATUS_NOT_SUPPORTED);
c.emu.stop();
return;
}
@@ -97,7 +97,7 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu)
if (!entry->second.handler)
{
win_emu.log.error("Unimplemented syscall: %s - 0x%X\n", entry->second.name.c_str(), syscall_id);
c.emu.reg<uint64_t>(x64_register::rax, STATUS_NOT_SUPPORTED);
c.emu.reg<uint64_t>(x86_register::rax, STATUS_NOT_SUPPORTED);
c.emu.stop();
return;
}
@@ -139,13 +139,13 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu)
catch (std::exception& e)
{
win_emu.log.error("Syscall threw an exception: %X (0x%" PRIx64 ") - %s\n", syscall_id, address, e.what());
emu.reg<uint64_t>(x64_register::rax, STATUS_UNSUCCESSFUL);
emu.reg<uint64_t>(x86_register::rax, STATUS_UNSUCCESSFUL);
emu.stop();
}
catch (...)
{
win_emu.log.error("Syscall threw an unknown exception: %X (0x%" PRIx64 ")\n", syscall_id, address);
emu.reg<uint64_t>(x64_register::rax, STATUS_UNSUCCESSFUL);
emu.reg<uint64_t>(x86_register::rax, STATUS_UNSUCCESSFUL);
emu.stop();
}
}

View File

@@ -7,24 +7,24 @@
struct syscall_context
{
windows_emulator& win_emu;
x64_emulator& emu;
x86_64_emulator& emu;
process_context& proc;
mutable bool write_status{true};
mutable bool retrigger_syscall{false};
};
inline uint64_t get_syscall_argument(x64_emulator& emu, const size_t index)
inline uint64_t get_syscall_argument(x86_64_emulator& emu, const size_t index)
{
switch (index)
{
case 0:
return emu.reg(x64_register::r10);
return emu.reg(x86_register::r10);
case 1:
return emu.reg(x64_register::rdx);
return emu.reg(x86_register::rdx);
case 2:
return emu.reg(x64_register::r8);
return emu.reg(x86_register::r8);
case 3:
return emu.reg(x64_register::r9);
return emu.reg(x86_register::r9);
default:
return emu.read_stack(index + 1);
}
@@ -110,7 +110,7 @@ inline void map_syscalls(std::map<uint64_t, syscall_handler_entry>& handlers, st
template <typename T>
requires(std::is_integral_v<T> || std::is_enum_v<T>)
T resolve_argument(x64_emulator& emu, const size_t index)
T resolve_argument(x86_64_emulator& emu, const size_t index)
{
const auto arg = get_syscall_argument(emu, index);
return static_cast<T>(arg);
@@ -118,7 +118,7 @@ T resolve_argument(x64_emulator& emu, const size_t index)
template <typename T>
requires(std::is_same_v<std::remove_cvref_t<T>, handle>)
handle resolve_argument(x64_emulator& emu, const size_t index)
handle resolve_argument(x86_64_emulator& emu, const size_t index)
{
handle h{};
h.bits = resolve_argument<uint64_t>(emu, index);
@@ -127,14 +127,14 @@ handle resolve_argument(x64_emulator& emu, const size_t index)
template <typename T>
requires(std::is_same_v<T, emulator_object<typename T::value_type>>)
T resolve_argument(x64_emulator& emu, const size_t index)
T resolve_argument(x86_64_emulator& emu, const size_t index)
{
const auto arg = get_syscall_argument(emu, index);
return T(emu, arg);
}
template <typename T>
T resolve_indexed_argument(x64_emulator& emu, size_t& index)
T resolve_indexed_argument(x86_64_emulator& emu, size_t& index)
{
return resolve_argument<T>(emu, index++);
}
@@ -143,13 +143,13 @@ inline void write_syscall_status(const syscall_context& c, const NTSTATUS status
{
if (c.write_status && !c.retrigger_syscall)
{
c.emu.reg<uint64_t>(x64_register::rax, static_cast<uint64_t>(status));
c.emu.reg<uint64_t>(x86_register::rax, static_cast<uint64_t>(status));
}
const auto new_ip = c.emu.read_instruction_pointer();
if (initial_ip != new_ip || c.retrigger_syscall)
{
c.emu.reg(x64_register::rip, new_ip - 2);
c.emu.reg(x86_register::rip, new_ip - 2);
}
}
@@ -197,7 +197,7 @@ void write_attribute(emulator& emu, const PS_ATTRIBUTE<Traits>& attribute, const
}
template <typename ResponseType, typename Action, typename ReturnLengthSetter>
NTSTATUS handle_query_internal(x64_emulator& emu, const uint64_t buffer, const uint32_t length,
NTSTATUS handle_query_internal(x86_64_emulator& emu, const uint64_t buffer, const uint32_t length,
const ReturnLengthSetter& return_length_setter, const Action& action)
{
constexpr auto required_size = sizeof(ResponseType);
@@ -217,7 +217,7 @@ NTSTATUS handle_query_internal(x64_emulator& emu, const uint64_t buffer, const u
}
template <typename ResponseType, typename Action>
NTSTATUS handle_query(x64_emulator& emu, const uint64_t buffer, const uint32_t length,
NTSTATUS handle_query(x86_64_emulator& emu, const uint64_t buffer, const uint32_t length,
const emulator_object<uint32_t> return_length, const Action& action)
{
const auto length_setter = [&](const uint32_t required_size) {
@@ -231,7 +231,7 @@ NTSTATUS handle_query(x64_emulator& emu, const uint64_t buffer, const uint32_t l
}
template <typename ResponseType, typename Action>
NTSTATUS handle_query(x64_emulator& emu, const uint64_t buffer, const uint32_t length,
NTSTATUS handle_query(x86_64_emulator& emu, const uint64_t buffer, const uint32_t length,
const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
const Action& action)
{

View File

@@ -3,10 +3,10 @@
#include "cpu_context.hpp"
#include <unicorn_x64_emulator.hpp>
#include <unicorn_x86_64_emulator.hpp>
#if MOMO_ENABLE_RUST_CODE
#include <icicle_x64_emulator.hpp>
#include <icicle_x86_64_emulator.hpp>
#endif
#include <utils/io.hpp>
@@ -117,13 +117,13 @@ namespace
ctx.ContextFlags = CONTEXT64_ALL;
cpu_context::save(emu, ctx);
const auto initial_sp = emu.reg(x64_register::rsp);
const auto initial_sp = emu.reg(x86_register::rsp);
const auto new_sp = align_down(initial_sp - sizeof(stack_layout), 0x100);
emu.write_memory(new_sp, stack_layout);
emu.reg(x64_register::rsp, new_sp);
emu.reg(x64_register::rip, win_emu.process.ki_user_apc_dispatcher);
emu.reg(x86_register::rsp, new_sp);
emu.reg(x86_register::rip, win_emu.process.ki_user_apc_dispatcher);
}
bool switch_to_thread(windows_emulator& win_emu, emulator_thread& thread, const bool force = false)
@@ -267,22 +267,22 @@ namespace
}
}
std::unique_ptr<x64_emulator> create_default_x64_emulator()
std::unique_ptr<x86_64_emulator> create_default_x86_64_emulator()
{
#if MOMO_ENABLE_RUST_CODE
const auto* env = getenv("EMULATOR_ICICLE");
if (env && (env == "1"sv || env == "true"sv))
{
return icicle::create_x64_emulator();
return icicle::create_x86_64_emulator();
}
#endif
return unicorn::create_x64_emulator();
return unicorn::create_x86_64_emulator();
}
windows_emulator::windows_emulator(application_settings app_settings, const emulator_settings& settings,
emulator_callbacks callbacks, emulator_interfaces interfaces,
std::unique_ptr<x64_emulator> emu)
std::unique_ptr<x86_64_emulator> emu)
: windows_emulator(settings, std::move(callbacks), std::move(interfaces), std::move(emu))
{
fixup_application_settings(app_settings);
@@ -290,7 +290,7 @@ windows_emulator::windows_emulator(application_settings app_settings, const emul
}
windows_emulator::windows_emulator(const emulator_settings& settings, emulator_callbacks callbacks,
emulator_interfaces interfaces, std::unique_ptr<x64_emulator> emu)
emulator_interfaces interfaces, std::unique_ptr<x86_64_emulator> emu)
: emu_(std::move(emu)),
clock_(get_clock(interfaces, this->executed_instructions_, settings.use_relative_time)),
socket_factory_(get_socket_factory(interfaces)),
@@ -485,26 +485,26 @@ void windows_emulator::on_instruction_execution(const uint64_t address)
log.print(color::gray,
"Inst: %16" PRIx64 " - RAX: %16" PRIx64 " - RBX: %16" PRIx64 " - RCX: %16" PRIx64 " - RDX: %16" PRIx64
" - R8: %16" PRIx64 " - R9: %16" PRIx64 " - RDI: %16" PRIx64 " - RSI: %16" PRIx64 " - %s\n",
address, emu.reg(x64_register::rax), emu.reg(x64_register::rbx), emu.reg(x64_register::rcx),
emu.reg(x64_register::rdx), emu.reg(x64_register::r8), emu.reg(x64_register::r9),
emu.reg(x64_register::rdi), emu.reg(x64_register::rsi), binary ? binary->name.c_str() : "<N/A>");
address, emu.reg(x86_register::rax), emu.reg(x86_register::rbx), emu.reg(x86_register::rcx),
emu.reg(x86_register::rdx), emu.reg(x86_register::r8), emu.reg(x86_register::r9),
emu.reg(x86_register::rdi), emu.reg(x86_register::rsi), binary ? binary->name.c_str() : "<N/A>");
}
void windows_emulator::setup_hooks()
{
this->emu().hook_instruction(x64_hookable_instructions::syscall, [&] {
this->emu().hook_instruction(x86_hookable_instructions::syscall, [&] {
this->dispatcher.dispatch(*this);
return instruction_hook_continuation::skip_instruction;
});
this->emu().hook_instruction(x64_hookable_instructions::rdtsc, [&] {
this->emu().hook_instruction(x86_hookable_instructions::rdtsc, [&] {
const auto ticks = this->clock_->timestamp_counter();
this->emu().reg(x64_register::rax, ticks & 0xFFFFFFFF);
this->emu().reg(x64_register::rdx, (ticks >> 32) & 0xFFFFFFFF);
this->emu().reg(x86_register::rax, ticks & 0xFFFFFFFF);
this->emu().reg(x86_register::rdx, (ticks >> 32) & 0xFFFFFFFF);
return instruction_hook_continuation::skip_instruction;
});
this->emu().hook_instruction(x64_hookable_instructions::invalid, [&] {
this->emu().hook_instruction(x86_hookable_instructions::invalid, [&] {
const auto ip = this->emu().read_instruction_pointer();
this->log.print(color::gray, "Invalid instruction at: 0x%" PRIx64 " (via 0x%" PRIx64 ")\n", ip,

View File

@@ -1,7 +1,7 @@
#pragma once
#include "std_include.hpp"
#include <x64_emulator.hpp>
#include <arch_emulator.hpp>
#include <utils/function.hpp>
@@ -13,11 +13,11 @@
#include "module/module_manager.hpp"
#include "network/socket_factory.hpp"
std::unique_ptr<x64_emulator> create_default_x64_emulator();
std::unique_ptr<x86_64_emulator> create_default_x86_64_emulator();
struct emulator_callbacks : module_manager::callbacks, process_context::callbacks
{
utils::optional_function<instruction_hook_continuation(uint32_t syscall_id, x64_emulator::pointer_type address,
utils::optional_function<instruction_hook_continuation(uint32_t syscall_id, x86_64_emulator::pointer_type address,
std::string_view mod_name, std::string_view syscall_name)>
on_syscall{};
@@ -57,7 +57,7 @@ class windows_emulator
{
uint64_t executed_instructions_{0};
std::unique_ptr<x64_emulator> emu_{};
std::unique_ptr<x86_64_emulator> emu_{};
std::unique_ptr<utils::clock> clock_{};
std::unique_ptr<network::socket_factory> socket_factory_{};
@@ -74,10 +74,10 @@ class windows_emulator
windows_emulator(const emulator_settings& settings = {}, emulator_callbacks callbacks = {},
emulator_interfaces interfaces = {},
std::unique_ptr<x64_emulator> emu = create_default_x64_emulator());
std::unique_ptr<x86_64_emulator> emu = create_default_x86_64_emulator());
windows_emulator(application_settings app_settings, const emulator_settings& settings = {},
emulator_callbacks callbacks = {}, emulator_interfaces interfaces = {},
std::unique_ptr<x64_emulator> emu = create_default_x64_emulator());
std::unique_ptr<x86_64_emulator> emu = create_default_x86_64_emulator());
windows_emulator(windows_emulator&&) = delete;
windows_emulator(const windows_emulator&) = delete;
@@ -86,12 +86,12 @@ class windows_emulator
~windows_emulator();
x64_emulator& emu()
x86_64_emulator& emu()
{
return *this->emu_;
}
const x64_emulator& emu() const
const x86_64_emulator& emu() const
{
return *this->emu_;
}