From 1f5afe4c741fd369f92f3004bdd9ecf75f079a4b Mon Sep 17 00:00:00 2001 From: CarlTSpeak Date: Sat, 18 Oct 2025 14:19:53 +0100 Subject: [PATCH 1/3] Minidump can load pages with C permission set. Minor instrumentation. --- src/analyzer/analysis.cpp | 11 +++++++++++ src/windows-emulator/memory_utils.hpp | 4 +++- src/windows-emulator/windows_emulator.cpp | 19 ++++++++++++------- src/windows-emulator/windows_emulator.hpp | 8 ++++++++ 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/analyzer/analysis.cpp b/src/analyzer/analysis.cpp index d4df4e5a..1667a421 100644 --- a/src/analyzer/analysis.cpp +++ b/src/analyzer/analysis.cpp @@ -204,6 +204,17 @@ namespace emu.reg(x86_register::rsp, emu.reg(x86_register::rsp) + 8); emu.reg(x86_register::rax, 1); } + else if (function == "VirtualQuery") + { + auto& emu = c.win_emu->emu(); + const auto lpAddress = emu.reg(x86_register::rcx); + const auto lpBuffer = emu.reg(x86_register::rdx); + const auto dwLength = emu.reg(x86_register::r8); + + c.win_emu->log.print(color::yellow, + "VirtualQuery called: lpAddress=0x%" PRIx64 ", lpBuffer=0x%" PRIx64 ", dwLength=%" PRIu64 "\n", lpAddress, + lpBuffer, dwLength); + } else if (function == "lstrcmp" || function == "lstrcmpi") { print_arg_as_string(*c.win_emu, 0); diff --git a/src/windows-emulator/memory_utils.hpp b/src/windows-emulator/memory_utils.hpp index 5c490223..632979c6 100644 --- a/src/windows-emulator/memory_utils.hpp +++ b/src/windows-emulator/memory_utils.hpp @@ -51,8 +51,10 @@ inline std::optional try_map_nt_to_emulator_protection(uin case PAGE_EXECUTE_READWRITE: common = memory_permission::all; break; - case 0: case PAGE_EXECUTE_WRITECOPY: + common = memory_permission::all; + break; + case 0: default: return std::nullopt; } diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index ab9ecbd8..988f396a 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -328,7 +328,7 @@ windows_emulator::windows_emulator(std::unique_ptr emu, const e this->map_port(mapping.first, mapping.second); } - this->setup_hooks(); + this->setup_hooks(); } windows_emulator::~windows_emulator() = default; @@ -434,6 +434,9 @@ void windows_emulator::on_instruction_execution(const uint64_t address) void windows_emulator::setup_hooks() { + uint64_t tsc_base = splitmix64(0xCAFEBABEDEADBEEFull); + constexpr uint64_t tick_scale = 50; + this->emu().hook_instruction(x86_hookable_instructions::syscall, [&] { this->dispatcher.dispatch(*this); return instruction_hook_continuation::skip_instruction; @@ -442,9 +445,10 @@ void windows_emulator::setup_hooks() this->emu().hook_instruction(x86_hookable_instructions::rdtscp, [&] { this->callbacks.on_rdtscp(); - const auto ticks = this->clock_->timestamp_counter(); - this->emu().reg(x86_register::rax, ticks & 0xFFFFFFFF); - this->emu().reg(x86_register::rdx, (ticks >> 32) & 0xFFFFFFFF); + const uint64_t retired = this->executed_instructions_; + const uint64_t ticks = tsc_base + (retired * tick_scale); + this->emu().reg(x86_register::rax, static_cast(ticks)); + this->emu().reg(x86_register::rdx, static_cast(ticks >> 32)); // Return the IA32_TSC_AUX value in RCX (low 32 bits) auto tsc_aux = 0; // Need to replace this with proper CPUID later @@ -456,9 +460,10 @@ void windows_emulator::setup_hooks() this->emu().hook_instruction(x86_hookable_instructions::rdtsc, [&] { this->callbacks.on_rdtsc(); - const auto ticks = this->clock_->timestamp_counter(); - this->emu().reg(x86_register::rax, ticks & 0xFFFFFFFF); - this->emu().reg(x86_register::rdx, (ticks >> 32) & 0xFFFFFFFF); + const uint64_t retired = this->executed_instructions_; + const uint64_t ticks = tsc_base + (retired * tick_scale); + this->emu().reg(x86_register::rax, static_cast(ticks)); + this->emu().reg(x86_register::rdx, static_cast(ticks >> 32)); return instruction_hook_continuation::skip_instruction; }); diff --git a/src/windows-emulator/windows_emulator.hpp b/src/windows-emulator/windows_emulator.hpp index 86e2a0e2..720bec3b 100644 --- a/src/windows-emulator/windows_emulator.hpp +++ b/src/windows-emulator/windows_emulator.hpp @@ -225,3 +225,11 @@ class windows_emulator void register_factories(utils::buffer_deserializer& buffer); }; + +static inline uint64_t splitmix64(uint64_t x) noexcept +{ + x += 0x9E3779B97F4A7C15ull; + x = (x ^ (x >> 30)) * 0xBF58476D1CE4E5B9ull; + x = (x ^ (x >> 27)) * 0x94D049BB133111EBull; + return x ^ (x >> 31); +} \ No newline at end of file From 064df5b6efe2f032481c5e5f0524565037041f9e Mon Sep 17 00:00:00 2001 From: CarlTSpeak Date: Fri, 24 Oct 2025 10:59:28 +0100 Subject: [PATCH 2/3] Revert earlier rdtsc changes, implement fixes --- src/analyzer/analysis.cpp | 11 ----------- src/windows-emulator/memory_manager.cpp | 6 +++--- src/windows-emulator/memory_manager.hpp | 1 + src/windows-emulator/syscalls/memory.cpp | 7 +++++++ src/windows-emulator/windows_emulator.cpp | 11 +++-------- src/windows-emulator/windows_emulator.hpp | 8 -------- 6 files changed, 14 insertions(+), 30 deletions(-) diff --git a/src/analyzer/analysis.cpp b/src/analyzer/analysis.cpp index 1667a421..d4df4e5a 100644 --- a/src/analyzer/analysis.cpp +++ b/src/analyzer/analysis.cpp @@ -204,17 +204,6 @@ namespace emu.reg(x86_register::rsp, emu.reg(x86_register::rsp) + 8); emu.reg(x86_register::rax, 1); } - else if (function == "VirtualQuery") - { - auto& emu = c.win_emu->emu(); - const auto lpAddress = emu.reg(x86_register::rcx); - const auto lpBuffer = emu.reg(x86_register::rdx); - const auto dwLength = emu.reg(x86_register::r8); - - c.win_emu->log.print(color::yellow, - "VirtualQuery called: lpAddress=0x%" PRIx64 ", lpBuffer=0x%" PRIx64 ", dwLength=%" PRIu64 "\n", lpAddress, - lpBuffer, dwLength); - } else if (function == "lstrcmp" || function == "lstrcmpi") { print_arg_as_string(*c.win_emu, 0); diff --git a/src/windows-emulator/memory_manager.cpp b/src/windows-emulator/memory_manager.cpp index cabcd9f2..b5f6e574 100644 --- a/src/windows-emulator/memory_manager.cpp +++ b/src/windows-emulator/memory_manager.cpp @@ -504,7 +504,7 @@ uint64_t memory_manager::find_free_allocation_base(const size_t size, const uint start_address = align_up(region_end, ALLOCATION_GRANULARITY); } - if (start_address + size <= MAX_ALLOCATION_ADDRESS) + if (start_address + size <= MAX_ALLOCATION_END_EXCL) { return start_address; } @@ -516,7 +516,7 @@ region_info memory_manager::get_region_info(const uint64_t address) { region_info result{}; result.start = MIN_ALLOCATION_ADDRESS; - result.length = static_cast(MAX_ALLOCATION_ADDRESS - result.start); + result.length = static_cast(MAX_ALLOCATION_END_EXCL - result.start); result.permissions = nt_memory_permission(); result.initial_permissions = nt_memory_permission(); result.allocation_base = {}; @@ -541,7 +541,7 @@ region_info memory_manager::get_region_info(const uint64_t address) if (lower_end <= address) { result.start = lower_end; - result.length = static_cast(MAX_ALLOCATION_ADDRESS - result.start); + result.length = static_cast(MAX_ALLOCATION_END_EXCL - result.start); return result; } diff --git a/src/windows-emulator/memory_manager.hpp b/src/windows-emulator/memory_manager.hpp index 669d9ecc..a6467fee 100644 --- a/src/windows-emulator/memory_manager.hpp +++ b/src/windows-emulator/memory_manager.hpp @@ -12,6 +12,7 @@ constexpr auto ALLOCATION_GRANULARITY = 0x0000000000010000ULL; constexpr auto MIN_ALLOCATION_ADDRESS = 0x0000000000010000ULL; constexpr auto MAX_ALLOCATION_ADDRESS = 0x00007ffffffeffffULL; +constexpr auto MAX_ALLOCATION_END_EXCL = MAX_ALLOCATION_ADDRESS + 1ULL; // This maps to the `basic_memory_region` struct defined in // emulator\memory_region.hpp diff --git a/src/windows-emulator/syscalls/memory.cpp b/src/windows-emulator/syscalls/memory.cpp index a727101c..403ba2a7 100644 --- a/src/windows-emulator/syscalls/memory.cpp +++ b/src/windows-emulator/syscalls/memory.cpp @@ -20,6 +20,13 @@ namespace syscalls return STATUS_NOT_SUPPORTED; } + if (base_address < MIN_ALLOCATION_ADDRESS || base_address >= MAX_ALLOCATION_END_EXCL) + { + if (return_length) + return_length.write(0); + return STATUS_INVALID_PARAMETER; + } + if (info_class == MemoryBasicInformation) { if (return_length) diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index 988f396a..8cd1c0a8 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -328,7 +328,7 @@ windows_emulator::windows_emulator(std::unique_ptr emu, const e this->map_port(mapping.first, mapping.second); } - this->setup_hooks(); + this->setup_hooks(); } windows_emulator::~windows_emulator() = default; @@ -434,9 +434,6 @@ void windows_emulator::on_instruction_execution(const uint64_t address) void windows_emulator::setup_hooks() { - uint64_t tsc_base = splitmix64(0xCAFEBABEDEADBEEFull); - constexpr uint64_t tick_scale = 50; - this->emu().hook_instruction(x86_hookable_instructions::syscall, [&] { this->dispatcher.dispatch(*this); return instruction_hook_continuation::skip_instruction; @@ -445,8 +442,7 @@ void windows_emulator::setup_hooks() this->emu().hook_instruction(x86_hookable_instructions::rdtscp, [&] { this->callbacks.on_rdtscp(); - const uint64_t retired = this->executed_instructions_; - const uint64_t ticks = tsc_base + (retired * tick_scale); + const auto ticks = this->clock_->timestamp_counter(); this->emu().reg(x86_register::rax, static_cast(ticks)); this->emu().reg(x86_register::rdx, static_cast(ticks >> 32)); @@ -460,8 +456,7 @@ void windows_emulator::setup_hooks() this->emu().hook_instruction(x86_hookable_instructions::rdtsc, [&] { this->callbacks.on_rdtsc(); - const uint64_t retired = this->executed_instructions_; - const uint64_t ticks = tsc_base + (retired * tick_scale); + const auto ticks = this->clock_->timestamp_counter(); this->emu().reg(x86_register::rax, static_cast(ticks)); this->emu().reg(x86_register::rdx, static_cast(ticks >> 32)); diff --git a/src/windows-emulator/windows_emulator.hpp b/src/windows-emulator/windows_emulator.hpp index 720bec3b..86e2a0e2 100644 --- a/src/windows-emulator/windows_emulator.hpp +++ b/src/windows-emulator/windows_emulator.hpp @@ -225,11 +225,3 @@ class windows_emulator void register_factories(utils::buffer_deserializer& buffer); }; - -static inline uint64_t splitmix64(uint64_t x) noexcept -{ - x += 0x9E3779B97F4A7C15ull; - x = (x ^ (x >> 30)) * 0xBF58476D1CE4E5B9ull; - x = (x ^ (x >> 27)) * 0x94D049BB133111EBull; - return x ^ (x >> 31); -} \ No newline at end of file From 22df3e7889b41603fbc4c108e6d167d81e006558 Mon Sep 17 00:00:00 2001 From: CarlTSpeak Date: Fri, 24 Oct 2025 11:13:55 +0100 Subject: [PATCH 3/3] Fix format issue --- src/windows-emulator/syscalls/memory.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/windows-emulator/syscalls/memory.cpp b/src/windows-emulator/syscalls/memory.cpp index 403ba2a7..0b8e45c3 100644 --- a/src/windows-emulator/syscalls/memory.cpp +++ b/src/windows-emulator/syscalls/memory.cpp @@ -23,7 +23,9 @@ namespace syscalls if (base_address < MIN_ALLOCATION_ADDRESS || base_address >= MAX_ALLOCATION_END_EXCL) { if (return_length) + { return_length.write(0); + } return STATUS_INVALID_PARAMETER; }