From 27f02c74c77c6876b61f5989381b023426776698 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sun, 9 Feb 2025 09:43:19 +0100 Subject: [PATCH] Support logging actions for interesting modules --- src/analyzer/main.cpp | 36 ++++++++---- src/analyzer/object_watching.hpp | 8 ++- src/common/utils/lazy_object.hpp | 69 +++++++++++++++++++++++ src/windows-emulator/windows_emulator.cpp | 35 +++++++++--- src/windows-emulator/windows_emulator.hpp | 3 + 5 files changed, 131 insertions(+), 20 deletions(-) create mode 100644 src/common/utils/lazy_object.hpp diff --git a/src/analyzer/main.cpp b/src/analyzer/main.cpp index 1ecdf4d2..21c1b3c0 100644 --- a/src/analyzer/main.cpp +++ b/src/analyzer/main.cpp @@ -15,23 +15,28 @@ namespace bool silent{false}; std::string registry_path{"./registry"}; std::string emulation_root{}; + std::set> modules{}; }; - void watch_system_objects(windows_emulator& win_emu, const bool cache_logging) + void watch_system_objects(windows_emulator& win_emu, const std::set>& modules, + const bool cache_logging) { (void)win_emu; + (void)modules; (void)cache_logging; #ifdef OS_WINDOWS - watch_object(win_emu, *win_emu.current_thread().teb, cache_logging); - watch_object(win_emu, win_emu.process().peb, cache_logging); - watch_object(win_emu, emulator_object{win_emu.emu(), kusd_mmio::address()}, cache_logging); + watch_object(win_emu, modules, *win_emu.current_thread().teb, cache_logging); + watch_object(win_emu, modules, win_emu.process().peb, cache_logging); + watch_object(win_emu, modules, emulator_object{win_emu.emu(), kusd_mmio::address()}, + cache_logging); - auto* params_hook = watch_object(win_emu, win_emu.process().process_params, cache_logging); + auto* params_hook = watch_object(win_emu, modules, win_emu.process().process_params, cache_logging); win_emu.emu().hook_memory_write( win_emu.process().peb.value() + offsetof(PEB64, ProcessParameters), 0x8, - [&win_emu, cache_logging, params_hook](const uint64_t address, size_t, const uint64_t value) mutable { + [&win_emu, cache_logging, params_hook, modules](const uint64_t address, size_t, + const uint64_t value) mutable { const auto target_address = win_emu.process().peb.value() + offsetof(PEB64, ProcessParameters); if (address == target_address) @@ -39,7 +44,7 @@ namespace const emulator_object obj{win_emu.emu(), value}; win_emu.emu().delete_hook(params_hook); - params_hook = watch_object(win_emu, obj, cache_logging); + params_hook = watch_object(win_emu, modules, obj, cache_logging); } }); #endif @@ -108,7 +113,7 @@ namespace return false; } - emulator_settings settings{ + const emulator_settings settings{ .application = args[0], .registry_directory = options.registry_path, .emulation_root = options.emulation_root, @@ -116,12 +121,13 @@ namespace .verbose_calls = options.verbose_logging, .disable_logging = options.silent, .silent_until_main = options.concise_logging, + .modules = options.modules, }; - windows_emulator win_emu{std::move(settings)}; + windows_emulator win_emu{settings}; (void)&watch_system_objects; - watch_system_objects(win_emu, options.concise_logging); + watch_system_objects(win_emu, options.modules, options.concise_logging); win_emu.buffer_stdout = true; if (options.silent) @@ -226,6 +232,16 @@ namespace { options.concise_logging = true; } + else if (arg == "-m") + { + if (args.size() < 2) + { + throw std::runtime_error("No module provided after -m"); + } + + arg_it = args.erase(arg_it); + options.modules.insert(std::string(args[0])); + } else if (arg == "-e") { if (args.size() < 2) diff --git a/src/analyzer/object_watching.hpp b/src/analyzer/object_watching.hpp index 34c2b5fb..57bef027 100644 --- a/src/analyzer/object_watching.hpp +++ b/src/analyzer/object_watching.hpp @@ -1,18 +1,20 @@ #pragma once #include "reflect_type_info.hpp" +#include template -emulator_hook* watch_object(windows_emulator& emu, emulator_object object, const bool cache_logging = false) +emulator_hook* watch_object(windows_emulator& emu, const std::set>& modules, + emulator_object object, const bool cache_logging = false) { const reflect_type_info info{}; return emu.emu().hook_memory_read( object.value(), object.size(), - [i = std::move(info), object, &emu, cache_logging](const uint64_t address, size_t, uint64_t) { + [i = std::move(info), object, &emu, cache_logging, modules](const uint64_t address, size_t, uint64_t) { const auto rip = emu.emu().read_instruction_pointer(); const auto* mod = emu.process().mod_manager.find_by_address(rip); - const auto is_main_access = mod == emu.process().executable; + const auto is_main_access = mod == emu.process().executable || modules.contains(mod->name); if (!emu.verbose_calls && !is_main_access) { diff --git a/src/common/utils/lazy_object.hpp b/src/common/utils/lazy_object.hpp new file mode 100644 index 00000000..e981abc8 --- /dev/null +++ b/src/common/utils/lazy_object.hpp @@ -0,0 +1,69 @@ +#pragma once + +#include +#include + +namespace utils +{ + template + concept CallableWithReturn = requires(const F f) { + { f() } -> std::same_as; + }; + + template + requires(CallableWithReturn) + class lazy_object + { + public: + lazy_object(F accessor) + : accessor_(std::move(accessor)) + { + } + + operator const T&() const + { + return this->get(); + } + + operator T&() + { + return this->get(); + } + + T& operator->() + requires std::is_pointer_v + { + return this->get(); + } + + const T& operator->() const + requires std::is_pointer_v + { + return this->get(); + } + + private: + F accessor_{}; + mutable std::optional object_{}; + + T& get() const + { + this->ensure_construction(); + return *this->object_; + } + + void ensure_construction() const + { + if (!this->object_.has_value()) + { + this->object_.emplace(this->accessor_()); + } + } + }; + + template + auto make_lazy(F accessor) + { + return lazy_object, F>(std::move(accessor)); + } +} diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index 72d5f5e2..437cdd10 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -5,9 +5,11 @@ #include "context_frame.hpp" #include + +#include #include -#include "utils/compression.hpp" -#include "utils/io.hpp" +#include +#include #include "apiset.hpp" @@ -861,6 +863,8 @@ windows_emulator::windows_emulator(const emulator_settings& settings, emulator_c 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->modules_ = settings.modules; + this->setup_process(settings, working_dir); } @@ -955,15 +959,34 @@ void windows_emulator::on_instruction_execution(const uint64_t address) const auto thread_insts = ++thread.executed_instructions; if (thread_insts % MAX_INSTRUCTIONS_PER_TIME_SLICE == 0) { - this->switch_thread_ = true; - this->emu().stop(); + this->yield_thread(); } process.previous_ip = process.current_ip; process.current_ip = this->emu().read_instruction_pointer(); + const auto binary = utils::make_lazy([&] { + return this->process().mod_manager.find_by_address(address); // + }); + + const auto previous_binary = utils::make_lazy([&] { + return this->process().mod_manager.find_by_address(process.previous_ip); // + }); + + const auto is_in_interesting_module = [&] { + if (this->modules_.empty()) + { + return false; + } + + return (binary && this->modules_.contains(binary->name)) || + (previous_binary && this->modules_.contains(previous_binary->name)); + }; + const auto is_main_exe = process.executable->is_within(address); - const auto is_interesting_call = process.executable->is_within(process.previous_ip) || is_main_exe; + const auto is_interesting_call = process.executable->is_within(process.previous_ip) // + || is_main_exe // + || is_in_interesting_module(); if (this->silent_until_main_ && is_main_exe) { @@ -976,8 +999,6 @@ void windows_emulator::on_instruction_execution(const uint64_t address) return; } - const auto* binary = this->process().mod_manager.find_by_address(address); - if (binary) { const auto export_entry = binary->address_names.find(address); diff --git a/src/windows-emulator/windows_emulator.hpp b/src/windows-emulator/windows_emulator.hpp index 69a17497..e586c3cc 100644 --- a/src/windows-emulator/windows_emulator.hpp +++ b/src/windows-emulator/windows_emulator.hpp @@ -38,6 +38,7 @@ struct emulator_settings bool use_relative_time{false}; std::unordered_map port_mappings{}; std::unordered_map path_mappings{}; + std::set> modules{}; }; enum class apiset_location : uint8_t @@ -204,6 +205,8 @@ class windows_emulator std::vector syscall_hooks_{}; std::unordered_map port_mappings_{}; + std::set> modules_{}; + process_context process_; syscall_dispatcher dispatcher_;