有没有办法检测系统时钟是否在 Windows 中向后更改?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7852209/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 08:51:04  来源:igfitidea点击:

Is there a way to detect if the system clock has been changed backwards in windows?

windowswinapi

提问by Nick Randell

On a windows machine, is there a way to find out if the time has been changed backwards without continually monitoring for WM_TIMECHANGE messages?

在 Windows 机器上,有没有办法在不持续监视 WM_TIMECHANGE 消息的情况下找出时间是否已向后更改?

For example, I would like to make the first thing my application does on startup is see if the time has been changed back since I last run the application.

例如,我想让我的应用程序在启动时做的第一件事是查看自上次运行该应用程序以来时间是否已更改回来。

As far as I can tell, the only way to see a change is to look at the WM_TIMECHANGE message, but I will only see that if my application is running.

据我所知,查看更改的唯一方法是查看 WM_TIMECHANGE 消息,但只有在我的应用程序正在运行时才能看到。

回答by Paul Sasik

Yes. You can read the Windows Event Logsand look for changes to system time. (System time changes are one of the system events that are automatically logged.) For example, I just tweaked my system time by a few seconds and the following appeared in the System Event log:

是的。您可以阅读Windows 事件日志并查找系统时间的更改。(系统时间更改是自动记录的系统事件之一。)例如,我只是将系统时间调整了几秒钟,系统事件日志中出现以下内容:

Information 10/21/2011 11:16:26 AM Kernel-General 1 None

The system time has changed to ?2011?-?10?-?21T16:16:26.000000000Z from ?2011?-?10?-?21T16:16:26.000000000Z.

信息 10/21/2011 11:16:26 AM Ke​​rnel-General 1 无

系统时间已从 ?2011?-?10?-?21T16:16:26.000000000Z 更改为?2011?-?10?-?21T16:16:26.000000000Z。

You can use the Win32 API to get access to the event logsthen query for these events to determine if the time was indeed altered. What's great about this solution is that it's built-in and always running. No need to monitor events via a custom service etc. You just query the OS's data.

您可以使用 Win32 API 访问事件日志,然后查询这些事件以确定时间是否确实被更改。此解决方案的优点在于它是内置的并且始终运行。无需通过自定义服务等监控事件。您只需查询操作系统的数据。

This is still not a bullet-proof solutionsince people with admin rights can chance settings, clear logs etc. But you would definitely layperson-proof your app. System event logs are not something regular Windows users think about.

这仍然不是一个万无一失的解决方案,因为具有管理员权限的人可以设置、清除日志等。但您肯定会为您的应用程序提供外行证明。系统事件日志不是普通 Windows 用户考虑的事情。

The XML for that particular event: (de-identified for privacy & security)

该特定事件的 XML:(为了隐私和安全而去标识化)

  <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
  <System>
  <Provider Name="Microsoft-Windows-Kernel-General" 
        Guid="{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" /> 
  <EventID>1</EventID> 
  <Version>0</Version> 
  <Level>4</Level> 
  <Task>0</Task> 
  <Opcode>0</Opcode> 
  <Keywords>0x8000000000000010</Keywords> 
  <TimeCreated SystemTime="2011-10-21T16:16:26.001000000Z" /> 
  <EventRecordID>138478</EventRecordID> 
  <Correlation /> 
  <Execution ProcessID="40044" ThreadID="50016" /> 
  <Channel>System</Channel> 
  <Computer>xxxxx.xxxxxxxxx.org</Computer> 
  <Security UserID="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" /> 
  </System>
  <EventData>
  <Data Name="NewTime">2011-10-21T16:16:26.000000000Z</Data> 
  <Data Name="OldTime">2011-10-21T16:16:26.000000000Z</Data> 
  </EventData>
  </Event>

回答by Mahmoud Al-Qudsi

No, you can't. That's why time-sensitive DRM schemes are in general rather useless.

不,你不能。这就是为什么对时间敏感的 DRM 方案通常毫无用处。

You couldtry to work around it by using a service, and then you'd have to work around the service's downtime by using another hack, and another hack on top of that as well.

可以尝试通过使用服务来解决它,然后您必须通过使用另一个 hack 来解决服务的停机时间,以及在此之上的另一个 hack。

Anyway, if that's all you're trying to do then simply storing somewhere (encrypted, possibly) the value of the system time on your program's shutdown, then making sure that it has not been passed on program startup shouldbe enough. It won't stop users that basically "froze" the time from shutdown to startup, but it'll be enough for 9/10 of the people trying to get past your timed trial.

无论如何,如果这就是你要做的则只需存储的地方(加密,可能)的系统时间程序的关闭值,然后确保它没有被传递程序启动时都应该是足够的。它不会阻止那些基本上“冻结”从关机到启动时间的用户,但对于 9/10 试图通过您的定时试用的人来说已经足够了。

回答by MusiGenesis

You could have your app (while it happens to be running) periodically compare the system time with a time fetched from a server resource somewhere. If you suddenly see that the difference between system time and server time has increased, that means the system time has been set back.

您可以让您的应用程序(当它恰好正在运行时)定期将系统时间与从某处服务器资源获取的时间进行比较。如果你突然发现系统时间和服务器时间的差值变大了,那说明系统时间已经调回来了。

Obviously this wouldn't work on a machine with no Internet access.

显然,这不适用于无法访问 Internet 的机器。

回答by Dominic Haigh

One idea to that above (while I note that checking against an external clock is the definitive answer if feasible) - you can also periodically read the system clock and store it, perhaps encrypted, in a hidden file somewhere. Each time you do this you check to make sure the new value is more recent than the one in the file. The trigger to doing this could be at every startup etc.

上面的一个想法(虽然我注意到如果可行,检查外部时钟是确定的答案) - 您还可以定期读取系统时钟并将其存储(可能已加密)在某个隐藏文件中。每次执行此操作时,您都会检查以确保新值比文件中的值更新。这样做的触发因素可能是每次启动等。

Like all internal methods this one is vulnerable to someone figuring out the hidden file. You can also therefore flag a problem if the hidden file is missing, or if its date stamp doesn't match its contents.

像所有内部方法一样,这个方法很容易被人找出隐藏文件。因此,如果隐藏文件丢失,或者其日期戳与其内容不匹配,您也可以标记问题。