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?
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.
Yes. You can read the Windows Event Logs and 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:
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.
You can use the Win32 API to get access to the event logs then 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.
This is still not a bullet-proof solution since 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.
The XML for that particular event: (de-identified for privacy & security)
<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>
No, you can't. That's why time-sensitive DRM schemes are in general rather useless.
You could try 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.
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 should be 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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With