diff --git a/src/windows-emulator-test/emulation_test_utils.hpp b/src/windows-emulator-test/emulation_test_utils.hpp index 15bf4858..40fec6ea 100644 --- a/src/windows-emulator-test/emulation_test_utils.hpp +++ b/src/windows-emulator-test/emulation_test_utils.hpp @@ -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() diff --git a/src/windows-emulator-test/time_test.cpp b/src/windows-emulator-test/time_test.cpp index 00158a05..38555971 100644 --- a/src/windows-emulator-test/time_test.cpp +++ b/src/windows-emulator-test/time_test.cpp @@ -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; diff --git a/src/windows-emulator/syscall_dispatcher.cpp b/src/windows-emulator/syscall_dispatcher.cpp index 118df673..6c6cc08e 100644 --- a/src/windows-emulator/syscall_dispatcher.cpp +++ b/src/windows-emulator/syscall_dispatcher.cpp @@ -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() : "", + 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() : ""); } @@ -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() : "", + entry->second.name.c_str(), context.previous_ip, + previous_mod ? previous_mod->name.c_str() : ""); win_emu.log.print(color::blue, "Crafted out-of-line syscall: %s (0x%X) at 0x%" PRIx64 " (%s) via 0x%" PRIx64 " (%s)\n", diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index 2b0bb14d..b06548e7 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -742,13 +742,14 @@ std::unique_ptr create_default_x64_emulator() return unicorn::create_x64_emulator(); } -windows_emulator::windows_emulator(emulator_settings settings, std::unique_ptr emu) +windows_emulator::windows_emulator(emulator_settings settings, emulator_callbacks callbacks, + std::unique_ptr 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); + } +} diff --git a/src/windows-emulator/windows_emulator.hpp b/src/windows-emulator/windows_emulator.hpp index d4e35f96..e2ced33d 100644 --- a/src/windows-emulator/windows_emulator.hpp +++ b/src/windows-emulator/windows_emulator.hpp @@ -9,6 +9,17 @@ std::unique_ptr create_default_x64_emulator(); +struct emulator_callbacks +{ + std::function stdout_callback{}; + std::function + inline_syscall{}; + std::function + 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 arguments{}; - std::function 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 emu = create_default_x64_emulator()); - windows_emulator(emulator_settings settings, std::unique_ptr emu = create_default_x64_emulator()); + windows_emulator(emulator_settings settings, emulator_callbacks callbacks = {}, + std::unique_ptr 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 emu_{};