diff --git a/src/analyzer/main.cpp b/src/analyzer/main.cpp index 2d5f8421..87fc37eb 100644 --- a/src/analyzer/main.cpp +++ b/src/analyzer/main.cpp @@ -1,7 +1,7 @@ #include "std_include.hpp" #include -#include +#include #include "object_watching.hpp" @@ -43,22 +43,12 @@ namespace const auto* address = "0.0.0.0:28960"; win_emu.logger.print(color::pink, "Waiting for GDB connection on %s...\n", address); - x64_gdb_stub_handler handler{win_emu.emu()}; + win_x64_gdb_stub_handler handler{win_emu}; run_gdb_stub(handler, "i386:x86-64", gdb_registers.size(), address); } else { - while (true) - { - win_emu.emu().start_from_ip(); - if (win_emu.switch_thread) - { - win_emu.perform_thread_switch(); - continue; - } - - break; - } + win_emu.start(); } } catch (...) diff --git a/src/emulator/emulator.hpp b/src/emulator/emulator.hpp index 4f33ee4b..72f554d3 100644 --- a/src/emulator/emulator.hpp +++ b/src/emulator/emulator.hpp @@ -58,7 +58,7 @@ public: emulator(emulator&&) = delete; emulator& operator=(emulator&&) = delete; - virtual void start(uint64_t start, uint64_t end = 0, std::chrono::microseconds timeout = {}, size_t count = 0) = 0; + virtual void start(uint64_t start, uint64_t end = 0, std::chrono::nanoseconds timeout = {}, size_t count = 0) = 0; virtual void stop() = 0; virtual void read_raw_register(int reg, void* value, size_t size) = 0; diff --git a/src/emulator/typed_emulator.hpp b/src/emulator/typed_emulator.hpp index 5f555f2a..078b2e32 100644 --- a/src/emulator/typed_emulator.hpp +++ b/src/emulator/typed_emulator.hpp @@ -15,7 +15,7 @@ public: static constexpr registers stack_pointer = StackPointer; static constexpr registers instruction_pointer = InstructionPointer; - void start_from_ip(const std::chrono::microseconds timeout = {}, const size_t count = 0) + void start_from_ip(const std::chrono::nanoseconds timeout = {}, const size_t count = 0) { this->start(this->read_instruction_pointer(), 0, timeout, count); } diff --git a/src/unicorn-emulator/unicorn_x64_emulator.cpp b/src/unicorn-emulator/unicorn_x64_emulator.cpp index 4f0358b9..c1fa22fb 100644 --- a/src/unicorn-emulator/unicorn_x64_emulator.cpp +++ b/src/unicorn-emulator/unicorn_x64_emulator.cpp @@ -235,18 +235,21 @@ namespace unicorn uc_close(this->uc_); } - void start(uint64_t start, const uint64_t end, std::chrono::microseconds timeout, + void start(uint64_t start, const uint64_t end, std::chrono::nanoseconds timeout, const size_t count) override { + if (timeout.count() < 0) + { + timeout = {}; + } + + // TODO: Fix adjusting timeout and count while (true) { - if (timeout.count() < 0) - { - timeout = {}; - } - this->retry_after_violation_ = false; - const auto res = uc_emu_start(*this, start, end, static_cast(timeout.count()), count); + const auto timeoutYs = std::chrono::duration_cast(timeout); + const auto res = uc_emu_start(*this, start, end, static_cast(timeoutYs.count()), + count); if (res == UC_ERR_OK) { return; @@ -259,13 +262,12 @@ namespace unicorn res == UC_ERR_WRITE_PROT || // res == UC_ERR_FETCH_PROT; - if (is_violation && this->retry_after_violation_) + if (!is_violation || !this->retry_after_violation_) { - start = this->read_instruction_pointer(); - continue; + uce(res); } - uce(res); + start = this->read_instruction_pointer(); } } diff --git a/src/windows-emulator/debugging/win_x64_gdb_stub_handler.hpp b/src/windows-emulator/debugging/win_x64_gdb_stub_handler.hpp new file mode 100644 index 00000000..a9427df2 --- /dev/null +++ b/src/windows-emulator/debugging/win_x64_gdb_stub_handler.hpp @@ -0,0 +1,45 @@ +#pragma once +#include "x64_gdb_stub_handler.hpp" + +#include "../windows_emulator.hpp" + +class win_x64_gdb_stub_handler : public x64_gdb_stub_handler +{ +public: + win_x64_gdb_stub_handler(windows_emulator& win_emu) + : x64_gdb_stub_handler(win_emu.emu()) + , win_emu_(&win_emu) + { + } + + gdb_action cont() override + { + try + { + this->win_emu_->start(); + } + catch (const std::exception& e) + { + puts(e.what()); + } + + return gdb_action::resume; + } + + gdb_action stepi() override + { + try + { + this->win_emu_->start({}, 1); + } + catch (const std::exception& e) + { + puts(e.what()); + } + + return gdb_action::resume; + } + +private: + windows_emulator* win_emu_{}; +}; diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index 5e73bb46..1e386437 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -853,6 +853,58 @@ void windows_emulator::setup_hooks() }); } +void windows_emulator::start(std::chrono::nanoseconds timeout, size_t count) +{ + const auto use_count = count > 0; + const auto use_timeout = timeout != std::chrono::nanoseconds{}; + + auto start_time = std::chrono::high_resolution_clock::now(); + auto start_instructions = this->process().executed_instructions; + + while (true) + { + if (this->switch_thread) + { + this->perform_thread_switch(); + } + + this->emu().start_from_ip(timeout, count); + + if (!this->switch_thread) + { + break; + } + + if (use_timeout) + { + const auto now = std::chrono::high_resolution_clock::now(); + const auto diff = now - start_time; + + if (diff >= timeout) + { + break; + } + + timeout = timeout - diff; + start_time = now; + } + + if (use_count) + { + const auto current_instructions = this->process().executed_instructions; + const auto diff = current_instructions - start_instructions; + + if(diff >= count) + { + break; + } + + count = diff; + start_instructions = current_instructions; + } + } +} + void windows_emulator::serialize(utils::buffer_serializer& buffer) const { this->emu().serialize(buffer); diff --git a/src/windows-emulator/windows_emulator.hpp b/src/windows-emulator/windows_emulator.hpp index d46baed4..b72cb58e 100644 --- a/src/windows-emulator/windows_emulator.hpp +++ b/src/windows-emulator/windows_emulator.hpp @@ -61,6 +61,8 @@ public: return *this->process_.active_thread; } + void start(std::chrono::nanoseconds timeout = {}, size_t count = 0); + void serialize(utils::buffer_serializer& buffer) const; void deserialize(utils::buffer_deserializer& buffer);