1

Background

I got this thought when playing idle-games. These are games that basically play themselves and usually work like so that there are one or more systems which generate some kind of resources for the player over time. The player can then use these accumulated resources to further upgrade the resource generators to generate even more resources over time.

Problem

These games often include some kind of offline progression system. When you shut the game down, the game saves the time it was shut down and when you open the game up again, it checks the current time, compares it to the time recorded when the game was shut down and calculates how much offline progression the player achieved during that "offline" time.

Most of these games just naively use the computer's clock to fetch the time when the game shuts down and goes back up, while some games fetch a time from a server to verify the elapsed time. If the game uses the computer's clock, the offline progression system can be easily exploited by shutting the game down, setting the computer clock to some time in the future and opening the game back up.

So we can consider a case like this:

  • The game is shut down at 12:00 according to the computer's clock
  • The user comes back at 14:00 (real time) and changes the computer's clock to 20:00
  • The user open the game back up and the game sees there has been 20:00 - 12:00 = 8h of offline progress, when in reality, there has only been 14:00 - 12:00 = 2h of offline progress

The question

So the question is:

Is there a known method for locally verifying the real elapsed time, i.e. not using a server, a separate time keeping process, or equivalent?

The game (or any program for that matter) should be able to verify the real elapsed time (against the computer's time) with reasonable accuracy (1) and do so reasonably locally (2).

(1) Say that the real elapsed time is 10 hours, but the computer's clock is saying 100 hours, I think that a solution which is able to verify if it's been 10 hours or 100 hours could be good enough

(2) Using a separate process or a server is not allowed, but since the game / program has to save the shut down time into the local filesystem either way, we might as well allow writing and reading files alltogether. However, having a background task / process / service which updates the elapsed time into a file is not allowed.

Ideas

I've got a couple of ideas I have been thinking.

Using something with a known duration

If we had something which we know takes x time, such as some kind of calculation, could we somehow use that to our advantage? This might be problematic, because at least my thoughts go straight into having a separate process performing some calculation which takes a set amount of time, but that wouldn't be allowed.

Using hardware tokens, JWT or equivalent in some clever way

I was thinking that since hardware tokens (especially those old keychain authenticators) work offline, the idea behind those could be adapted to this in some clever way.

As far as I know, the token itself is completely offline, but the idea is that the token is synchronized with some server, after which they share the same seed and timing. In our case, I guess the game would be the server and the token would be some file, which won't work because the whole problem here is that the server's clock can be changed.

So I thought what if we could somehow swap those around? What if the game is the hardware token and the file is the server? Well, the file cannot keep the time without an external process, so I doubt that would work either.

What about JWTs then? One thing about these tokens is that they are kind of hard to invalidate ahead of time. So when a valid token is generated for a user for, say, 24 hours, the user can use that token with the permissions the user had at the time of the token generation, regardless if those permissions get changed during those 24 hours. With JWTs, there is still the server though...

Time locked or dependent encryption algorithms?

I was thinking of cash registers. Those can only be opened at certain times. I wonder if there exists an encryption algorithm, which somehow only allows decryption after a set elapsed time? Or inversely, an encryption algorithm which somehow won't allow decryption after a set elapsed time?

Using uptime

I dabbled around in Excel to figure out whether we could use the computer's uptime somehow:

enter image description here

Here we close the game at 12:00 and open it back up the next day at 8:00. If the computer wasn't shut down during that time period, the uptime will match the elapsed time.

However, if the computer was shut down at any point during that time period, this does not work.

More generally, the uptime can be UT + IVL or < IVL, where UT is the uptime when the game was closed and IVL is the time between closing the game and opening it up again. This is great if the computer wasn't rebooted, as it would create an exact UT + IVL restriction, but the < IVL part ruins the whole thing, as the user could skip forwards any amount of time and restart their PC after to pass the check.

Using CMOS RTC

The CMOS RTC is what keeps the time even when the computer is shut down. While this can be also tampered with, it would be a great deal more challenging and / or annoying to do. However, it is also a great deal more challenging to read from. According to this StackOverflow article for example, it seems like it cannot be read by software directly.

So while this could potentially be a strong candidate for a solution, I think that the users might have a problem with their idle-game shipping with some kind of ring-0 kernel mode driver (as it is the case with most anti-cheat solutions) just to keep the god damn time.

Furthermore this would technically violate the restrictions set for this problem if a separate driver is needed - surely that counts as a separate process!

Windows performance monitors & event log

Now this one could work, but I haven't have time to test it out yet.

Since most operating systems keep some sort of performance logs, like CPU usage, voltages, ... could we just use those to see if time has been skipped forward? I'm not sure if the data is in time-value format, but if it is, we should be able to see that the system clock has been moved forward because the performance logs have suddenly skipped forward.

Even if the data is not in time-value format, I think we could look at certain data and see if there are some kind of mismatches with the elapsed time.

Then there's the event log as well. In the best case scenario, I guess there would be an event for changing the system clock, but even if there isn't, couldn't we use the lack of the events as a detection method? If the time has been skipped forward by 1 week for example, but there hasn't been a single system even during that time, we could flag that?

Outside of the box solutions (just for fun... unless...)

Skipping 100 years into the future can be simply blocked out by the fact that almost nobody lives that long. Skipping 50 years into the future, and still using x64 architecture should be pretty unlikely as well. Maybe there are similar "solutions" for ruling out 25, 10, 5, or even 1 year?

I think if the user is seemingly using the exact same hardware after 10 years, that would be suspicious as well.

DHCP-lease configuration could be one potential flag as well, if it can be obtained. If the lease is, say, 24 hours and the time elapsed is more than 24 hours, the lease should have at least refreshed during that time. Though this requires online I think.


So is something like this just outright impossible? Are there any real-world examples where something like this is used?

Swiffy
  • 4,401
  • 2
  • 23
  • 49

1 Answers1

1

This is impossible. As you've discovered as you design and discard solutions, all actual solutions require some piece of hardware you trust because the user does not control it. Your hardware token idea is the only thing you've listed that is plausible, assuming the token's hardware has its own clock and is hardened against tampering. This is just a computer that you trust because the user does not control it. There is no way to trust hardware that someone else controls, and there is no way to measure time without hardware.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • What about systems like streaming services, which allow you to download content for offline viewing? I'm pretty sure that the offline-content has some kind of expiry date, after which the user is required to "check in" online to continue using the offline-content. Surely those systems are not dependent on the clock of the mobile device for example? How is the expiry implemented in such cases and what is the expiry date checked against, if it can't be anything online? – Swiffy Jun 26 '23 at 17:36
  • They're absolutely dependent on the system clock. You can augment that by trying to detect clock manipulation (see https://stackoverflow.com/a/76542337/97337), but the only thing you can do when you detect it is to refuse to continue until the user connects. You can't determine how much time has actually passed. Your problem, however, is a bit harder. It's much easier to detect backwards movements rather than forward movements. But if someone moves forward several times, eventually they will likely move backwards to make their clock correct (or by finally connecting to the server). – Rob Napier Jun 26 '23 at 18:42