What are some best practices for “hiding” sensitive code?
I was quite surprised to find a key gen for my app. I’m pretty sure they didn’t reverse engineer the serial number algorithm but instead found the relevant code.
I include function names in the build because they are needed for crash reports. However, all code related to serial generation uses non obvious Class and Method names. I assume that variables, properties and comment names are not visible in built apps.
I assume my Achilles heal is somewhere in my app I have
If not ModuleThatMakeSerials.ValidSerial(SerialNumber) then // obviously named better
MsgBox "This text should be easy to search for"
End If
and someone can, with some tools that I don’t know about, step through the assembled code at key points and then extract it out with the appropriate life support equipment.
I usually don’t give them the right names, but more random character sequences for the name.
I don’t think there is a way you can prevent this, so after taking reasonable precautions, add a blacklist of usernames (obfuscated, of course) that brings up a stern warning about the cost of piracy. Mine does that, erased the “registration”, then takes the user to the web site to purchase.
Well, there is not a definitive solution. You can control some aspects of the problem, but not all.
For your particular problem (a keygen) you can make it harder to decode using the advice from Christian or Kem, and also not relegating a license validation to a method which simply returns a boolean (very easy to track with a debugger).
A better method to avoid a keygen is to adopt AquaticPrime. I did this in past exactly for this problem and therefore I started a Xojo/RS port of the AquaticPrime which then Thomas Tempelmann completed and updated and wrote a nice tutorial on his web site (http://www.tempel.org/UsingAquaticPrime). You can find the repository for AP here: https://github.com/bdrister/AquaticPrime
With AP, a license is tied to an email address or the user name or whatever personal data you want, so no more keygens (due to the complexity of breaking the AP algorithm and low chances to have some user which give away his license.
And you can still blacklist some licenses, if needed.
AquaticPrime is a good way to verify license codes. Just make sure you are encrypting/obfuscating/encoding the public key somehow. Otherwise a cracker can just sub in their own public key then sign a fake license with their own private key.
My tool Arbed can obfuscate all strings in Xojo projects right now, though I hope to also add method name obfuscation on day. When? Well, I’m like Xojo in this regard: I want to have it tomorrow but it’ll probably take one or two years
Not to spoil Arbed, which is a really nice tool that every Xojo developer should have, here its an IDE script which makes a very basic string obfuscation.
Just select the string to obfuscate in code editor and run the script.
////////////////////////////////////////////////////////////////////////////////
// simple string obfuscation
////////////////////////////////////////////////////////////////////////////////
dim selectedText as string
dim obfuscatedText as string
dim obfuscChar as string
dim obfuscLineLen as integer
dim selectionStart as integer
dim currentCode as string
dim ascValue as integer
dim i, n as integer
const MAX_LINE_LEN = 80
if selLength > 0 then
selectedText = selText
selectionStart = selStart
if selLength > 1 and left(selectedText, 1) = """" and right(selectedText, 1) = """" then
selectedText = mid(selectedText, 2, len(selectedText) - 2)
end if
n = len(selectedText)
for i = 1 to n
if obfuscLineLen > MAX_LINE_LEN then
obfuscLineLen = 0
obfuscatedText = obfuscatedText + " _" + endOfLine
end if
if obfuscatedText <> "" then
obfuscatedText = obfuscatedText + "+"
obfuscLineLen = obfuscLineLen + 1
end if
ascValue = asc(mid(selectedText, i, 1))
if ascValue < 128 then
obfuscChar = "chr(" + str(ascValue) + ")"
else
obfuscChar = "encodings.UTF8.chr(" + str(ascValue) + ")"
end if
obfuscLineLen = obfuscLineLen + len(obfuscChar)
obfuscatedText = obfuscatedText + obfuscChar
next
selText = obfuscatedText
currentCode = Text
i = selectionStart
while i > -1
if mid(currentCode, i, 1) = endOfLine then
if mid(currentCode, i-1, 1) <> "_" then
exit
end if
end if
i = i -1
wend
currentCode = left(currentCode, i) _
+ "// obfuscated string = " + selectedText + endOfLine _
+ mid(currentCode, i+1)
Text = currentCode
end if
Encrypting strings really want help. Most crackers will run your program using a debugger, they will create a breakpoint
on the routine that asks for the registration info. They will then find the algorithm that verifies the information then
copy this code and create a key generator.
Good crackers understand assembly language very well, programs like OllyDbg do a real good job of giving them the code
which they can extract or just patch.
If your program is popular there is nothing you can do. All the big companies have tried, Microsoft, IBM, intel… all have been cracked
or have key generators.
Ultimately the point is to drive more revenue, not necessarily stop people who were never going to buy anyway.
I can see encrypting strings for API keys and whatnot. How would it help with a serial generator?
Looks like the best bet is, as George mentioned, to not have a single routine that returns a serial. Or, switch to Aquatic Prime.
And, as Phillip said, reasonable precautions should be taken but the focus should be on the product, not the protection.
I suggest reading an old article about this topic: http://tidbits.com/article/6752
Just adopt some fair protection to avoid casual piracy and sharing of licenses (which again feeds casual piracy).
And font get wrong in thinking that all people using a pirated copy of your product would buy it if you protect it enough. Most of them would not buy it in any case.
Then stop thinking to this and invest your time enhancing your product, not the protection scheme.