diff --git a/src/analyzer/main.cpp b/src/analyzer/main.cpp index 0d51501e..33036026 100644 --- a/src/analyzer/main.cpp +++ b/src/analyzer/main.cpp @@ -289,38 +289,38 @@ namespace return create_application_emulator(options, args); } -bool run(const analysis_options& options, const std::span args) -{ - analysis_context context{ - .settings = &options, - }; - - const auto win_emu = setup_emulator(options, args); - win_emu->log.disable_output(options.concise_logging || options.silent); - context.win_emu = win_emu.get(); - - win_emu->log.log("Using emulator: %s\n", win_emu->emu().get_name().c_str()); - - // Enable TenetTracer and assign it to the context. - std::unique_ptr tenet_tracer; - if (options.tenet_trace) + bool run(const analysis_options& options, const std::span args) { - win_emu->log.log("Tenet Tracer enabled. Output: tenet_trace.log\n"); - tenet_tracer = std::make_unique(*win_emu, "tenet_trace.log"); + analysis_context context{ + .settings = &options, + }; - // Set up the hook to call the tracer for each instruction. - win_emu->emu().hook_memory_execution([&](uint64_t address) { - if (tenet_tracer) - { - tenet_tracer->process_instruction(address); - } - }); - } + const auto win_emu = setup_emulator(options, args); + win_emu->log.disable_output(options.concise_logging || options.silent); + context.win_emu = win_emu.get(); - register_analysis_callbacks(context); - watch_system_objects(*win_emu, options.modules, options.verbose_logging); + win_emu->log.log("Using emulator: %s\n", win_emu->emu().get_name().c_str()); - const auto& exe = *win_emu->mod_manager.executable; + // Enable TenetTracer and assign it to the context. + std::unique_ptr tenet_tracer; + if (options.tenet_trace) + { + win_emu->log.log("Tenet Tracer enabled. Output: tenet_trace.log\n"); + tenet_tracer = std::make_unique(*win_emu, "tenet_trace.log"); + + // Set up the hook to call the tracer for each instruction. + win_emu->emu().hook_memory_execution([&](uint64_t address) { + if (tenet_tracer) + { + tenet_tracer->process_instruction(address); + } + }); + } + + register_analysis_callbacks(context); + watch_system_objects(*win_emu, options.modules, options.verbose_logging); + + const auto& exe = *win_emu->mod_manager.executable; const auto concise_logging = !options.verbose_logging; @@ -434,7 +434,6 @@ bool run(const analysis_options& options, const std::span& args) { diff --git a/src/analyzer/tenet_tracer.cpp b/src/analyzer/tenet_tracer.cpp index b97e3fca..2c49f3f0 100644 --- a/src/analyzer/tenet_tracer.cpp +++ b/src/analyzer/tenet_tracer.cpp @@ -3,7 +3,8 @@ #include TenetTracer::TenetTracer(windows_emulator& win_emu, const std::string& log_filename) - : m_win_emu(win_emu), m_log_file(log_filename) + : m_win_emu(win_emu), + m_log_file(log_filename) { if (!m_log_file.is_open()) { @@ -11,19 +12,19 @@ TenetTracer::TenetTracer(windows_emulator& win_emu, const std::string& log_filen } // Set up memory hooks. auto& emu = m_win_emu.emu(); - m_read_hook = emu.hook_memory_read(0, 0xFFFFFFFFFFFFFFFF, [this](uint64_t a, const void* d, size_t s) { - this->log_memory_read(a, d, s); - }); - m_write_hook = emu.hook_memory_write(0, 0xFFFFFFFFFFFFFFFF, [this](uint64_t a, const void* d, size_t s) { - this->log_memory_write(a, d, s); - }); + m_read_hook = emu.hook_memory_read(0, 0xFFFFFFFFFFFFFFFF, + [this](uint64_t a, const void* d, size_t s) { this->log_memory_read(a, d, s); }); + m_write_hook = emu.hook_memory_write( + 0, 0xFFFFFFFFFFFFFFFF, [this](uint64_t a, const void* d, size_t s) { this->log_memory_write(a, d, s); }); } TenetTracer::~TenetTracer() { auto& emu = m_win_emu.emu(); - if (m_read_hook) emu.delete_hook(m_read_hook); - if (m_write_hook) emu.delete_hook(m_write_hook); + if (m_read_hook) + emu.delete_hook(m_read_hook); + if (m_write_hook) + emu.delete_hook(m_write_hook); // Filter and write the buffer when the program ends. filter_and_write_buffer(); @@ -89,9 +90,10 @@ void TenetTracer::filter_and_write_buffer() for (size_t i = 1; i < m_raw_log_buffer.size(); ++i) { const auto& line = m_raw_log_buffer[i]; - + size_t rip_pos = line.find("rip=0x"); - if (rip_pos == std::string::npos) continue; + if (rip_pos == std::string::npos) + continue; char* end_ptr; uint64_t address = std::strtoull(line.c_str() + rip_pos + 6, &end_ptr, 16); @@ -121,15 +123,17 @@ void TenetTracer::filter_and_write_buffer() for (const auto& pair : accumulated_changes) { - if (!first) summary_line << ","; + if (!first) + summary_line << ","; summary_line << pair.first << "=" << pair.second; first = false; } - + // Add the last known rip at the end. if (!last_rip.empty()) { - if (!first) summary_line << ","; + if (!first) + summary_line << ","; summary_line << "rip=" << last_rip; } @@ -154,7 +158,6 @@ void TenetTracer::filter_and_write_buffer() m_raw_log_buffer.clear(); } - std::string TenetTracer::format_hex(uint64_t value) { std::stringstream ss; @@ -203,7 +206,8 @@ void TenetTracer::process_instruction(uint64_t address) bool first_entry = true; auto append_separator = [&]() { - if (!first_entry) { + if (!first_entry) + { trace_line << ","; } first_entry = false; @@ -234,16 +238,18 @@ void TenetTracer::process_instruction(uint64_t address) trace_line << "rip=" << format_hex(address); std::string mem_reads = m_mem_read_log.str(); - if (!mem_reads.empty()) { + if (!mem_reads.empty()) + { append_separator(); trace_line << "mr=" << mem_reads; } std::string mem_writes = m_mem_write_log.str(); - if (!mem_writes.empty()) { + if (!mem_writes.empty()) + { append_separator(); trace_line << "mw=" << mem_writes; } - + // Add the data to the buffer instead of writing directly to the file. m_raw_log_buffer.push_back(trace_line.str()); diff --git a/src/analyzer/tenet_tracer.hpp b/src/analyzer/tenet_tracer.hpp index 4012c127..5480c835 100644 --- a/src/analyzer/tenet_tracer.hpp +++ b/src/analyzer/tenet_tracer.hpp @@ -10,18 +10,30 @@ #include // List of registers to trace for the x64 architecture. -constexpr std::array, 16> GPRs_TO_TRACE = {{ - {x86_register::rax, "rax"}, {x86_register::rbx, "rbx"}, {x86_register::rcx, "rcx"}, - {x86_register::rdx, "rdx"}, {x86_register::rsi, "rsi"}, {x86_register::rdi, "rdi"}, - {x86_register::rbp, "rbp"}, {x86_register::rsp, "rsp"}, {x86_register::r8, "r8"}, - {x86_register::r9, "r9"}, {x86_register::r10, "r10"}, {x86_register::r11, "r11"}, - {x86_register::r12, "r12"}, {x86_register::r13, "r13"}, {x86_register::r14, "r14"}, - {x86_register::r15, "r15"} -}}; +constexpr std::array, 16> GPRs_TO_TRACE = { + { + {x86_register::rax, "rax"}, + {x86_register::rbx, "rbx"}, + {x86_register::rcx, "rcx"}, + {x86_register::rdx, "rdx"}, + {x86_register::rsi, "rsi"}, + {x86_register::rdi, "rdi"}, + {x86_register::rbp, "rbp"}, + {x86_register::rsp, "rsp"}, + {x86_register::r8, "r8"}, + {x86_register::r9, "r9"}, + {x86_register::r10, "r10"}, + {x86_register::r11, "r11"}, + {x86_register::r12, "r12"}, + {x86_register::r13, "r13"}, + {x86_register::r14, "r14"}, + {x86_register::r15, "r15"}, + }, +}; class TenetTracer { -public: + public: TenetTracer(windows_emulator& win_emu, const std::string& log_filename); ~TenetTracer(); @@ -32,7 +44,7 @@ public: TenetTracer(const TenetTracer&) = delete; TenetTracer& operator=(const TenetTracer&) = delete; -private: + private: void filter_and_write_buffer(); void log_memory_read(uint64_t address, const void* data, size_t size); void log_memory_write(uint64_t address, const void* data, size_t size); @@ -45,7 +57,7 @@ private: // In-memory buffering for performance. std::vector m_raw_log_buffer; - + // Use an array instead of a map to store the register state of the previous instruction. std::array m_previous_regs{}; bool m_is_first_instruction = true;