diff --git a/src/emulator/cpu_interface.hpp b/src/emulator/cpu_interface.hpp new file mode 100644 index 00000000..4d30eef0 --- /dev/null +++ b/src/emulator/cpu_interface.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include +#include +#include +#include + +struct cpu_interface +{ + virtual ~cpu_interface() = default; + + 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; + virtual void write_raw_register(int reg, const void* value, size_t size) = 0; + + virtual std::vector save_registers() = 0; + virtual void restore_registers(const std::vector& register_data) = 0; + + virtual bool has_violation() const = 0; +}; diff --git a/src/emulator/emulator.hpp b/src/emulator/emulator.hpp index 2e4691ba..858902e4 100644 --- a/src/emulator/emulator.hpp +++ b/src/emulator/emulator.hpp @@ -1,56 +1,14 @@ #pragma once -#include -#include -#include +#include "cpu_interface.hpp" +#include "hook_interface.hpp" #include "memory_manager.hpp" -struct emulator_hook; - -using memory_operation = memory_permission; - -enum class instruction_hook_continuation : bool -{ - run_instruction = false, - skip_instruction = true, -}; - -enum class memory_violation_continuation : bool -{ - stop = false, - resume = true, -}; - -enum class memory_violation_type : uint8_t -{ - unmapped, - protection, -}; - -struct basic_block -{ - uint64_t address; - size_t instruction_count; - size_t size; -}; - -using edge_generation_hook_callback = - std::function; -using basic_block_hook_callback = std::function; - -using instruction_hook_callback = std::function; - -using interrupt_hook_callback = std::function; -using simple_memory_hook_callback = std::function; -using complex_memory_hook_callback = - std::function; -using memory_violation_hook_callback = std::function; - -class emulator : public memory_manager +class emulator : public cpu_interface, public memory_manager, public hook_interface { public: emulator() = default; + ~emulator() override = default; emulator(const emulator&) = delete; emulator& operator=(const emulator&) = delete; @@ -58,50 +16,6 @@ class emulator : public memory_manager emulator(emulator&&) = delete; emulator& operator=(emulator&&) = delete; - 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; - virtual void write_raw_register(int reg, const void* value, size_t size) = 0; - - virtual std::vector save_registers() = 0; - virtual void restore_registers(const std::vector& register_data) = 0; - - virtual emulator_hook* hook_memory_violation(uint64_t address, size_t size, - memory_violation_hook_callback callback) = 0; - - virtual emulator_hook* hook_memory_access(uint64_t address, size_t size, memory_operation filter, - complex_memory_hook_callback callback) = 0; - virtual emulator_hook* hook_instruction(int instruction_type, instruction_hook_callback callback) = 0; - - virtual emulator_hook* hook_interrupt(interrupt_hook_callback callback) = 0; - - virtual emulator_hook* hook_edge_generation(edge_generation_hook_callback callback) = 0; - virtual emulator_hook* hook_basic_block(basic_block_hook_callback callback) = 0; - - virtual void delete_hook(emulator_hook* hook) = 0; - - emulator_hook* hook_memory_violation(memory_violation_hook_callback callback) - { - return this->hook_memory_violation(0, std::numeric_limits::max(), std::move(callback)); - } - - emulator_hook* hook_memory_read(const uint64_t address, const size_t size, simple_memory_hook_callback callback) - { - return this->hook_simple_memory_access(address, size, std::move(callback), memory_operation::read); - } - - emulator_hook* hook_memory_write(const uint64_t address, const size_t size, simple_memory_hook_callback callback) - { - return this->hook_simple_memory_access(address, size, std::move(callback), memory_operation::write); - } - - emulator_hook* hook_memory_execution(const uint64_t address, const size_t size, - simple_memory_hook_callback callback) - { - return this->hook_simple_memory_access(address, size, std::move(callback), memory_operation::exec); - } - void serialize(utils::buffer_serializer& buffer) const { this->perform_serialization(buffer, false); @@ -130,21 +44,9 @@ class emulator : public memory_manager this->perform_deserialization(deserializer, true); } - virtual bool has_violation() const = 0; - private: std::vector last_snapshot_data_{}; - emulator_hook* hook_simple_memory_access(const uint64_t address, const size_t size, - simple_memory_hook_callback callback, const memory_operation operation) - { - assert((static_cast(operation) & (static_cast(operation) - 1)) == 0); - return this->hook_memory_access(address, size, operation, - [c = std::move(callback)](const uint64_t a, const size_t s, - const uint64_t value, - memory_operation) { c(a, s, value); }); - } - void perform_serialization(utils::buffer_serializer& buffer, const bool is_snapshot) const { this->serialize_state(buffer, is_snapshot); diff --git a/src/emulator/hook_interface.hpp b/src/emulator/hook_interface.hpp new file mode 100644 index 00000000..39752398 --- /dev/null +++ b/src/emulator/hook_interface.hpp @@ -0,0 +1,101 @@ +#pragma once + +#include "memory_permission.hpp" + +#include +#include +#include + +struct emulator_hook; + +using memory_operation = memory_permission; + +enum class instruction_hook_continuation : bool +{ + run_instruction = false, + skip_instruction = true, +}; + +enum class memory_violation_continuation : bool +{ + stop = false, + resume = true, +}; + +enum class memory_violation_type : uint8_t +{ + unmapped, + protection, +}; + +struct basic_block +{ + uint64_t address; + size_t instruction_count; + size_t size; +}; + +using edge_generation_hook_callback = + std::function; +using basic_block_hook_callback = std::function; + +using instruction_hook_callback = std::function; + +using interrupt_hook_callback = std::function; +using simple_memory_hook_callback = std::function; +using complex_memory_hook_callback = + std::function; +using memory_violation_hook_callback = std::function; + +class hook_interface +{ + public: + virtual ~hook_interface() = default; + + virtual emulator_hook* hook_memory_violation(uint64_t address, size_t size, + memory_violation_hook_callback callback) = 0; + + virtual emulator_hook* hook_memory_access(uint64_t address, size_t size, memory_operation filter, + complex_memory_hook_callback callback) = 0; + virtual emulator_hook* hook_instruction(int instruction_type, instruction_hook_callback callback) = 0; + + virtual emulator_hook* hook_interrupt(interrupt_hook_callback callback) = 0; + + virtual emulator_hook* hook_edge_generation(edge_generation_hook_callback callback) = 0; + virtual emulator_hook* hook_basic_block(basic_block_hook_callback callback) = 0; + + virtual void delete_hook(emulator_hook* hook) = 0; + + emulator_hook* hook_memory_violation(memory_violation_hook_callback callback) + { + return this->hook_memory_violation(0, std::numeric_limits::max(), std::move(callback)); + } + + emulator_hook* hook_memory_read(const uint64_t address, const size_t size, simple_memory_hook_callback callback) + { + return this->hook_simple_memory_access(address, size, std::move(callback), memory_operation::read); + } + + emulator_hook* hook_memory_write(const uint64_t address, const size_t size, simple_memory_hook_callback callback) + { + return this->hook_simple_memory_access(address, size, std::move(callback), memory_operation::write); + } + + emulator_hook* hook_memory_execution(const uint64_t address, const size_t size, + simple_memory_hook_callback callback) + { + return this->hook_simple_memory_access(address, size, std::move(callback), memory_operation::exec); + } + + private: + emulator_hook* hook_simple_memory_access(const uint64_t address, const size_t size, + simple_memory_hook_callback callback, const memory_operation operation) + { + assert((static_cast(operation) & (static_cast(operation) - 1)) == 0); + return this->hook_memory_access(address, size, operation, + [c = std::move(callback)](const uint64_t a, const size_t s, + const uint64_t value, + memory_operation) { c(a, s, value); }); + } +}; diff --git a/src/emulator/serialization.hpp b/src/emulator/serialization.hpp index 1b6a8333..e8eee856 100644 --- a/src/emulator/serialization.hpp +++ b/src/emulator/serialization.hpp @@ -20,15 +20,6 @@ namespace utils { a.deserialize(deserializer) } -> std::same_as; }; - /* Use concept instead, to prevent overhead of virtual function calls - struct serializable - { - virtual ~serializable() = default; - virtual void serialize(buffer_serializer& buffer) const = 0; - virtual void deserialize(buffer_deserializer& buffer) = 0; - }; - */ - namespace detail { template @@ -66,7 +57,7 @@ namespace utils { public: template - buffer_deserializer(const std::span buffer, bool no_debugging = false) + buffer_deserializer(const std::span buffer, const bool no_debugging = false) : no_debugging_(no_debugging), buffer_(reinterpret_cast(buffer.data()), buffer.size() * sizeof(T)) { diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index 04f537ff..115a87f7 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -1,6 +1,7 @@ #include "std_include.hpp" #include "windows_emulator.hpp" +#include "address_utils.hpp" #include "context_frame.hpp" #include