diff --git a/src/analyzer/analysis.cpp b/src/analyzer/analysis.cpp new file mode 100644 index 00000000..de307274 --- /dev/null +++ b/src/analyzer/analysis.cpp @@ -0,0 +1,64 @@ +#include "analysis.hpp" +#include "windows_emulator.hpp" + +namespace +{ + emulator_callbacks::continuation handle_syscall(windows_emulator& win_emu, const uint32_t syscall_id, + const std::string_view syscall_name) + { + auto& emu = win_emu.emu(); + + const auto address = emu.read_instruction_pointer(); + const auto* mod = win_emu.mod_manager.find_by_address(address); + const auto is_sus_module = mod != win_emu.mod_manager.ntdll && mod != win_emu.mod_manager.win32u; + + if (is_sus_module) + { + win_emu.log.print(color::blue, "Executing inline syscall: %.*s (0x%X) at 0x%" PRIx64 " (%s)\n", + static_cast(syscall_name.size()), syscall_name.data(), syscall_id, address, + mod ? mod->name.c_str() : ""); + } + 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_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", + static_cast(syscall_name.size()), syscall_name.data(), syscall_id, address, + return_address, caller_mod_name); + } + else + { + const auto* previous_mod = win_emu.mod_manager.find_by_address(win_emu.process.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", + static_cast(syscall_name.size()), syscall_name.data(), syscall_id, address, + mod ? mod->name.c_str() : "", win_emu.process.previous_ip, + previous_mod ? previous_mod->name.c_str() : ""); + } + + return instruction_hook_continuation::run_instruction; + } + + template + std::function make_callback(windows_emulator& win_emu, + Return (*callback)(windows_emulator&, Args...)) + { + return [&win_emu, callback](Args... args) { + return callback(win_emu, std::forward(args)...); // + }; + } +} + +void register_analysis_callbacks(windows_emulator& win_emu) +{ + auto& cb = win_emu.callbacks; + + cb.on_syscall = make_callback(win_emu, handle_syscall); +} diff --git a/src/analyzer/analysis.hpp b/src/analyzer/analysis.hpp new file mode 100644 index 00000000..e5cc8050 --- /dev/null +++ b/src/analyzer/analysis.hpp @@ -0,0 +1,5 @@ +#pragma once + +class windows_emulator; + +void register_analysis_callbacks(windows_emulator& win_emu); diff --git a/src/windows-emulator/event_manager.cpp b/src/windows-emulator/event_manager.cpp deleted file mode 100644 index 805d3ff4..00000000 --- a/src/windows-emulator/event_manager.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#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(this->data.name.size()), this->data.name.data(), this->data.id, address, - mod ? mod->name.c_str() : ""); - } - 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(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(this->data.name.size()), this->data.name.data(), this->data.id, address, - mod ? mod->name.c_str() : "", win.process.previous_ip, - previous_mod ? previous_mod->name.c_str() : ""); - } - } -} diff --git a/src/windows-emulator/event_manager.hpp b/src/windows-emulator/event_manager.hpp deleted file mode 100644 index 91987688..00000000 --- a/src/windows-emulator/event_manager.hpp +++ /dev/null @@ -1,114 +0,0 @@ -#pragma once -#include "logger.hpp" - -struct mapped_module; -class windows_emulator; - -enum class emulation_event_type -{ - syscall, - function_call, -}; - -struct emulation_event : utils::object -{ - emulation_event() = default; - - 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 emulation_event_type get_type() const = 0; - - virtual void print(generic_logger& log) const - { - (void)log; - } -}; - -template -struct typed_event : emulation_event -{ - using emulation_event::emulation_event; - - emulation_event_type get_type() const override - { - return Type; - } -}; - -struct empty_data -{ -}; - -template -class rich_event : public typed_event -{ - public: - rich_event(windows_emulator& win_emu, Input input = {}, Output output = {}) - : win_emu(&win_emu), - in(std::move(input)) - { - } - - const Input& get_input() const - { - return this->in; - } - - Output& get_output() - { - return this->out; - } - - const Output& get_output() const - { - return this->out; - } - - protected: - windows_emulator* win_emu{}; - Input in{}; - Output out{}; -}; - -struct syscall_input -{ - uint32_t id{}; - std::string_view name{}; -}; - -struct syscall_output -{ - bool skip{false}; -}; - -struct syscall_event : rich_event -{ - using rich_event::rich_event; - - void print(generic_logger& log) const override; -}; - -struct event_manager : utils::object -{ - virtual void handle(emulation_event& e); -}; - -class printing_event_manager : public event_manager -{ - public: - printing_event_manager(generic_logger& log) - : logger_(&log) - { - } - - void handle(emulation_event& e) override - { - e.print(*this->logger_); - } - - private: - generic_logger* logger_{}; -}; diff --git a/src/windows-emulator/syscall_dispatcher.cpp b/src/windows-emulator/syscall_dispatcher.cpp index b5e6232b..c25ad547 100644 --- a/src/windows-emulator/syscall_dispatcher.cpp +++ b/src/windows-emulator/syscall_dispatcher.cpp @@ -76,8 +76,6 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu) try { - const auto* mod = win_emu.mod_manager.find_by_address(address); - const auto entry = this->handlers_.find(syscall_id); if (entry == this->handlers_.end()) { @@ -87,14 +85,8 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu) return; } - syscall_event e(c.win_emu, { - .id = syscall_id, - .name = entry->second.name, - }); - - c.win_emu.manager().handle(e); - - if (e.get_output().skip) + const auto res = win_emu.callbacks.on_syscall(syscall_id, entry->second.name); + if (res == instruction_hook_continuation::skip_instruction) { return; } diff --git a/src/windows-emulator/windows_emulator.hpp b/src/windows-emulator/windows_emulator.hpp index cd2a7ed8..34df864a 100644 --- a/src/windows-emulator/windows_emulator.hpp +++ b/src/windows-emulator/windows_emulator.hpp @@ -5,7 +5,6 @@ #include -#include "event_manager.hpp" #include "syscall_dispatcher.hpp" #include "process_context.hpp" #include "logger.hpp" @@ -16,7 +15,10 @@ struct emulator_callbacks : module_manager::callbacks, process_context::callbacks { - utils::optional_function on_stdout{}; + using continuation = instruction_hook_continuation; + + utils::optional_function on_syscall{}; + utils::optional_function on_stdout{}; }; struct application_settings @@ -55,7 +57,6 @@ class windows_emulator std::unique_ptr emu_{}; std::unique_ptr clock_{}; std::unique_ptr socket_factory_{}; - std::unique_ptr event_manager_{}; public: std::filesystem::path emulation_root{}; @@ -91,16 +92,6 @@ 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_;