diff --git a/src/common/utils/function.hpp b/src/common/utils/function.hpp new file mode 100644 index 00000000..f7905232 --- /dev/null +++ b/src/common/utils/function.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include + +namespace utils +{ + template + class optional_function; + + template + class optional_function + { + private: + std::function func; + + public: + optional_function() = default; + + optional_function(std::function f) + : func(std::move(f)) + { + } + + template >> + optional_function(F&& f) + : func(std::forward(f)) + { + } + + optional_function& operator=(std::function f) + { + func = std::move(f); + return *this; + } + + Ret operator()(Args... args) const + { + if (func) + { + return func(std::forward(args)...); + } + + if constexpr (!std::is_void_v) + { + return Ret(); + } + } + + explicit operator bool() const noexcept + { + return static_cast(func); + } + }; +} diff --git a/src/emulator/CMakeLists.txt b/src/emulator/CMakeLists.txt index 15e1395a..8069d238 100644 --- a/src/emulator/CMakeLists.txt +++ b/src/emulator/CMakeLists.txt @@ -8,4 +8,5 @@ list(SORT SRC_FILES) add_library(emulator ${SRC_FILES}) +target_link_libraries(emulator PUBLIC emulator-common) target_include_directories(emulator INTERFACE "${CMAKE_CURRENT_LIST_DIR}") diff --git a/src/windows-emulator/CMakeLists.txt b/src/windows-emulator/CMakeLists.txt index b0510952..a623de76 100644 --- a/src/windows-emulator/CMakeLists.txt +++ b/src/windows-emulator/CMakeLists.txt @@ -16,10 +16,7 @@ target_link_libraries(windows-emulator PRIVATE unicorn-emulator ) -target_link_libraries(windows-emulator PUBLIC - emulator-common - emulator -) +target_link_libraries(windows-emulator PUBLIC emulator) target_include_directories(windows-emulator INTERFACE "${CMAKE_CURRENT_LIST_DIR}") diff --git a/src/windows-emulator/syscall_dispatcher.cpp b/src/windows-emulator/syscall_dispatcher.cpp index 6c6cc08e..1ed7581c 100644 --- a/src/windows-emulator/syscall_dispatcher.cpp +++ b/src/windows-emulator/syscall_dispatcher.cpp @@ -91,8 +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.callbacks().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() : ""); } @@ -111,9 +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.callbacks().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/syscalls.cpp b/src/windows-emulator/syscalls.cpp index 90265798..614670f3 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -2681,7 +2681,7 @@ namespace temp_buffer.push_back('\n'); } - c.win_emu.on_stdout(temp_buffer); + c.win_emu.callbacks().stdout_callback(temp_buffer); c.win_emu.log.info("%.*s", static_cast(temp_buffer.size()), temp_buffer.data()); return STATUS_SUCCESS; diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index 559b3175..e7f7500c 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -1141,30 +1141,3 @@ 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 36f0f9b2..2f524a07 100644 --- a/src/windows-emulator/windows_emulator.hpp +++ b/src/windows-emulator/windows_emulator.hpp @@ -3,6 +3,8 @@ #include +#include + #include "syscall_dispatcher.hpp" #include "process_context.hpp" #include "logger.hpp" @@ -11,13 +13,13 @@ std::unique_ptr create_default_x64_emulator(); struct emulator_callbacks { - std::function stdout_callback{}; - std::function + utils::optional_function stdout_callback{}; + utils::optional_function inline_syscall{}; - std::function + utils::optional_function outofline_syscall{}; }; @@ -108,13 +110,6 @@ class windows_emulator this->syscall_hooks_.push_back(std::move(callback)); } - 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}; bool verbose_calls{false}; @@ -131,6 +126,11 @@ class windows_emulator return this->use_relative_time_; } + emulator_callbacks& callbacks() + { + return this->callbacks_; + } + private: emulator_callbacks callbacks_{}; bool use_relative_time_{false};