From f924a8bf06fb9ea1c5ddef0f3bd4300c63769353 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 7 Mar 2026 00:09:08 +0800 Subject: [PATCH] Uptime: reads `(System|Interrupt)Time` directly from `SharedUserData` --- src/common/time.h | 15 +++--------- src/common/windows/nt.h | 4 ++++ src/detection/uptime/uptime_windows.c | 34 +++++++-------------------- 3 files changed, 16 insertions(+), 37 deletions(-) diff --git a/src/common/time.h b/src/common/time.h index d8506d3b8..b4e0587d7 100644 --- a/src/common/time.h +++ b/src/common/time.h @@ -4,17 +4,9 @@ #include #include #ifdef _WIN32 - #include #include + #include "common/windows/nt.h" #include - #include - - NTSYSCALLAPI - NTSTATUS - NTAPI - NtDelayExecution( - _In_ BOOLEAN Alertable, - _In_ PLARGE_INTEGER DelayInterval); #elif defined(__HAIKU__) #include #endif @@ -40,8 +32,7 @@ static inline double ffTimeGetTick(void) //In msec static inline uint64_t ffTimeGetNow(void) { #ifdef _WIN32 - uint64_t timeNow; - GetSystemTimeAsFileTime((FILETIME*) &timeNow); + uint64_t timeNow = ffKSystemTimeToUInt64(&SharedUserData->SystemTime); return (timeNow - 116444736000000000ull) / 10000ull; #elif defined(__HAIKU__) return (uint64_t) real_time_clock_usecs() / 1000u; @@ -58,7 +49,7 @@ static inline bool ffTimeSleep(uint32_t msec) #ifdef _WIN32 LARGE_INTEGER interval; interval.QuadPart = -(int64_t) msec * 10000; // Relative time in 100-nanosecond intervals - return NtDelayExecution(TRUE, &interval) == STATUS_SUCCESS; + return NT_SUCCESS(NtDelayExecution(TRUE, &interval)); #else return nanosleep(&(struct timespec){ msec / 1000, (long) (msec % 1000) * 1000000 }, NULL) == 0; #endif diff --git a/src/common/windows/nt.h b/src/common/windows/nt.h index df85b9c76..27d516ec9 100644 --- a/src/common/windows/nt.h +++ b/src/common/windows/nt.h @@ -2,6 +2,8 @@ #include #include +#include +#include enum { SystemModuleInformation = 11, @@ -423,6 +425,8 @@ typedef struct _SYSTEM_FIRMWARE_TABLE_INFORMATION _Field_size_bytes_(TableBufferLength) UCHAR TableBuffer[]; } SYSTEM_FIRMWARE_TABLE_INFORMATION, *PSYSTEM_FIRMWARE_TABLE_INFORMATION; +NTSTATUS NTAPI NtDelayExecution(_In_ BOOLEAN Alertable, _In_ PLARGE_INTEGER DelayInterval); + /** * The KSYSTEM_TIME structure represents interrupt time, system time, and time zone bias. */ diff --git a/src/detection/uptime/uptime_windows.c b/src/detection/uptime/uptime_windows.c index c5cd7245a..c5a4d423f 100644 --- a/src/detection/uptime/uptime_windows.c +++ b/src/detection/uptime/uptime_windows.c @@ -1,34 +1,18 @@ #include "uptime.h" #include "common/time.h" -#include "common/library.h" - -#include -#include +#include "common/windows/nt.h" const char* ffDetectUptime(FFUptimeResult* result) { - #if FF_WIN7_COMPAT - HMODULE hKernelBase = GetModuleHandleW(L"KernelBase.dll"); - if (__builtin_expect(!!hKernelBase, true)) - { - FF_LIBRARY_LOAD_SYMBOL_LAZY(hKernelBase, QueryInterruptTime); - if (ffQueryInterruptTime) // Windows 10 and later - { - uint64_t uptime; - ffQueryInterruptTime(&uptime); - result->uptime = uptime / 10000; // Convert from 100-nanosecond intervals to milliseconds - goto ok; - } - } + // GetInterruptTime with Win7 support + uint64_t interruptTime = ffKSystemTimeToUInt64(&SharedUserData->InterruptTime); - result->uptime = GetTickCount64(); -ok: - - #else - uint64_t uptime; - QueryInterruptTime(&uptime); - result->uptime = uptime / 10000; // Convert from 100-nanosecond intervals to milliseconds - #endif + result->uptime = interruptTime / 10000; // Convert from 100-nanosecond intervals to milliseconds result->bootTime = ffTimeGetNow() - result->uptime; + + // Alternatively, `NtQuerySystemInformation(SystemTimeOfDayInformation)` reports the boot time directly, + // whose result exactly equals what WMI `Win32_OperatingSystem` reports + // with much lower accuracy (0.5 seconds) + return NULL; }