Dynamically update KUSD system time

This commit is contained in:
momo5502
2024-11-23 21:46:34 +01:00
parent 2e2b4ffb2f
commit d3cf88a0c4
4 changed files with 75 additions and 4 deletions

View File

@@ -19,6 +19,20 @@ inline void deserialize(utils::buffer_deserializer& buffer, std::chrono::steady_
tp = time_point{duration{count}};
}
inline void serialize(utils::buffer_serializer& buffer, const std::chrono::system_clock::time_point& tp)
{
buffer.write(tp.time_since_epoch().count());
}
inline void deserialize(utils::buffer_deserializer& buffer, std::chrono::system_clock::time_point& tp)
{
using time_point = std::chrono::system_clock::time_point;
using duration = time_point::duration;
const auto count = buffer.read<duration::rep>();
tp = time_point{duration{count}};
}
inline void serialize(utils::buffer_serializer& buffer, const std::filesystem::path& path)
{
buffer.write_string<wchar_t>(path.wstring());

View File

@@ -1,4 +1,5 @@
#include "kusd_mmio.hpp"
#include "syscall_utils.hpp"
#include "windows_emulator.hpp"
#include <address_utils.hpp>
@@ -103,6 +104,7 @@ kusd_mmio::kusd_mmio(windows_emulator& win_emu, const bool use_relative_time, co
, win_emu_(&win_emu)
{
setup_kusd(this->kusd_, use_relative_time);
this->start_time_ = convert_from_ksystem_time(this->kusd_.SystemTime);
if (perform_registration)
{
@@ -118,6 +120,7 @@ kusd_mmio::~kusd_mmio()
kusd_mmio::kusd_mmio(kusd_mmio&& obj) // throws!
: use_relative_time_(obj.use_relative_time_)
, win_emu_(obj.win_emu_)
, start_time_(obj.start_time_)
{
memcpy(&this->kusd_, &obj.kusd_, sizeof(this->kusd_));
@@ -137,12 +140,14 @@ void kusd_mmio::serialize(utils::buffer_serializer& buffer) const
{
buffer.write(this->use_relative_time_);
buffer.write(this->kusd_);
buffer.write(this->start_time_);
}
void kusd_mmio::deserialize(utils::buffer_deserializer& buffer)
{
buffer.read(this->use_relative_time_);
buffer.read(this->kusd_);
buffer.read(this->start_time_);
this->register_mmio();
}
@@ -185,7 +190,22 @@ void kusd_mmio::write(const uint64_t /*addr*/, const size_t /*size*/, const uint
void kusd_mmio::update()
{
// TODO
auto time = this->start_time_;
if (this->use_relative_time_)
{
const auto passed_time = this->win_emu_->process().executed_instructions;
const auto clock_frequency = this->kusd_.QpcFrequency;
using duration = std::chrono::system_clock::duration;
time += duration(passed_time * duration::period::den / clock_frequency);
}
else
{
time = std::chrono::system_clock::now();
}
convert_to_ksystem_time(&this->kusd_.SystemTime, time);
}
void kusd_mmio::register_mmio()

View File

@@ -39,6 +39,7 @@ private:
bool use_relative_time_{};
windows_emulator* win_emu_{};
KUSER_SHARED_DATA kusd_{};
std::chrono::system_clock::time_point start_time_{};
uint64_t read(uint64_t addr, size_t size);
void write(uint64_t addr, size_t size, uint64_t data);

View File

@@ -175,11 +175,12 @@ void write_attribute(emulator& emu, const PS_ATTRIBUTE& attribute, const T& valu
}
}
constexpr auto HUNDRED_NANOSECONDS_IN_ONE_SECOND = 10000000LL;
constexpr auto EPOCH_DIFFERENCE_1601_TO_1970_SECONDS = 11644473600LL;
constexpr auto WINDOWS_EPOCH_DIFFERENCE = EPOCH_DIFFERENCE_1601_TO_1970_SECONDS * HUNDRED_NANOSECONDS_IN_ONE_SECOND;
inline std::chrono::steady_clock::time_point convert_delay_interval_to_time_point(const LARGE_INTEGER delay_interval)
{
constexpr auto HUNDRED_NANOSECONDS_IN_ONE_SECOND = 10000000LL;
constexpr auto EPOCH_DIFFERENCE_1601_TO_1970_SECONDS = 11644473600LL;
if (delay_interval.QuadPart <= 0)
{
const auto relative_time = -delay_interval.QuadPart;
@@ -207,3 +208,38 @@ inline std::chrono::steady_clock::time_point convert_delay_interval_to_time_poin
return std::chrono::steady_clock::now() + duration_until_target;
}
inline KSYSTEM_TIME convert_to_ksystem_time(const std::chrono::system_clock::time_point& tp)
{
const auto duration = tp.time_since_epoch();
const auto ns_duration = std::chrono::duration_cast<std::chrono::nanoseconds>(duration);
const auto total_ticks = ns_duration.count() / 100 + WINDOWS_EPOCH_DIFFERENCE;
KSYSTEM_TIME time{};
time.LowPart = static_cast<uint32_t>(total_ticks);
time.High1Time = static_cast<int32_t>(total_ticks >> 32);
time.High2Time = time.High1Time;
return time;
}
inline void convert_to_ksystem_time(volatile KSYSTEM_TIME* dest, const std::chrono::system_clock::time_point& tp)
{
const auto time = convert_to_ksystem_time(tp);
memcpy(const_cast<KSYSTEM_TIME*>(dest), &time, sizeof(*dest));
}
inline std::chrono::system_clock::time_point convert_from_ksystem_time(const KSYSTEM_TIME& time)
{
auto totalTicks = (static_cast<int64_t>(time.High1Time) << 32) | time.LowPart;
totalTicks -= WINDOWS_EPOCH_DIFFERENCE;
const auto duration = std::chrono::system_clock::duration(totalTicks * 100);
return std::chrono::system_clock::time_point(duration);
}
inline std::chrono::system_clock::time_point convert_from_ksystem_time(const volatile KSYSTEM_TIME& time)
{
return convert_from_ksystem_time(*const_cast<const KSYSTEM_TIME*>(&time));
}