OnlineUnlockStatus vulnerabilities


#1

Hi everybody,

I am currently implementing a simple copy protection scheme using the OnlineUnlockStatus and I am by no means an expert on this field (I just followed common sense and the documentation of this class).

Basically you implement all virtual functions of OnlineUnlockStatus with your project specific data and then scatter your non-realtime code randomly with the isUnlocked() checks to make the cracking an annoying process.

But I think the weakest point of this class is the getPublicKey() method. Because its a virtual function, it can’t be inlined (unlike the actual isUnlocked() check).

If you find this method (which is called exactly once at the point where you load the key file), you can simply exchange the public key with a public key matching to another private key and use this in a keygen to create perfectly valid licence files.

Now basically there are two strategies:

  1. Try to harden this copy protection scheme (eg. by adding a hash of your public key somewhere into the binary and check if it stays correct. This check should be called as frequently as the isUnlocked() check).

  2. Stop further efforts because if a cracker can find the public key, he is good enough to solve every other puzzle you throw at him within minutes.

What would you recommend (and what is your experience in this field)? I certainly don’t need a bulletproof solution (because there is none), but want to apply as much effort as needed to prevent little idiots with reverse debuggers to create a keygen within the first days.


#2

What’s to stop the cracker from just replacing the key hash with whatever they want, or jumping past the check against the key hash? I suppose a way around this would be to inline the key hashing/checking so that the public key has to be replaced many times (though I’m probably incorrect in understanding how this works).


#3

Yes, if this function can be inlined and is called more frequently than the getPublicKey(), it would be harder to find every occurrence of this check:

#define PUBLIC_KEY "123456789"
#define SALT "xyz"
#define PRECALCULATED_HASH "7b46dd7a1b8e0037616496d6744c3014f9a0480e439f86e815deb782ee576330"

inline var isPublicKeyValid() const
{
    return SHA256(PUBLIC_KEY + SALT).toHexString() == String(PRECALCULATED_HASH);
}

#4

FYI I recently added a command-line utility to the Projucer to generate obfuscated code for strings. My own use-case for this was for hiding RSA keys.
Just run it with the --obfuscated-string-code flag.


#5

Thanks, this works like a charm. Would it be useful to embed this functionality directly in the OnlineUnlockStatus class (it is a bit hidden right now).