Загрузка данных


#include <windows.h>

typedef struct _KSYSTEM_TIME
{
    ULONG LowPart;
    LONG High1Time;
    LONG High2Time;
} KSYSTEM_TIME, *PKSYSTEM_TIME;

typedef struct _KUSER_SHARED_DATA
{
    ULONG TickCountLowDeprecated;
    ULONG TickCountMultiplier;
    volatile KSYSTEM_TIME InterruptTime;
    volatile KSYSTEM_TIME SystemTime;
    volatile KSYSTEM_TIME TimeZoneBias;
    USHORT ImageNumberLow;
    USHORT ImageNumberHigh;
    WCHAR NtSystemRoot[260];
    ULONG MaxStackTraceDepth;
    ULONG CryptoExponent;
    ULONG TimeZoneId;
    ULONG LargePageMinimum;
    ULONG AitSamplingValue;
    ULONG AppCompatFlag;
    ULONGLONG RNGSeedVersion;
    ULONG GlobalValidationRunlevel;
    LONG TimeZoneBiasStamp;
    ULONG NtBuildNumber;
    NT_PRODUCT_TYPE NtProductType;
    BOOLEAN ProductTypeIsValid;
    BOOLEAN Reserved0[1];
    USHORT NativeProcessorArchitecture;
    ULONG NtMajorVersion;
    ULONG NtMinorVersion;
    BOOLEAN ProcessorFeatures[64];
    ULONG Reserved1;
    ULONG Reserved3;
    volatile ULONG TimeSlip;
    ALTERNATIVE_ARCHITECTURE_TYPE AlternativeArchitecture;
    ULONG BootId;
    LARGE_INTEGER SystemExpirationDate;
    ULONG SuiteMask;
    BOOLEAN KdDebuggerEnabled;
    union
    {
        UCHAR MitigationPolicies;
        UCHAR CycleDivider;
    };
    USHORT ActiveConsoleId;
    volatile USHORT DismountCount;
    ULONG ComPlusPackage;
    ULONG LastSystemRITEventTickCount;
    ULONG NumberOfPhysicalPages;
    BOOLEAN SafeBootMode;
    UCHAR VirtualizationFlags;
    ULONG TraceLogging;
    ULONGLONG TestRetInstruction;
    LONGLONG SystemCall;
    ULONG SystemCallReturn;
    ULONGLONG SystemCallPad[3];
    union
    {
        volatile KSYSTEM_TIME TickCount;
        volatile ULONGLONG TickCountQuad;
    };
    ULONG Cookie;
    ULONG ConsoleHandle;
    ULONGLONG TimeUpdateLock;
    ULONGLONG BaselineSystemTimeQpc;
    ULONGLONG BaselineInterruptTimeQpc;
    ULONGLONG ReservedForFutureUse;
    ULONGLONG ReservedForFutureUse2;
} KUSER_SHARED_DATA, *PKUSER_SHARED_DATA;

struct SavedState
{
    ULONGLONG InterruptTime;
    ULONGLONG SystemTime;
    LONGLONG TimeZoneBias;
    ULONG LastSystemRITEventTickCount;
    ULONGLONG TickCount;
    ULONGLONG TickCountMultiplier;
    ULONGLONG BaselineSystemTimeQpc;
    ULONGLONG BaselineInterruptTimeQpc;
    ULONGLONG PerformanceCounter;
    ULONGLONG PerformanceFrequency;
};

SavedState LoadFromBuffer(BYTE* kuser_old, ULONGLONG old_perf_counter, ULONGLONG old_perf_freq)
{
    PKUSER_SHARED_DATA old = (PKUSER_SHARED_DATA)kuser_old;
    SavedState state;

    state.InterruptTime = ((ULONGLONG)old->InterruptTime.High1Time << 32) | old->InterruptTime.LowPart;
    state.SystemTime = ((ULONGLONG)old->SystemTime.High1Time << 32) | old->SystemTime.LowPart;
    
    LONGLONG BiasHigh = ((LONGLONG)old->TimeZoneBias.High1Time << 32);
    state.TimeZoneBias = BiasHigh | old->TimeZoneBias.LowPart;
    
    state.LastSystemRITEventTickCount = old->LastSystemRITEventTickCount;
    state.TickCount = ((ULONGLONG)old->TickCount.High1Time << 32) | old->TickCount.LowPart;
    state.TickCountMultiplier = old->TickCountMultiplier;
    state.BaselineSystemTimeQpc = old->BaselineSystemTimeQpc;
    state.BaselineInterruptTimeQpc = old->BaselineInterruptTimeQpc;
    state.PerformanceCounter = old_perf_counter;
    state.PerformanceFrequency = old_perf_freq;

    return state;
}

void UpdateLoop(SavedState* state, DWORD update_interval_ms, BOOL* stop_flag)
{
    PKUSER_SHARED_DATA kuser = (PKUSER_SHARED_DATA)0x7FFE0000;

    while (!*stop_flag)
    {
        LARGE_INTEGER CurrentPerfCounter;
        QueryPerformanceCounter(&CurrentPerfCounter);

        ULONGLONG ElapsedQpc = CurrentPerfCounter.QuadPart - state->PerformanceCounter;
        ULONGLONG ElapsedMs = (ElapsedQpc * 10000) / state->PerformanceFrequency;

        state->InterruptTime += ElapsedMs;
        state->SystemTime += ElapsedMs;

        ULONGLONG ElapsedTickCount = (ElapsedQpc * state->TickCountMultiplier) >> 32;
        state->TickCount += ElapsedTickCount;
        state->LastSystemRITEventTickCount += (ULONG)ElapsedTickCount;

        state->PerformanceCounter = CurrentPerfCounter.QuadPart;

        kuser->InterruptTime.LowPart = (ULONG)state->InterruptTime;
        kuser->InterruptTime.High1Time = (LONG)(state->InterruptTime >> 32);
        kuser->InterruptTime.High2Time = (LONG)(state->InterruptTime >> 32);

        kuser->SystemTime.LowPart = (ULONG)state->SystemTime;
        kuser->SystemTime.High1Time = (LONG)(state->SystemTime >> 32);
        kuser->SystemTime.High2Time = (LONG)(state->SystemTime >> 32);

        ULONGLONG AbsBias = (state->TimeZoneBias < 0) ? (-state->TimeZoneBias) : state->TimeZoneBias;
        kuser->TimeZoneBias.LowPart = (ULONG)AbsBias;
        kuser->TimeZoneBias.High1Time = (LONG)(AbsBias >> 32);
        kuser->TimeZoneBias.High2Time = (LONG)(AbsBias >> 32);

        kuser->LastSystemRITEventTickCount = state->LastSystemRITEventTickCount;

        kuser->TickCount.LowPart = (ULONG)state->TickCount;
        kuser->TickCount.High1Time = (LONG)(state->TickCount >> 32);
        kuser->TickCount.High2Time = (LONG)(state->TickCount >> 32);

        kuser->BaselineSystemTimeQpc = CurrentPerfCounter.QuadPart;
        kuser->BaselineInterruptTimeQpc = CurrentPerfCounter.QuadPart;

        Sleep(update_interval_ms);
    }
}

int main()
{
    BYTE kuser_old[sizeof(KUSER_SHARED_DATA)];
    
    PKUSER_SHARED_DATA current = (PKUSER_SHARED_DATA)0x7FFE0000;
    memcpy(kuser_old, (PVOID)current, sizeof(KUSER_SHARED_DATA));
    
    LARGE_INTEGER old_perf_counter;
    LARGE_INTEGER old_perf_freq;
    QueryPerformanceCounter(&old_perf_counter);
    QueryPerformanceFrequency(&old_perf_freq);
    
    SavedState state = LoadFromBuffer(kuser_old, old_perf_counter.QuadPart, old_perf_freq.QuadPart);

    BOOL stop = FALSE;
    UpdateLoop(&state, 15, &stop);

    return 0;
}