diff --git a/src/analyzer/main.cpp b/src/analyzer/main.cpp index 495aa4c7..7926908b 100644 --- a/src/analyzer/main.cpp +++ b/src/analyzer/main.cpp @@ -136,7 +136,7 @@ namespace if (options.silent) { win_emu.buffer_stdout = false; - win_emu.callbacks.stdout_callback = [](const std::string_view data) { + win_emu.callbacks().stdout_callback = [](const std::string_view data) { (void)fwrite(data.data(), 1, data.size(), stdout); }; } diff --git a/src/common/utils/function.hpp b/src/common/utils/function.hpp index 242e9e08..1daa4f6c 100644 --- a/src/common/utils/function.hpp +++ b/src/common/utils/function.hpp @@ -27,19 +27,13 @@ namespace utils { } - optional_function& operator=(std::function f) + template >> + optional_function& operator=(F&& f) { - func = std::move(f); + func = std::forward(f); return *this; } - template - requires(!std::is_same_v, std::function>) - optional_function& operator=(T&& t) - { - return this->operator=(std::function(std::forward(t))); - } - Ret operator()(Args... args) const { if (func) diff --git a/src/windows-emulator/module/module_manager.cpp b/src/windows-emulator/module/module_manager.cpp index cf6ab2c9..f2ae5791 100644 --- a/src/windows-emulator/module/module_manager.cpp +++ b/src/windows-emulator/module/module_manager.cpp @@ -95,6 +95,7 @@ mapped_module* module_manager::map_local_module(const std::filesystem::path& fil const auto image_base = mod.image_base; const auto entry = this->modules_.try_emplace(image_base, std::move(mod)); + this->on_module_load(entry.first->second); return &entry.first->second; } catch (const std::exception& e) @@ -146,6 +147,7 @@ bool module_manager::unmap(const uint64_t address, const logger& logger) logger.log("Unmapping %s (0x%" PRIx64 ")\n", mod->second.path.generic_string().c_str(), mod->second.image_base); + this->on_module_unload(mod->second); unmap_module(*this->memory_, mod->second); this->modules_.erase(mod); diff --git a/src/windows-emulator/module/module_manager.hpp b/src/windows-emulator/module/module_manager.hpp index 0994a3e0..f64276eb 100644 --- a/src/windows-emulator/module/module_manager.hpp +++ b/src/windows-emulator/module/module_manager.hpp @@ -3,6 +3,7 @@ #include "mapped_module.hpp" #include "../file_system.hpp" +#include class logger; @@ -10,6 +11,9 @@ class module_manager { public: using module_map = std::map; + utils::optional_function on_module_load{}; + utils::optional_function on_module_unload{}; + module_manager(memory_manager& memory, file_system& file_sys); void map_main_modules(const windows_path& executable_path, const windows_path& ntdll_path, diff --git a/src/windows-emulator/process_context.cpp b/src/windows-emulator/process_context.cpp index 7dbe27a6..0a15cb49 100644 --- a/src/windows-emulator/process_context.cpp +++ b/src/windows-emulator/process_context.cpp @@ -201,5 +201,7 @@ handle process_context::create_thread(memory_manager& memory, const uint64_t sta const uint64_t stack_size) { emulator_thread t{memory, *this, start_address, argument, stack_size, ++this->spawned_thread_count}; - return this->threads.store(std::move(t)); + auto h = this->threads.store(std::move(t)); + on_create_thread(h, *this->threads.get(h)); + return h; } diff --git a/src/windows-emulator/process_context.hpp b/src/windows-emulator/process_context.hpp index 339807f6..e03b3465 100644 --- a/src/windows-emulator/process_context.hpp +++ b/src/windows-emulator/process_context.hpp @@ -44,6 +44,8 @@ struct process_context const emulator_settings& emu_settings, const mapped_module& executable, const mapped_module& ntdll, const apiset::container& apiset_container); + utils::optional_function on_create_thread{}; + handle create_thread(memory_manager& memory, const uint64_t start_address, const uint64_t argument, const uint64_t stack_size); diff --git a/src/windows-emulator/syscall_dispatcher.cpp b/src/windows-emulator/syscall_dispatcher.cpp index 1f846f66..8b4344e5 100644 --- a/src/windows-emulator/syscall_dispatcher.cpp +++ b/src/windows-emulator/syscall_dispatcher.cpp @@ -91,7 +91,7 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu) const auto* mod = win_emu.mod_manager.find_by_address(address); if (mod != win_emu.mod_manager.ntdll && mod != win_emu.mod_manager.win32u) { - win_emu.callbacks.inline_syscall(syscall_id, address, mod ? mod->name.c_str() : "", + win_emu.callbacks().inline_syscall(syscall_id, address, mod ? mod->name.c_str() : "", entry->second.name); win_emu.log.print(color::blue, "Executing inline syscall: %s (0x%X) at 0x%" PRIx64 " (%s)\n", @@ -116,7 +116,7 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu) { const auto* previous_mod = win_emu.mod_manager.find_by_address(context.previous_ip); - win_emu.callbacks.outofline_syscall(syscall_id, address, mod ? mod->name.c_str() : "", + win_emu.callbacks().outofline_syscall(syscall_id, address, mod ? mod->name.c_str() : "", entry->second.name, context.previous_ip, previous_mod ? previous_mod->name.c_str() : ""); diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index 088f9fcd..eb937c2e 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -2878,7 +2878,7 @@ namespace io_status_block.write(block); } - c.win_emu.callbacks.stdout_callback(temp_buffer); + c.win_emu.callbacks().stdout_callback(temp_buffer); if (!temp_buffer.ends_with("\n")) { @@ -3613,6 +3613,7 @@ namespace } thread->exit_status = exit_status; + c.win_emu.callbacks().thread_terminated(thread_handle, *thread); if (thread == c.proc.active_thread) { c.win_emu.yield_thread(); diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index 5f20f4c1..0fa03680 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -172,7 +172,7 @@ windows_emulator::windows_emulator(application_settings app_settings, const emul emulator_callbacks callbacks, std::unique_ptr emu) : windows_emulator(settings, std::move(emu)) { - this->callbacks = std::move(callbacks); + this->callbacks_ = std::move(callbacks); fixup_application_settings(app_settings); this->setup_process(app_settings, settings); @@ -220,6 +220,10 @@ void windows_emulator::setup_process(const application_settings& app_settings, c const auto& emu = this->emu(); auto& context = this->process; + mod_manager.on_module_load = [this](mapped_module& mod) { this->callbacks().module_loaded(mod); }; + mod_manager.on_module_unload = [this](mapped_module& mod) { this->callbacks().module_unloaded(mod); }; + context.on_create_thread = [this](handle h, emulator_thread& thr) { this->callbacks().thread_created(h, thr); }; + this->mod_manager.map_main_modules(app_settings.application, R"(C:\Windows\System32\ntdll.dll)", R"(C:\Windows\System32\win32u.dll)", this->log); diff --git a/src/windows-emulator/windows_emulator.hpp b/src/windows-emulator/windows_emulator.hpp index 6665dc55..5f13de5d 100644 --- a/src/windows-emulator/windows_emulator.hpp +++ b/src/windows-emulator/windows_emulator.hpp @@ -23,6 +23,10 @@ struct emulator_callbacks std::string_view syscall_name, x64_emulator::pointer_type prev_address, std::string_view prev_mod_name)> outofline_syscall{}; + utils::optional_function module_loaded{}; + utils::optional_function module_unloaded{}; + utils::optional_function thread_created{}; + utils::optional_function thread_terminated{}; }; struct application_settings @@ -53,7 +57,6 @@ class windows_emulator public: std::filesystem::path emulation_root{}; - emulator_callbacks callbacks{}; logger log{}; file_system file_sys; memory_manager memory; @@ -161,11 +164,18 @@ class windows_emulator return this->use_relative_time_; } + emulator_callbacks& callbacks() + { + return this->callbacks_; + } + private: bool switch_thread_{false}; bool use_relative_time_{false}; bool silent_until_main_{false}; + emulator_callbacks callbacks_{}; + std::vector syscall_hooks_{}; std::unordered_map port_mappings_{};