From f046246740f8d13f59e9bc048fd5329725ef189d Mon Sep 17 00:00:00 2001 From: momo5502 Date: Wed, 4 Jun 2025 21:21:48 +0200 Subject: [PATCH] Extract more analysis logic --- src/analyzer/analysis.cpp | 92 +++++++++++++++++++++++ src/windows-emulator/windows_emulator.cpp | 84 +-------------------- src/windows-emulator/windows_emulator.hpp | 16 ++-- 3 files changed, 103 insertions(+), 89 deletions(-) diff --git a/src/analyzer/analysis.cpp b/src/analyzer/analysis.cpp index 9d449519..583876ed 100644 --- a/src/analyzer/analysis.cpp +++ b/src/analyzer/analysis.cpp @@ -1,5 +1,6 @@ #include "analysis.hpp" #include "windows_emulator.hpp" +#include "utils/lazy_object.hpp" #define STR_VIEW_VA(str) static_cast((str).size()), (str).data() @@ -20,6 +21,96 @@ namespace win_emu.log.print(color::pink, "Suspicious: %.*s (0x%" PRIx64 ")\n", STR_VIEW_VA(details), rip); } + void handle_instruction(windows_emulator& win_emu, const uint64_t address) + { + const auto is_main_exe = win_emu.mod_manager.executable->is_within(address); + const auto is_previous_main_exe = win_emu.mod_manager.executable->is_within(win_emu.process.previous_ip); + + const auto binary = utils::make_lazy([&] { + if (is_main_exe) + { + return win_emu.mod_manager.executable; + } + + return win_emu.mod_manager.find_by_address(address); // + }); + + const auto previous_binary = utils::make_lazy([&] { + if (is_previous_main_exe) + { + return win_emu.mod_manager.executable; + } + + return win_emu.mod_manager.find_by_address(win_emu.process.previous_ip); // + }); + + const auto is_in_interesting_module = [&] { + if (win_emu.modules_.empty()) + { + return false; + } + + return (binary && win_emu.modules_.contains(binary->name)) || + (previous_binary && win_emu.modules_.contains(previous_binary->name)); + }; + + const auto is_interesting_call = is_previous_main_exe // + || is_main_exe // + || is_in_interesting_module(); + + if (win_emu.silent_until_main_ && is_main_exe) + { + win_emu.silent_until_main_ = false; + win_emu.log.disable_output(false); + } + + if (!win_emu.verbose && !win_emu.verbose_calls && !is_interesting_call) + { + return; + } + + if (binary) + { + const auto export_entry = binary->address_names.find(address); + if (export_entry != binary->address_names.end() && + !win_emu.ignored_functions_.contains(export_entry->second)) + { + const auto rsp = win_emu.emu().read_stack_pointer(); + + uint64_t return_address{}; + win_emu.emu().try_read_memory(rsp, &return_address, sizeof(return_address)); + + const auto* mod_name = win_emu.mod_manager.find_name(return_address); + + win_emu.log.print(is_interesting_call ? color::yellow : color::dark_gray, + "Executing function: %s - %s (0x%" PRIx64 ") via (0x%" PRIx64 ") %s\n", + binary->name.c_str(), export_entry->second.c_str(), address, return_address, + mod_name); + } + else if (address == binary->entry_point) + { + win_emu.log.print(is_interesting_call ? color::yellow : color::gray, + "Executing entry point: %s (0x%" PRIx64 ")\n", binary->name.c_str(), address); + } + } + + if (!win_emu.verbose) + { + return; + } + + auto& emu = win_emu.emu(); + + // TODO: Remove or cleanup + win_emu.log.print( + color::gray, + "Inst: %16" PRIx64 " - RAX: %16" PRIx64 " - RBX: %16" PRIx64 " - RCX: %16" PRIx64 " - RDX: %16" PRIx64 + " - R8: %16" PRIx64 " - R9: %16" PRIx64 " - RDI: %16" PRIx64 " - RSI: %16" PRIx64 " - %s\n", + address, emu.reg(x86_register::rax), emu.reg(x86_register::rbx), emu.reg(x86_register::rcx), + emu.reg(x86_register::rdx), emu.reg(x86_register::r8), emu.reg(x86_register::r9), + emu.reg(x86_register::rdi), emu.reg(x86_register::rsi), binary ? binary->name.c_str() : ""); + } + emulator_callbacks::continuation handle_syscall(windows_emulator& win_emu, const uint32_t syscall_id, const std::string_view syscall_name) { @@ -66,5 +157,6 @@ void register_analysis_callbacks(windows_emulator& win_emu) auto& cb = win_emu.callbacks; cb.on_syscall = make_callback(win_emu, handle_syscall); + cb.on_instruction = make_callback(win_emu, handle_instruction); cb.on_suspicious_activity = make_callback(win_emu, handle_suspicious_activity); } diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index d52896e3..af53e96d 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -418,89 +418,7 @@ void windows_emulator::on_instruction_execution(const uint64_t address) this->process.previous_ip = this->process.current_ip; this->process.current_ip = this->emu().read_instruction_pointer(); - const auto is_main_exe = this->mod_manager.executable->is_within(address); - const auto is_previous_main_exe = this->mod_manager.executable->is_within(this->process.previous_ip); - - const auto binary = utils::make_lazy([&] { - if (is_main_exe) - { - return this->mod_manager.executable; - } - - return this->mod_manager.find_by_address(address); // - }); - - const auto previous_binary = utils::make_lazy([&] { - if (is_previous_main_exe) - { - return this->mod_manager.executable; - } - - return this->mod_manager.find_by_address(this->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_interesting_call = is_previous_main_exe // - || is_main_exe // - || is_in_interesting_module(); - - if (this->silent_until_main_ && is_main_exe) - { - this->silent_until_main_ = false; - this->log.disable_output(false); - } - - if (!this->verbose && !this->verbose_calls && !is_interesting_call) - { - return; - } - - if (binary) - { - const auto export_entry = binary->address_names.find(address); - if (export_entry != binary->address_names.end() && !this->ignored_functions_.contains(export_entry->second)) - { - const auto rsp = this->emu().read_stack_pointer(); - - uint64_t return_address{}; - this->emu().try_read_memory(rsp, &return_address, sizeof(return_address)); - - const auto* mod_name = this->mod_manager.find_name(return_address); - - log.print(is_interesting_call ? color::yellow : color::dark_gray, - "Executing function: %s - %s (0x%" PRIx64 ") via (0x%" PRIx64 ") %s\n", binary->name.c_str(), - export_entry->second.c_str(), address, return_address, mod_name); - } - else if (address == binary->entry_point) - { - log.print(is_interesting_call ? color::yellow : color::gray, "Executing entry point: %s (0x%" PRIx64 ")\n", - binary->name.c_str(), address); - } - } - - if (!this->verbose) - { - return; - } - - auto& emu = this->emu(); - - // TODO: Remove or cleanup - log.print(color::gray, - "Inst: %16" PRIx64 " - RAX: %16" PRIx64 " - RBX: %16" PRIx64 " - RCX: %16" PRIx64 " - RDX: %16" PRIx64 - " - R8: %16" PRIx64 " - R9: %16" PRIx64 " - RDI: %16" PRIx64 " - RSI: %16" PRIx64 " - %s\n", - address, emu.reg(x86_register::rax), emu.reg(x86_register::rbx), emu.reg(x86_register::rcx), - emu.reg(x86_register::rdx), emu.reg(x86_register::r8), emu.reg(x86_register::r9), - emu.reg(x86_register::rdi), emu.reg(x86_register::rsi), binary ? binary->name.c_str() : ""); + this->callbacks.on_instruction(address); } void windows_emulator::setup_hooks() diff --git a/src/windows-emulator/windows_emulator.hpp b/src/windows-emulator/windows_emulator.hpp index 3f8eba65..391bfe59 100644 --- a/src/windows-emulator/windows_emulator.hpp +++ b/src/windows-emulator/windows_emulator.hpp @@ -20,6 +20,7 @@ struct emulator_callbacks : module_manager::callbacks, process_context::callback utils::optional_function on_syscall{}; utils::optional_function on_stdout{}; utils::optional_function on_suspicious_activity{}; + utils::optional_function on_instruction{}; }; struct application_settings @@ -176,25 +177,28 @@ class windows_emulator } } - bool verbose{false}; - bool verbose_calls{false}; - bool buffer_stdout{false}; + // TODO: Remove bool fuzzing{false}; void yield_thread(bool alertable = false); bool perform_thread_switch(); bool activate_thread(uint32_t id); + // TODO: Move to analyzer + bool verbose{false}; + bool verbose_calls{false}; + bool buffer_stdout{false}; + bool silent_until_main_{false}; + std::set> modules_{}; + std::set> ignored_functions_{}; + private: bool switch_thread_{false}; bool use_relative_time_{false}; - bool silent_until_main_{false}; std::atomic_bool should_stop{false}; std::unordered_map port_mappings_{}; - std::set> modules_{}; - std::set> ignored_functions_{}; std::vector process_snapshot_{}; // std::optional process_snapshot_{};