mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-09 23:56:16 +00:00
partial process_context abstraction
This commit is contained in:
@@ -20,7 +20,7 @@ namespace
|
||||
win_emu.log.disable_output(true);
|
||||
win_emu.start();
|
||||
|
||||
if (win_emu.process.exception_rip.has_value())
|
||||
if (win_emu.process.exception_ip.has_value())
|
||||
{
|
||||
throw std::runtime_error("Exception!");
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace
|
||||
emu.reg(x86_register::rsp, stack_end);
|
||||
}
|
||||
|
||||
bool is_object_signaled(process_context& c, const handle h, const uint32_t current_thread_id)
|
||||
bool is_object_signaled(process_context64& c, const handle h, const uint32_t current_thread_id)
|
||||
{
|
||||
const auto type = h.value.type;
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
emulator_thread::emulator_thread(memory_manager& memory, const process_context& context, const uint64_t start_address,
|
||||
emulator_thread::emulator_thread(memory_manager& memory, const process_context64& context, const uint64_t start_address,
|
||||
const uint64_t argument, const uint64_t stack_size, const bool suspended,
|
||||
const uint32_t id)
|
||||
: memory_ptr(&memory),
|
||||
@@ -139,7 +139,7 @@ bool emulator_thread::is_terminated() const
|
||||
return this->exit_status.has_value();
|
||||
}
|
||||
|
||||
bool emulator_thread::is_thread_ready(process_context& process, utils::clock& clock)
|
||||
bool emulator_thread::is_thread_ready(process_context64& process, utils::clock& clock)
|
||||
{
|
||||
if (this->is_terminated() || this->suspended > 0)
|
||||
{
|
||||
@@ -208,7 +208,7 @@ bool emulator_thread::is_thread_ready(process_context& process, utils::clock& cl
|
||||
return true;
|
||||
}
|
||||
|
||||
void emulator_thread::setup_registers(x86_64_emulator& emu, const process_context& context) const
|
||||
void emulator_thread::setup_registers(x86_64_emulator& emu, const process_context64& context) const
|
||||
{
|
||||
if (!this->gs_segment)
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#include <utils/moved_marker.hpp>
|
||||
|
||||
struct process_context;
|
||||
struct process_context64;
|
||||
|
||||
struct pending_apc
|
||||
{
|
||||
@@ -48,7 +48,7 @@ class emulator_thread : public ref_counted_object
|
||||
{
|
||||
}
|
||||
|
||||
emulator_thread(memory_manager& memory, const process_context& context, uint64_t start_address, uint64_t argument,
|
||||
emulator_thread(memory_manager& memory, const process_context64& context, uint64_t start_address, uint64_t argument,
|
||||
uint64_t stack_size, bool suspended, uint32_t id);
|
||||
|
||||
emulator_thread(const emulator_thread&) = delete;
|
||||
@@ -103,7 +103,7 @@ class emulator_thread : public ref_counted_object
|
||||
|
||||
bool is_terminated() const;
|
||||
|
||||
bool is_thread_ready(process_context& process, utils::clock& clock);
|
||||
bool is_thread_ready(process_context64& process, utils::clock& clock);
|
||||
|
||||
void save(x86_64_emulator& emu)
|
||||
{
|
||||
@@ -115,7 +115,7 @@ class emulator_thread : public ref_counted_object
|
||||
emu.restore_registers(this->last_registers);
|
||||
}
|
||||
|
||||
void setup_if_necessary(x86_64_emulator& emu, const process_context& context)
|
||||
void setup_if_necessary(x86_64_emulator& emu, const process_context64& context)
|
||||
{
|
||||
if (!this->executed_instructions)
|
||||
{
|
||||
@@ -211,7 +211,7 @@ class emulator_thread : public ref_counted_object
|
||||
}
|
||||
|
||||
private:
|
||||
void setup_registers(x86_64_emulator& emu, const process_context& context) const;
|
||||
void setup_registers(x86_64_emulator& emu, const process_context64& context) const;
|
||||
|
||||
void release()
|
||||
{
|
||||
|
||||
@@ -140,7 +140,7 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
void dispatch_exception(x86_64_emulator& emu, const process_context& proc, const DWORD status,
|
||||
void dispatch_exception(x86_64_emulator& emu, const process_context64& proc, const DWORD status,
|
||||
const std::vector<EmulatorTraits<Emu64>::ULONG_PTR>& parameters)
|
||||
{
|
||||
CONTEXT64 ctx{};
|
||||
@@ -172,7 +172,7 @@ void dispatch_exception(x86_64_emulator& emu, const process_context& proc, const
|
||||
dispatch_exception_pointers(emu, proc.ki_user_exception_dispatcher, pointers);
|
||||
}
|
||||
|
||||
void dispatch_access_violation(x86_64_emulator& emu, const process_context& proc, const uint64_t address,
|
||||
void dispatch_access_violation(x86_64_emulator& emu, const process_context64& proc, const uint64_t address,
|
||||
const memory_operation operation)
|
||||
{
|
||||
dispatch_exception(emu, proc, STATUS_ACCESS_VIOLATION,
|
||||
@@ -182,22 +182,22 @@ void dispatch_access_violation(x86_64_emulator& emu, const process_context& proc
|
||||
});
|
||||
}
|
||||
|
||||
void dispatch_illegal_instruction_violation(x86_64_emulator& emu, const process_context& proc)
|
||||
void dispatch_illegal_instruction_violation(x86_64_emulator& emu, const process_context64& proc)
|
||||
{
|
||||
dispatch_exception(emu, proc, STATUS_ILLEGAL_INSTRUCTION, {});
|
||||
}
|
||||
|
||||
void dispatch_integer_division_by_zero(x86_64_emulator& emu, const process_context& proc)
|
||||
void dispatch_integer_division_by_zero(x86_64_emulator& emu, const process_context64& proc)
|
||||
{
|
||||
dispatch_exception(emu, proc, STATUS_INTEGER_DIVIDE_BY_ZERO, {});
|
||||
}
|
||||
|
||||
void dispatch_single_step(x86_64_emulator& emu, const process_context& proc)
|
||||
void dispatch_single_step(x86_64_emulator& emu, const process_context64& proc)
|
||||
{
|
||||
dispatch_exception(emu, proc, STATUS_SINGLE_STEP, {});
|
||||
}
|
||||
|
||||
void dispatch_breakpoint(x86_64_emulator& emu, const process_context& proc)
|
||||
void dispatch_breakpoint(x86_64_emulator& emu, const process_context64& proc)
|
||||
{
|
||||
dispatch_exception(emu, proc, STATUS_BREAKPOINT, {});
|
||||
}
|
||||
|
||||
@@ -5,21 +5,21 @@
|
||||
#include <platform/traits.hpp>
|
||||
#include <platform/primitives.hpp>
|
||||
|
||||
struct process_context;
|
||||
struct process_context64;
|
||||
|
||||
void dispatch_exception(x86_64_emulator& emu, const process_context& proc, DWORD status,
|
||||
void dispatch_exception(x86_64_emulator& emu, const process_context64& 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(x86_64_emulator& emu, const process_context& proc, const T status,
|
||||
void dispatch_exception(x86_64_emulator& emu, const process_context64& 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(x86_64_emulator& emu, const process_context& proc, uint64_t address,
|
||||
void dispatch_access_violation(x86_64_emulator& emu, const process_context64& proc, uint64_t address,
|
||||
memory_operation operation);
|
||||
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);
|
||||
void dispatch_illegal_instruction_violation(x86_64_emulator& emu, const process_context64& proc);
|
||||
void dispatch_integer_division_by_zero(x86_64_emulator& emu, const process_context64& proc);
|
||||
void dispatch_single_step(x86_64_emulator& emu, const process_context64& proc);
|
||||
void dispatch_breakpoint(x86_64_emulator& emu, const process_context64& proc);
|
||||
|
||||
@@ -27,9 +27,9 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
void process_context64::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)
|
||||
{
|
||||
setup_gdt(emu, memory);
|
||||
|
||||
@@ -125,7 +125,7 @@ void process_context::setup(x86_64_emulator& emu, memory_manager& memory, const
|
||||
this->default_register_set = emu.save_registers();
|
||||
}
|
||||
|
||||
void process_context::serialize(utils::buffer_serializer& buffer) const
|
||||
void process_context64::serialize(utils::buffer_serializer& buffer) const
|
||||
{
|
||||
buffer.write(this->current_ip);
|
||||
buffer.write(this->previous_ip);
|
||||
@@ -133,7 +133,7 @@ void process_context::serialize(utils::buffer_serializer& buffer) const
|
||||
buffer.write(this->shared_section_size);
|
||||
buffer.write(this->dbwin_buffer);
|
||||
buffer.write(this->dbwin_buffer_size);
|
||||
buffer.write_optional(this->exception_rip);
|
||||
buffer.write_optional(this->exception_ip);
|
||||
buffer.write_optional(this->exit_status);
|
||||
buffer.write(this->base_allocator);
|
||||
buffer.write(this->peb);
|
||||
@@ -163,7 +163,7 @@ void process_context::serialize(utils::buffer_serializer& buffer) const
|
||||
buffer.write(this->threads.find_handle(this->active_thread).bits);
|
||||
}
|
||||
|
||||
void process_context::deserialize(utils::buffer_deserializer& buffer)
|
||||
void process_context64::deserialize(utils::buffer_deserializer& buffer)
|
||||
{
|
||||
buffer.read(this->current_ip);
|
||||
buffer.read(this->previous_ip);
|
||||
@@ -171,7 +171,7 @@ void process_context::deserialize(utils::buffer_deserializer& buffer)
|
||||
buffer.read(this->shared_section_size);
|
||||
buffer.read(this->dbwin_buffer);
|
||||
buffer.read(this->dbwin_buffer_size);
|
||||
buffer.read_optional(this->exception_rip);
|
||||
buffer.read_optional(this->exception_ip);
|
||||
buffer.read_optional(this->exit_status);
|
||||
buffer.read(this->base_allocator);
|
||||
buffer.read(this->peb);
|
||||
@@ -207,7 +207,7 @@ void process_context::deserialize(utils::buffer_deserializer& buffer)
|
||||
this->active_thread = this->threads.get(buffer.read<uint64_t>());
|
||||
}
|
||||
|
||||
generic_handle_store* process_context::get_handle_store(const handle handle)
|
||||
generic_handle_store* process_context64::get_handle_store(const handle handle)
|
||||
{
|
||||
switch (handle.value.type)
|
||||
{
|
||||
@@ -234,8 +234,8 @@ generic_handle_store* process_context::get_handle_store(const handle handle)
|
||||
}
|
||||
}
|
||||
|
||||
handle process_context::create_thread(memory_manager& memory, const uint64_t start_address, const uint64_t argument,
|
||||
const uint64_t stack_size, const bool suspended)
|
||||
handle process_context64::create_thread(memory_manager& memory, const uint64_t start_address, const uint64_t argument,
|
||||
const uint64_t stack_size, const bool suspended)
|
||||
{
|
||||
emulator_thread t{memory, *this, start_address, argument, stack_size, suspended, ++this->spawned_thread_count};
|
||||
auto [h, thr] = this->threads.store_and_get(std::move(t));
|
||||
@@ -243,7 +243,9 @@ handle process_context::create_thread(memory_manager& memory, const uint64_t sta
|
||||
return h;
|
||||
}
|
||||
|
||||
uint16_t process_context::add_or_find_atom(std::u16string name)
|
||||
// --[ process_context_common ]-----------------------------------------------------------------------------------------
|
||||
|
||||
uint16_t process_context_common::add_or_find_atom(std::u16string name)
|
||||
{
|
||||
uint16_t index = 0;
|
||||
if (!atoms.empty())
|
||||
@@ -286,7 +288,7 @@ uint16_t process_context::add_or_find_atom(std::u16string name)
|
||||
return index;
|
||||
}
|
||||
|
||||
bool process_context::delete_atom(const std::u16string& name)
|
||||
bool process_context_common::delete_atom(const std::u16string& name)
|
||||
{
|
||||
for (auto it = atoms.begin(); it != atoms.end(); ++it)
|
||||
{
|
||||
@@ -303,7 +305,7 @@ bool process_context::delete_atom(const std::u16string& name)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool process_context::delete_atom(uint16_t atom_id)
|
||||
bool process_context_common::delete_atom(uint16_t atom_id)
|
||||
{
|
||||
const auto it = atoms.find(atom_id);
|
||||
if (it == atoms.end())
|
||||
@@ -319,7 +321,7 @@ bool process_context::delete_atom(uint16_t atom_id)
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::u16string* process_context::get_atom_name(uint16_t atom_id) const
|
||||
const std::u16string* process_context_common::get_atom_name(uint16_t atom_id) const
|
||||
{
|
||||
const auto it = atoms.find(atom_id);
|
||||
if (it == atoms.end())
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
struct emulator_settings;
|
||||
struct application_settings;
|
||||
|
||||
struct process_context
|
||||
struct process_context_common
|
||||
{
|
||||
struct callbacks
|
||||
{
|
||||
@@ -50,7 +50,44 @@ struct process_context
|
||||
atom_entry() = default;
|
||||
};
|
||||
|
||||
process_context(x86_64_emulator& emu, memory_manager& memory, utils::clock& clock, callbacks& cb)
|
||||
std::map<uint16_t, atom_entry> atoms{};
|
||||
uint16_t add_or_find_atom(std::u16string name);
|
||||
bool delete_atom(const std::u16string& name);
|
||||
bool delete_atom(uint16_t atom_id);
|
||||
const std::u16string* get_atom_name(uint16_t atom_id) const;
|
||||
|
||||
uint64_t current_ip{0};
|
||||
uint64_t previous_ip{0};
|
||||
|
||||
uint64_t shared_section_address{0};
|
||||
uint64_t shared_section_size{0};
|
||||
uint64_t dbwin_buffer{0};
|
||||
uint64_t dbwin_buffer_size{0};
|
||||
|
||||
std::optional<NTSTATUS> exit_status{};
|
||||
|
||||
uint64_t ntdll_image_base{};
|
||||
uint64_t ldr_initialize_thunk{};
|
||||
uint64_t rtl_user_thread_start{};
|
||||
uint64_t ki_user_apc_dispatcher{};
|
||||
uint64_t ki_user_exception_dispatcher{};
|
||||
|
||||
std::optional<uint64_t> exception_ip{};
|
||||
|
||||
handle_store<handle_types::event, event> events{};
|
||||
handle_store<handle_types::file, file> files{};
|
||||
handle_store<handle_types::section, section> sections{};
|
||||
handle_store<handle_types::semaphore, semaphore> semaphores{};
|
||||
handle_store<handle_types::port, port> ports{};
|
||||
handle_store<handle_types::mutant, mutant> mutants{};
|
||||
handle_store<handle_types::registry, registry_key, 2> registry_keys{};
|
||||
|
||||
std::vector<std::byte> default_register_set{};
|
||||
};
|
||||
|
||||
struct process_context64 final : process_context_common
|
||||
{
|
||||
process_context64(x86_64_emulator& emu, memory_manager& memory, utils::clock& clock, callbacks& cb)
|
||||
: callbacks_(&cb),
|
||||
base_allocator(emu),
|
||||
peb(emu),
|
||||
@@ -65,11 +102,6 @@ struct process_context
|
||||
handle create_thread(memory_manager& memory, uint64_t start_address, uint64_t argument, uint64_t stack_size,
|
||||
bool suspended);
|
||||
|
||||
uint16_t add_or_find_atom(std::u16string name);
|
||||
bool delete_atom(const std::u16string& name);
|
||||
bool delete_atom(uint16_t atom_id);
|
||||
const std::u16string* get_atom_name(uint16_t atom_id) const;
|
||||
|
||||
void serialize(utils::buffer_serializer& buffer) const;
|
||||
void deserialize(utils::buffer_deserializer& buffer);
|
||||
|
||||
@@ -77,40 +109,13 @@ struct process_context
|
||||
|
||||
callbacks* callbacks_{};
|
||||
|
||||
uint64_t current_ip{0};
|
||||
uint64_t previous_ip{0};
|
||||
|
||||
uint64_t shared_section_address{0};
|
||||
uint64_t shared_section_size{0};
|
||||
uint64_t dbwin_buffer{0};
|
||||
uint64_t dbwin_buffer_size{0};
|
||||
|
||||
std::optional<uint64_t> exception_rip{};
|
||||
std::optional<NTSTATUS> exit_status{};
|
||||
|
||||
emulator_allocator base_allocator;
|
||||
|
||||
emulator_object<PEB64> peb;
|
||||
emulator_object<RTL_USER_PROCESS_PARAMETERS64> process_params;
|
||||
kusd_mmio kusd;
|
||||
|
||||
uint64_t ntdll_image_base{};
|
||||
uint64_t ldr_initialize_thunk{};
|
||||
uint64_t rtl_user_thread_start{};
|
||||
uint64_t ki_user_apc_dispatcher{};
|
||||
uint64_t ki_user_exception_dispatcher{};
|
||||
|
||||
handle_store<handle_types::event, event> events{};
|
||||
handle_store<handle_types::file, file> files{};
|
||||
handle_store<handle_types::section, section> sections{};
|
||||
handle_store<handle_types::device, io_device_container> devices{};
|
||||
handle_store<handle_types::semaphore, semaphore> semaphores{};
|
||||
handle_store<handle_types::port, port> ports{};
|
||||
handle_store<handle_types::mutant, mutant> mutants{};
|
||||
handle_store<handle_types::registry, registry_key, 2> registry_keys{};
|
||||
std::map<uint16_t, atom_entry> atoms{};
|
||||
|
||||
std::vector<std::byte> default_register_set{};
|
||||
|
||||
uint32_t spawned_thread_count{0};
|
||||
handle_store<handle_types::thread, emulator_thread> threads{};
|
||||
|
||||
@@ -8,7 +8,7 @@ struct syscall_context
|
||||
{
|
||||
windows_emulator& win_emu;
|
||||
x86_64_emulator& emu;
|
||||
process_context& proc;
|
||||
process_context64& proc;
|
||||
mutable bool write_status{true};
|
||||
mutable bool retrigger_syscall{false};
|
||||
};
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace syscalls
|
||||
}
|
||||
|
||||
c.proc.exit_status = error_status;
|
||||
c.proc.exception_rip = c.emu.read_instruction_pointer();
|
||||
c.proc.exception_ip = c.emu.read_instruction_pointer();
|
||||
c.emu.stop();
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
@@ -36,7 +36,7 @@ namespace syscalls
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
c.proc.exception_rip = thread_context.read().Rip;
|
||||
c.proc.exception_ip = thread_context.read().Rip;
|
||||
c.emu.stop();
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
emulator_thread* get_thread_by_id(process_context& process, const uint32_t id)
|
||||
emulator_thread* get_thread_by_id(process_context64& process, const uint32_t id)
|
||||
{
|
||||
for (auto& t : process.threads | std::views::values)
|
||||
{
|
||||
@@ -540,7 +540,7 @@ void windows_emulator::setup_hooks()
|
||||
|
||||
if (this->fuzzing || true) // TODO: Fix
|
||||
{
|
||||
this->process.exception_rip = rip;
|
||||
this->process.exception_ip = rip;
|
||||
this->emu().stop();
|
||||
}
|
||||
});
|
||||
@@ -564,7 +564,7 @@ void windows_emulator::setup_hooks()
|
||||
|
||||
if (this->fuzzing)
|
||||
{
|
||||
this->process.exception_rip = ip;
|
||||
this->process.exception_ip = ip;
|
||||
this->emu().stop();
|
||||
return memory_violation_continuation::stop;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
std::unique_ptr<x86_64_emulator> create_default_x86_64_emulator();
|
||||
|
||||
struct emulator_callbacks : module_manager::callbacks, process_context::callbacks
|
||||
struct emulator_callbacks : module_manager::callbacks, process_context64::callbacks
|
||||
{
|
||||
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)>
|
||||
@@ -69,7 +69,7 @@ class windows_emulator
|
||||
memory_manager memory;
|
||||
registry_manager registry{};
|
||||
module_manager mod_manager;
|
||||
process_context process;
|
||||
process_context64 process;
|
||||
syscall_dispatcher dispatcher;
|
||||
|
||||
windows_emulator(const emulator_settings& settings = {}, emulator_callbacks callbacks = {},
|
||||
|
||||
Reference in New Issue
Block a user