Introduction

24 Hour Fitness has converted their check-in method to time-based QR codes generated by their app 24GO.

This sucks. The app is not very optimized, sucks down battery, and takes almost 200MB of space. The app blocks screenshots of the QR code and the code changes every 5 minutes. However, there are some flaws in their verification logic that we can use to convert this time-based QR code to a static one that can be added to Apple or Android Wallets without the need for dynamic background services or push updates!

Getting the QR Data

Since the app prevents you from screen-shotting (at least on iOS) you’ll have to use another camera to scan the QR code to get the JSON data. After you scan it, you should get something like this:

{"TP":"X","OS":"X","DT":9999999999999,"DI":"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX","AP":"X.XX.X","MB":"MBRXXXXXXXX","SR":"24GO"}

Values have been replaced to avoid leaking personal info. From what I can glean, these are the definitions of each value:

  • TP: Not sure what this indiacates.
  • OS: This is the operating system, on my iPhone the value is iOS
  • DT: The DateTime value in Unix Epoch time
  • DI: This appears to be the device identifier and is unique to the phone
  • AP: This indicates the app version
  • MB: This is your 24 Hour Fitness Member Number, unique to you
  • SR: Indicates the scan source, it seems in all cases the value is 24GO, the app.

Circumventing the Time-Based Aspect

Generally these types of QR codes rely on a salted dynamic value, even if that’s just a salted DateTime value. That is not the case here, which means as long as we regenerate the JSON string as a QR code with the current time every 5 minutes we should be fine.

However it gets even better. During some field testing I discovered that the check-in system only checks if the DT value is older than the limit, not if it’s in the future.

This means we can set the DT value to something in the future and it passes the time validation check. I haven’t found a limit to the system, so technically you can set the time to however far you want in the future (i.e. Jan 1 2077), but I would keep it within reason and only add a year or two.

The Steps

Take your original DT value and add 31557600000 to it, which is the number of seconds in 1 year (with millisecond precision). If you want to do a different time you can use a Unix time calculator like UnixTimestamp to do it for you.

Slap your modified Unix Epoch time back into the JSON object and convert it to a QR code. There are lots of sites you can use for this, like SmallDevTools.

Wallet Pass generators like AddPass.io can generate the QR code for you. You paste the JSON text into the QR code generation box, and can even input a geolocation for the wallet to automatically open up to.