What this tutorial is:
Ideas on how to keep your app/game safe from hackers.
What this tutorial is NOT
Complete instructions on how to implement any of these ideas.
A number of years ago, I became a shareware author. Like most software authors, I decided on a licensing registration scheme. The plan was simple. PayPal has a wonderful feature called the Instant Payment Notification (IPN)
Anytime someone purchases your software, PayPal will automatically send you a gob of information on the purchase. I'd use a PHP file to grab that info, stuff it into a MySQL database and then use the PayPal transaction number to generate a registration key. I'd then require the user to enter the transaction ID number and the matching registration key to activate the product (I sent these to them by Email). It was, to me, an elegant solution because I could always verify any registration key against a PayPal transaction.
The fallacy of any elegant solution is that the moment your digital product becomes popular, you will get hacked.
I got hacked
As my little shareware product became more popular, hackers took an interest in me. First, they came out with a list of fake registration ID numbers and a corresponding list of registration keys. Sure enough, if I entered one of their fake ID's and the key, it would register my product.
Then... the hackers created a keygen for my product. With it, anyone could enter any ID they wanted and it instantly generated a working registration number. The fact that there was a trojan embedded in this keygen didn't seem to matter. People still downloaded it an used it.
The lesson here is... you will get hacked, prepare for it.
Anticipating being hacked
Before I even released my first version, I expected the worst. And I'm glad I did. One of the things I had my little program do was to contact a php file on my server. Along with tracking usage (which you can find in one of my other tutorials) I also had the foresight to compare the user's IP address to a list of cheapskates I manually kept. If the incoming IP address matched one in the list, it sent me an Email letting me know. But I did nothing to them, I kept letting them use their cracked copy. The other thing my little program did was to send the registration ID to my php script. I could then compare it to my database of known PayPal transaction numbers. If it wasn't there, it was a cracked copy. Again, it sent me an Email letting me know, but I again, did nothing.
So, why didn't I react immediately?
Hackers are an egotistical bunch. One of the reasons they crack software is simply to prove it can be done. But they're not always intelligent. While they did manage to generate gobs and gobs of fake registration information, they simply overlooked the part where my software contacted that php file when it started up. So here I was, knowing I'd been hacked and I was being notified every single time.
Crushing the hacker's ego
When a hacker releases a crack, they pride themselves in the fact that they did it. Have a look at a keygen sometime (if you're brave enough) and they always include a file with their logo and their names. They want attention. One of the most embarrassing things for a group of hackers is to have their little toys suddenly stop working. They put in all this effort to crack your software and release the crack and then... a month later, it doesn't work any more.
By not acting immediately, I let them think that they successfully cracked my shareware and they moved on to something else. Then, a month later, I began banning registration keys. Anytime my software contacted the server I compared the ID to my known list of good ID's and, if it didn't match, the program simply reset itself back to the demo version and... banned any attempt from that computer to register it again by setting a buried registry key and saving a small file to the hard drive (it's a Windows only program). If that key or the file existed, it simply denied any attempt to register the product. Screw me once, I don't need your money.
Did it work?
My Email notifications of people using cracked registration codes went down from 20 a day to 1 or 2 a week. And, the only way for them to remove the ability my software had to contact the server was to release a completely cracked copy of my software. To date, I haven't found any.
So, how can you protect a C2 app/game
Here's a little trick I used to send information back to my software from the server, a trick that will work just as well with C2.
When my software contacted the server's php script, the script logged their connection, checked against banned keys and addresses and then, sent a response back. I needed the software to know if it had been banned and if it was a valid registration. So, I needed a way to get two booleans back to my software without making it obvious. My solution, random numbers.
That is an example of what my script sent back to the software. And each time it responded, the numbers completely changed and the length of the number changed. So how can you possibly get information from that?
First chop out everything except a couple of numbers.
For example: System.Set FirstNumber to mid(AJAX.LastData,12,2)
FirstNumber is then set to 20.
Then System.Set SecondNumber to mid(AJAX.LastData,14,2)
SecondNumber is then set to 83
So, how can we turn this into a boolean? Modulo! Modulo divides a number by another number and gives you the remainder. That makes it easy to check and see if it's an even or an odd number by dividing it by 2. If it is even, then the result will = 0. If it's odd, the result will = 1. In the world of binary numbers, 0 is false, 1 is true. See how this works?
Using System, compare two numbers you can int(FirstNumber) % 2 = 0 followed by an 'else'.
If it is = 0, then the response from the server is false. If it's 1, the response is true.
So, by using modulo, the response we just got back from that string of numbers is:
FirstNumber = false (it's 0)
SecondNumber = true (it's not 0)
By using modulo and a string of random numbers, C2 can also send buried boolean information back and forth to a server using AJAX.
How do you create these true/false numbers in C2? Again, modulo. Create a random(10,98) and stuff it into a variable like MyModulo. Then check to see if it's even or odd by MyModulo % 2. If the result is 0 then it's false. If you want it to be true... add 1 to it. (That's why you only randomize up to 98. If you did 99 it could come back with a 3 digit number.)
Need more than just booleans? It's possible but this will take some creativity in C2 since it doesn't have a way to convert characters to other types (think array) ASCII Table
You could send text buried in a gob of apparently random numbers as octals.
Now while this doesn't exactly substitute for encryption, I can tell you without a doubt, that getting a piece of software to encrypt data using an algorithm, send it to a server and then get a server side script to decrypt that data is a chore. And while anyone determined enough can figure this out given enough time, at least your data isn't going to be plainly visible should they try to sniff the packets your game/app is sending back and forth. The more curve balls you throw at would-be hackers, the more they're likely to miss something.
Sometimes, the best place to hide things is in plain sight.