Tuesday, March 27, 2012

Sometimes I think you should have to have a license to write protection.

Tonight's application was a database monitoring application written mostly in unobfuscated java. Is this 1999 and no one told me? I mean SERIOUSLY. And the thing that made it all that much better was that this code runs under Tomcat, and while running something called Jasper, it spit out .java versions of some of the important files. I didn't even have to decompile them! (shaking head). OK, so here's how it all works. You get a license key from the vendor when you register your trial, or buy a license from them. It comes in the form of a string of characters that you copy & paste into a form in the program. (It's all web based evidently). This license key contains a server name if you buy a license, or a string that they identify later as the "trial sentinel", and a number. This number is the time since the epoch in milliseconds for when your trial, or license expires. At runtime, in just about every module, they load this string from the key file, decrypt it, and pull the 2 halves out. (There is a delineation character between the fields). Then, they simply compare the time to now, if it comes back negative, your license has expired, and you need to get a new one.

So, as you see, the lynch pin of this WHOLE protection boils down to a simple string decryption routine. It was written in java as well, and unobfuscated for your reversing pleasure. A little while examining it, and I was able to write my very own ENcrypter, so that I can now make license files till the cows come home. Here's the pertinent code:


void EncryptString(char *s)
{
char temp[1026];
char output[2049];
unsigned char x, y;
unsigned char len = (strlen(s) & 0xFF);

memset(temp, 0x00, 1026);
memset(output, 0x00, 2049);

temp[0] = len ^ 0x95;
temp[1] = s[0] ^ 0x95;
temp[2] = s[1] ^ 0x59;

for(x = 3; x <= len; x++)
{
temp[x] = s[x - 1] ^ temp[x - 3];
}

for(x = 0, y = 0; x <= len; x++)
{
output[y++] = ((temp[x] & 0xF0) >> 4) | 0x40;
output[y++] = (temp[x] & 0x0F) | 0x40;
}

printf("[%s]\n", output);
}

The 1st byte of the license is the LENGTH xor'd with 0x95, followed by the serverID, followed by the expiration time. They do a pseudo rolling encryption where the value of THIS byte is xor'd with the value of another byte in the string, (3 bytes away). Once they have this, they simply walk through the string, pull out the upper nibble, shift it right, and OR it with 0x40, as that makes it printable, and then pull the lower nibble, and OR it with 0x40. Then, save those bytes, and move along. So, the resulting string ends up being twice as long as the actual payload.

I can only hope that these guys kick ass on database applications, and that it works better than their attempt at protection. Maybe they're finally wising up, and are only trying to "keep the honest people honest", as that's about all this scheme would do.