2

I'm working on a mild anti-cheat solution in order to counteract changes to device time. The goal is to determine the current DateTime by using the device uptime. When the device is rebooted, the value should be synchronized to whatever the device reports.

It will be combined in a layered structure where an internet time will be used first (if available), then uptime and lastly default to the device time.

All I'm missing is a reliable method of detecting whether the device was rebooted between app sessions.

I have tried:

  • Getting the boottime from the kernel. This is not an option since the boottime will change when the device time is altered.
  • Creating a file in NSTemporaryDirectory() and checking whether it exists when the app starts. Unfortunately, the file persists for a minimum of 1 week before it is deleted on reboot.
  • Comparing uptime. This can result in a false positive in the following scenario:
    Started the app at 14:00, with an uptime of 20min => I determine the boottime to be 13:40.
    Started the app at 15:00, with an uptime of 25min => I am unable to determine whether the user rebooted the device at 14:35, or if the time was changed without rebooting the device.

I am able to detect a reboot on Android by reading the contents of a file located at /proc/sys/kernel/random/boot_id. It is populated with a randomly generated ID on every boot. I have not been able to find something similar on iOS.

I retrieve the uptime/boottime using this code:

struct timeval boottime;
int mib[2] = {CTL_KERN, KERN_BOOTTIME};
size_t size = sizeof(boottime);
time_t now;
time_t uptime = -1;
(void)time(&now);
if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 && boottime.tv_sec != 0)
{
    uptime = now - boottime.tv_sec;
}
return uptime;
Wemju
  • 21
  • 1

1 Answers1

0

Comparing uptime. This can result in a false positive in the following scenario: Started the app at 14:00, with an uptime of 20min => I determine the boottime to be 13:40. Started the app at 15:00, with an uptime of 25min => I am unable to determine whether the user rebooted the device at 14:35, or if the time was changed without rebooting the device.

If you can't trust the time you get from the system, get it from an external source instead. See Get Date and Time from Apple Server for suggestions on using Network Time Protocol for this. You can then use uptime to calculate the boot time and compare that to the previously calculated and stored boot time.

Caleb
  • 124,013
  • 19
  • 183
  • 272
  • I am looking for a solution where internet time is not required, since this is the fallback solution, as I mentioned in the original post: "It will be combined in a layered structure where an internet time will be used first (if available), then uptime and lastly default to the device time." – Wemju Nov 12 '19 at 20:11