exposing high level callbacks to win_emu

This commit is contained in:
Elias Bachaalany
2025-01-14 22:59:41 -08:00
parent f9f980fbc5
commit e50eb96470
5 changed files with 62 additions and 15 deletions

View File

@@ -20,10 +20,10 @@
namespace test
{
inline windows_emulator create_sample_emulator(emulator_settings settings)
inline windows_emulator create_sample_emulator(emulator_settings settings, emulator_callbacks callbacks = {})
{
settings.application = "./test-sample.exe";
return windows_emulator{std::move(settings)};
return windows_emulator{std::move(settings), std::move(callbacks)};
}
inline windows_emulator create_sample_emulator()

View File

@@ -6,14 +6,17 @@ namespace test
{
std::string output_buffer{};
emulator_callbacks callbacks{
.stdout_callback = [&output_buffer](const std::string_view data) { output_buffer.append(data); },
};
const emulator_settings settings{
.arguments = {u"-time"},
.stdout_callback = [&output_buffer](const std::string_view data) { output_buffer.append(data); },
.disable_logging = true,
.use_relative_time = false,
};
auto emu = create_sample_emulator(settings);
auto emu = create_sample_emulator(settings, callbacks);
emu.start();
constexpr auto prefix = "Time: "sv;

View File

@@ -91,6 +91,8 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu)
const auto* mod = context.mod_manager.find_by_address(address);
if (mod != context.ntdll && mod != context.win32u)
{
win_emu.on_inline_syscall(syscall_id, address, mod ? mod->name.c_str() : "<N/A>",
entry->second.name.c_str());
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>");
}
@@ -109,6 +111,9 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu)
else
{
const auto* previous_mod = context.mod_manager.find_by_address(context.previous_ip);
win_emu.on_outofline_syscall(syscall_id, address, mod ? mod->name.c_str() : "<N/A>",
entry->second.name.c_str(), context.previous_ip,
previous_mod ? previous_mod->name.c_str() : "<N/A>");
win_emu.log.print(color::blue,
"Crafted out-of-line syscall: %s (0x%X) at 0x%" PRIx64 " (%s) via 0x%" PRIx64
" (%s)\n",

View File

@@ -742,13 +742,14 @@ std::unique_ptr<x64_emulator> create_default_x64_emulator()
return unicorn::create_x64_emulator();
}
windows_emulator::windows_emulator(emulator_settings settings, std::unique_ptr<x64_emulator> emu)
windows_emulator::windows_emulator(emulator_settings settings, emulator_callbacks callbacks,
std::unique_ptr<x64_emulator> emu)
: windows_emulator(std::move(emu))
{
this->silent_until_main_ = settings.silent_until_main && !settings.disable_logging;
this->stdout_callback_ = std::move(settings.stdout_callback);
this->use_relative_time_ = settings.use_relative_time;
this->log.disable_output(settings.disable_logging || this->silent_until_main_);
this->callbacks_ = std::move(callbacks);
this->setup_process(settings);
}
@@ -1054,3 +1055,30 @@ void windows_emulator::restore_snapshot()
this->process_.deserialize(deserializer);
// this->process_ = *this->process_snapshot_;
}
void windows_emulator::on_stdout(const std::string_view data) const
{
if (this->callbacks_.stdout_callback)
{
this->callbacks_.stdout_callback(data);
}
}
void windows_emulator::on_inline_syscall(uint32_t syscall_id, const x64_emulator::pointer_type address,
const std::string_view mod_name, const std::string_view name)
{
if (this->callbacks_.inline_syscall)
{
this->callbacks_.inline_syscall(syscall_id, address, mod_name, name);
}
}
void windows_emulator::on_outofline_syscall(uint32_t syscall_id, x64_emulator::pointer_type address,
std::string_view mod_name, std::string_view syscall_name,
x64_emulator::pointer_type prev_address, std::string_view prev_mod_name)
{
if (this->callbacks_.outofline_syscall)
{
this->callbacks_.outofline_syscall(syscall_id, address, mod_name, syscall_name, prev_address, prev_mod_name);
}
}

View File

@@ -9,6 +9,17 @@
std::unique_ptr<x64_emulator> create_default_x64_emulator();
struct emulator_callbacks
{
std::function<void(std::string_view)> stdout_callback{};
std::function<void(uint32_t syscall_id, x64_emulator::pointer_type address, std::string_view mod_name,
std::string_view syscall_name)>
inline_syscall{};
std::function<void(uint32_t syscall_id, x64_emulator::pointer_type address, std::string_view mod_name,
std::string_view syscall_name, x64_emulator::pointer_type prev_address, std::string_view prev_mod_name)>
outofline_syscall{};
};
// TODO: Split up into application and emulator settings
struct emulator_settings
{
@@ -16,7 +27,6 @@ struct emulator_settings
std::filesystem::path working_directory{};
std::filesystem::path registry_directory{"./registry"};
std::vector<std::u16string> arguments{};
std::function<void(std::string_view)> stdout_callback{};
bool disable_logging{false};
bool silent_until_main{false};
bool use_relative_time{false};
@@ -26,7 +36,8 @@ class windows_emulator
{
public:
windows_emulator(std::unique_ptr<x64_emulator> emu = create_default_x64_emulator());
windows_emulator(emulator_settings settings, std::unique_ptr<x64_emulator> emu = create_default_x64_emulator());
windows_emulator(emulator_settings settings, emulator_callbacks callbacks = {},
std::unique_ptr<x64_emulator> emu = create_default_x64_emulator());
windows_emulator(windows_emulator&&) = delete;
windows_emulator(const windows_emulator&) = delete;
@@ -88,13 +99,12 @@ class windows_emulator
this->syscall_hooks_.push_back(std::move(callback));
}
void on_stdout(const std::string_view data) const
{
if (this->stdout_callback_)
{
this->stdout_callback_(data);
}
}
void on_stdout(const std::string_view data) const;
void on_inline_syscall(uint32_t syscall_id, const x64_emulator::pointer_type address,
const std::string_view mod_name, const std::string_view name);
void on_outofline_syscall(uint32_t syscall_id, x64_emulator::pointer_type address, std::string_view mod_name,
std::string_view syscall_name, x64_emulator::pointer_type prev_address,
std::string_view prev_mod_name);
logger log{};
bool verbose{false};
@@ -112,6 +122,7 @@ class windows_emulator
}
private:
emulator_callbacks callbacks_{};
bool use_relative_time_{false};
bool silent_until_main_{false};
std::unique_ptr<x64_emulator> emu_{};