mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-20 12:13:57 +00:00
Event manager progress
This commit is contained in:
@@ -1,2 +1,45 @@
|
||||
#include "std_include.hpp"
|
||||
#include "event_manager.hpp"
|
||||
#include "windows_emulator.hpp"
|
||||
|
||||
void syscall_event::print(generic_logger& log) const
|
||||
{
|
||||
auto& win = *this->win_emu;
|
||||
auto& emu = win.emu();
|
||||
|
||||
const auto address = emu.read_instruction_pointer();
|
||||
const auto* mod = win.mod_manager.find_by_address(address);
|
||||
|
||||
if (mod != win.mod_manager.ntdll && mod != win.mod_manager.win32u)
|
||||
{
|
||||
log.print(color::blue, "Executing inline syscall: %.*s (0x%X) at 0x%" PRIx64 " (%s)\n",
|
||||
static_cast<int>(this->data.name.size()), this->data.name.data(), this->data.id, address,
|
||||
mod ? mod->name.c_str() : "<N/A>");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mod->is_within(win_emu->process.previous_ip))
|
||||
{
|
||||
const auto rsp = emu.read_stack_pointer();
|
||||
|
||||
uint64_t return_address{};
|
||||
emu.try_read_memory(rsp, &return_address, sizeof(return_address));
|
||||
|
||||
const auto* caller_mod_name = win.mod_manager.find_name(return_address);
|
||||
|
||||
log.print(color::dark_gray, "Executing syscall: %.*s (0x%X) at 0x%" PRIx64 " via 0x%" PRIx64 " (%s)\n",
|
||||
static_cast<int>(this->data.name.size()), this->data.name.data(), this->data.id, address,
|
||||
return_address, caller_mod_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto* previous_mod = win.mod_manager.find_by_address(win.process.previous_ip);
|
||||
|
||||
log.print(color::blue,
|
||||
"Crafted out-of-line syscall: %.*s (0x%X) at 0x%" PRIx64 " (%s) via 0x%" PRIx64 " (%s)\n",
|
||||
static_cast<int>(this->data.name.size()), this->data.name.data(), this->data.id, address,
|
||||
mod ? mod->name.c_str() : "<N/A>", win.process.previous_ip,
|
||||
previous_mod ? previous_mod->name.c_str() : "<N/A>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,82 +2,98 @@
|
||||
#include "logger.hpp"
|
||||
|
||||
struct mapped_module;
|
||||
struct windows_emulator;
|
||||
class windows_emulator;
|
||||
|
||||
enum class event_type
|
||||
enum class emulation_event_type
|
||||
{
|
||||
syscall,
|
||||
function_call,
|
||||
};
|
||||
|
||||
struct event : utils::object
|
||||
struct emulation_event : utils::object
|
||||
{
|
||||
event() = default;
|
||||
emulation_event() = default;
|
||||
|
||||
event(event&&) = delete;
|
||||
event& operator=(event&&) = delete;
|
||||
event(const event&) = delete;
|
||||
event& operator=(const event&) = delete;
|
||||
emulation_event(emulation_event&&) = delete;
|
||||
emulation_event& operator=(emulation_event&&) = delete;
|
||||
emulation_event(const emulation_event&) = delete;
|
||||
emulation_event& operator=(const emulation_event&) = delete;
|
||||
|
||||
virtual event_type get_type() const = 0;
|
||||
virtual emulation_event_type get_type() const = 0;
|
||||
|
||||
virtual void print(const generic_logger& log) const
|
||||
virtual void print(generic_logger& log) const
|
||||
{
|
||||
(void)log;
|
||||
}
|
||||
};
|
||||
|
||||
template <event_type Type>
|
||||
struct typed_event : event
|
||||
template <emulation_event_type Type>
|
||||
struct typed_event : emulation_event
|
||||
{
|
||||
using event::event;
|
||||
using emulation_event::emulation_event;
|
||||
|
||||
event_type get_type() const override
|
||||
emulation_event_type get_type() const override
|
||||
{
|
||||
return Type;
|
||||
}
|
||||
};
|
||||
|
||||
template <event_type Type, typename Data>
|
||||
class rich_event : typed_event<Type>
|
||||
struct empty_data
|
||||
{
|
||||
};
|
||||
|
||||
template <emulation_event_type Type, typename Input = empty_data, typename Output = empty_data>
|
||||
class rich_event : public typed_event<Type>
|
||||
{
|
||||
public:
|
||||
rich_event(windows_emulator& win_emu, Data data)
|
||||
rich_event(windows_emulator& win_emu, Input input = {}, Output output = {})
|
||||
: win_emu(&win_emu),
|
||||
data(std::move(data))
|
||||
in(std::move(input))
|
||||
{
|
||||
}
|
||||
|
||||
const Data& get_data() const
|
||||
const Input& get_input() const
|
||||
{
|
||||
return this->data;
|
||||
return this->in;
|
||||
}
|
||||
|
||||
Output& get_output()
|
||||
{
|
||||
return this->out;
|
||||
}
|
||||
|
||||
const Output& get_output() const
|
||||
{
|
||||
return this->out;
|
||||
}
|
||||
|
||||
protected:
|
||||
windows_emulator* win_emu{};
|
||||
Data data{};
|
||||
Input in{};
|
||||
Output out{};
|
||||
};
|
||||
|
||||
struct syscall_data
|
||||
struct syscall_input
|
||||
{
|
||||
uint32_t id{};
|
||||
std::string_view name{};
|
||||
};
|
||||
|
||||
struct syscall_event : rich_event<event_type::syscall, syscall_data>
|
||||
struct syscall_output
|
||||
{
|
||||
struct extended_info
|
||||
{
|
||||
uint64_t address{};
|
||||
mapped_module* origin{};
|
||||
};
|
||||
bool skip{false};
|
||||
};
|
||||
|
||||
extended_info get_extended_info() const;
|
||||
struct syscall_event : rich_event<emulation_event_type::syscall, syscall_input, syscall_output>
|
||||
{
|
||||
using rich_event::rich_event;
|
||||
|
||||
void print(generic_logger& log) const override;
|
||||
};
|
||||
|
||||
struct event_manager : utils::object
|
||||
{
|
||||
virtual void handle(const event& e);
|
||||
virtual void handle(emulation_event& e);
|
||||
};
|
||||
|
||||
class printing_event_manager : public event_manager
|
||||
@@ -88,7 +104,7 @@ class printing_event_manager : public event_manager
|
||||
{
|
||||
}
|
||||
|
||||
void handle(const event& e) override
|
||||
void handle(emulation_event& e) override
|
||||
{
|
||||
e.print(*this->logger_);
|
||||
}
|
||||
|
||||
@@ -87,9 +87,14 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu)
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string_view mod_name = mod ? mod->name : std::string_view{};
|
||||
const auto res = win_emu.callbacks.on_syscall(syscall_id, address, mod_name, entry->second.name);
|
||||
if (res == instruction_hook_continuation::skip_instruction)
|
||||
syscall_event e(c.win_emu, {
|
||||
.id = syscall_id,
|
||||
.name = entry->second.name,
|
||||
});
|
||||
|
||||
c.win_emu.manager().handle(e);
|
||||
|
||||
if (e.get_output().skip)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -102,38 +107,6 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu)
|
||||
return;
|
||||
}
|
||||
|
||||
if (mod != win_emu.mod_manager.ntdll && mod != win_emu.mod_manager.win32u)
|
||||
{
|
||||
win_emu.log.print(color::blue, "Executing inline syscall: %s (0x%X) at 0x%" PRIx64 " (%s)\n",
|
||||
entry->second.name.c_str(), syscall_id, address, mod ? mod->name.c_str() : "<N/A>");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mod->is_within(context.previous_ip))
|
||||
{
|
||||
const auto rsp = c.emu.read_stack_pointer();
|
||||
|
||||
uint64_t return_address{};
|
||||
c.emu.try_read_memory(rsp, &return_address, sizeof(return_address));
|
||||
|
||||
const auto* caller_mod_name = win_emu.mod_manager.find_name(return_address);
|
||||
|
||||
win_emu.log.print(color::dark_gray,
|
||||
"Executing syscall: %s (0x%X) at 0x%" PRIx64 " via 0x%" PRIx64 " (%s)\n",
|
||||
entry->second.name.c_str(), syscall_id, address, return_address, caller_mod_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto* previous_mod = win_emu.mod_manager.find_by_address(context.previous_ip);
|
||||
|
||||
win_emu.log.print(color::blue,
|
||||
"Crafted out-of-line syscall: %s (0x%X) at 0x%" PRIx64 " (%s) via 0x%" PRIx64
|
||||
" (%s)\n",
|
||||
entry->second.name.c_str(), syscall_id, address, mod ? mod->name.c_str() : "<N/A>",
|
||||
context.previous_ip, previous_mod ? previous_mod->name.c_str() : "<N/A>");
|
||||
}
|
||||
}
|
||||
|
||||
entry->second.handler(c);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <utils/function.hpp>
|
||||
|
||||
#include "event_manager.hpp"
|
||||
#include "syscall_dispatcher.hpp"
|
||||
#include "process_context.hpp"
|
||||
#include "logger.hpp"
|
||||
@@ -15,10 +16,6 @@
|
||||
|
||||
struct emulator_callbacks : module_manager::callbacks, process_context::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)>
|
||||
on_syscall{};
|
||||
|
||||
utils::optional_function<void(std::string_view)> on_stdout{};
|
||||
};
|
||||
|
||||
@@ -58,6 +55,7 @@ class windows_emulator
|
||||
std::unique_ptr<x86_64_emulator> emu_{};
|
||||
std::unique_ptr<utils::clock> clock_{};
|
||||
std::unique_ptr<network::socket_factory> socket_factory_{};
|
||||
std::unique_ptr<event_manager> event_manager_{};
|
||||
|
||||
public:
|
||||
std::filesystem::path emulation_root{};
|
||||
@@ -93,6 +91,16 @@ class windows_emulator
|
||||
return *this->emu_;
|
||||
}
|
||||
|
||||
event_manager& manager()
|
||||
{
|
||||
return *this->event_manager_;
|
||||
}
|
||||
|
||||
event_manager& manager() const
|
||||
{
|
||||
return *this->event_manager_;
|
||||
}
|
||||
|
||||
utils::clock& clock()
|
||||
{
|
||||
return *this->clock_;
|
||||
|
||||
Reference in New Issue
Block a user