From dbc1b4439e08043a39c63e42834c0e3e49936db3 Mon Sep 17 00:00:00 2001 From: Soham Nandy Date: Thu, 10 Apr 2025 06:58:01 +0530 Subject: [PATCH] feat: spoof rdtsc timings Previously, RDTSC in the VM always returned a constant value, which broke any non deterministic timing-based operations, or caused detections in heuristics of malware and ANTI-VM tools. This patch introduces a spoofed rdtsc_fake counter that tracks and adjusts timing deltas to simulate realistic TSC increments. Can be extended to simulate rdtsc timings based on CPU clock speed. --- src/common/utils/time.hpp | 22 ++++++++++++++++++++++ src/windows-emulator/windows_emulator.cpp | 22 +++++++++++++++++++--- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/common/utils/time.hpp b/src/common/utils/time.hpp index b887e789..e2d2e5c6 100644 --- a/src/common/utils/time.hpp +++ b/src/common/utils/time.hpp @@ -3,6 +3,10 @@ #include #include "../platform/platform.hpp" +#if defined(_MSC_VER) +#include +#pragma intrinsic(__rdtsc) +#endif constexpr auto HUNDRED_NANOSECONDS_IN_ONE_SECOND = 10000000LL; constexpr auto EPOCH_DIFFERENCE_1601_TO_1970_SECONDS = 11644473600LL; @@ -29,6 +33,24 @@ namespace utils { return std::chrono::steady_clock::now(); } + + // Returnds the current timestamp counter value. RDTSC on x86/x64, or just time since epoch for ARM + /// TODO: find better solution for ARM and Figure out better CPU base frequency heuristics + virtual uint64_t timestamp_counter() + { +#if defined(_MSC_VER) +#if defined(_M_X64) || defined(_M_AMD64) || defined(_M_IX86) + return __rdtsc(); // 64-bit with MSVC intrinsic +#endif + +#elif defined(__x86_64__) || defined(__i386__) || defined(__amd64__) // If we are using clang or gcc + unsigned int lo, hi; + __asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi)); + return ((uint64_t)hi << 32) | lo; +#endif + return static_cast(std::chrono::high_resolution_clock::now().time_since_epoch().count()) * + 3.8; // should be base cpu frequency here; + } }; class tick_clock : public clock diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index e87f7044..d127d569 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -448,9 +448,25 @@ void windows_emulator::setup_hooks() }); this->emu().hook_instruction(x64_hookable_instructions::rdtsc, [&] { - const auto instructions = this->executed_instructions_; - this->emu().reg(x64_register::rax, instructions & 0xFFFFFFFF); - this->emu().reg(x64_register::rdx, (instructions >> 32) & 0xFFFFFFFF); + uint64_t ticks = this->clock_.get()->timestamp_counter(); + static uint64_t fake_ticks = ticks; + static uint64_t prev_ticks = 0; + + if (prev_ticks != 0) + { + if (ticks > prev_ticks) + { + fake_ticks += (ticks - prev_ticks); + } + } + if (fake_ticks > ticks) + { + fake_ticks = ticks; + } + prev_ticks = ticks; + + this->emu().reg(x64_register::rax, fake_ticks & 0xFFFFFFFF); + this->emu().reg(x64_register::rdx, (fake_ticks >> 32) & 0xFFFFFFFF); return instruction_hook_continuation::skip_instruction; });