views:

472

answers:

4

I'm currently using a simple XML file that contains license information along with the data's signature and public key. So far, this method is working great. However, I'm seeing one rather large security flaw...

When my ASP.NET MVC application starts, it verifies the license and sets the "ValidLicense" bool property accordingly. During each request, this property is checked and an error message is displayed if the license is invalid.

As you can guess, there's absolutely nothing to stop a competent user from simply modifying my assembly to set "ValidLicense" to true regardless of the license's validity. I know this can be done to pretty much any application, but it seems incredibly easy to do with .NET assemblies.

What are some ways that I can stop this from happening, or at least make it a little more difficult to crack the license verification procedure?

I'd rather stay away from assembly encryption and obfuscation systems, if possible. Go ahead and suggest them if you feel that they are good enough to warrant the cost and extra headache, however.

+3  A: 

Instead of a simple boolean variable, you could perform a complex calculation every time you need to verify the license and base your logic on the result from that calculation. You do get a perf hit, though. And cracking your assembly wouldn't be that much harder anyway.

You could also employ some more advanced techniques, like dynamic mutation of the code and using the a corresponding mutable function to control the flow of your logic.

However, you should ask yourself does your assembly really contain such precious intelectual property, as to warrant the time and efforts to implement anything like this? It might be more viable and cheaper to go the legal route and battle the potential piracy if and when it occurs.

Franci Penov
+8  A: 

The only way to win is not to play.

The people who are going to steal your stuff (regardless of what protections you put in place), are not the people who are going to pay for it if it's too hard for them to break.

Greg Hewgill
I agree, don't focus on license security... Focus on features that make people wanna buy your software. You'll never get rid of piracy no mater what precautions you put in place, simple or complex. So spare yourself the trouble and try to give your legitimate customers the best product possible.
JohannesH
+1  A: 

You can make it a bit more complicated but in the end it will come down to one (or several) booleans: Either you run the code or you don't. Non-obfuscated.NET code is pretty much the same as open source and it is ridiculously easy to crack open.

Even if obfuscation is not a full solution, I think it would make sense to obfuscate, just to prevent fringe amateurs from producing cracked versions.

Of course it won't stop a real cracker who is willing to spend the time, but just by putting the bar a little higher, you can weed out a lot of crackers wannabes.

Obfuscation can be pretty simple to implement for free. If you have a commercial version of Visual Studio, you can use DotFuscator (not with the "Express" editions). I never tried, but I guess it should be simple enough.

Otherwise, you can use Assemblur. (http://www.metapropeller.com/). The free version is a command line application (there is a GUI to create the setting file, but you need to run the settings from the command line).

All in all, it barely takes a couple minutes to obfuscate a simple exe file and it's free

If you want to make your license check a little more challenging, you can make different checks inside various methods, and you can also make sure that the license checking code does not actually output any string directly. (for instance, you do a license check in method A, but you output the error warning from method B, so that when a cracker looks for the license error message, he doesn't land right on the bit of code to be changed).

All it does is raise the bar for wannabe crackers and make things more complex for a real cracker.

Case 1: Non obfuscated .NET application with 1 license check method which output a "not licensed" error message. Can be cracked in about 5 minutes by anyone who can run reflector.

Case 2: Obfuscated .NET application with a couple different license checks and no obvious string output. Could take hours for a cracker and prove too hard for a wannabe.

You can get from case 1 to case 2 with about 1 hour of work, without spending a dime. Going beyond that is probably a waste of time (everything can be cracked) but at least, you can weed out the folks who open your application in Reflector just to see if it's going to be easy. If the guy opens the application in reflector and sees something like:

public bool ValidateLicense(string sLicense)
{
    string sInvalidLicense = "Your license is not valid";
    ...
}

Guess what happens next?

//EDIT: In a comment, LC asked:

How do you not have it output any string message but still notify the user? Even if you do a license check and output in two different methods, you'll still have a the binary decision "if(!ValidateLicense(LicenseCode)) {NotifyUserOfInvalidLicense(); throw new LicenseException();}" or something, no?

Put yourself in the shoes of a cracker: You are looking for the License validation code. You are not going to study the whole code just to find it. Instead, you run the application unlicensed: The error message shows up.

You take that error message, you open the assembly in Refactor and you search for a part of that error message.

If that string is located inside "ValidateLicence()", you immediately find the ValidateLicence() function. From there, you only need to locate the return value and change that 1 byte. Done.

If the string is found instead inside "WhatEver()", you still needs to find what methods call "WhatEver()". It might not even be in the same assembly (in which case Refactor will not find it for you). This makes the job harder for your wannabe cracker. He will have to look at that method to see how it validates the code (which it doesn't). He might even be sloppy and change the return value of the wrong method, in which case he introduces a bug (if the method is obfuscated, figuring out what it does is not that simple).

Better yet, don't use a string at all: you can store the error message as a sequence of hex codes, and convert it to string dynamically when you need to display the message. No error string means that the cracker will have to rely on something else to locate your license validation code. And reading through obfuscated code is not fun.

You could also have a fake validation method containing the error message and suppress the warning to make it look like the crack worked.

So, a couple of simple, stupid tricks like these + simple obfuscation are very easy to implement and they can turn a 5 minutes "In and Out" cracking session into weeks of work for the cracker, because not only does he need to find and crack your validation code, but he also has to test to make sure that everything is working and that he didn't just fix a decoy or unwillingly created nasty bugs. Now, he just can't be sure without testing.

In the end, cracking an assembly is just a matter of changing a few bytes, and you can't prevent anyone from changing bytes in your assembly's files. Everything can be cracked.

However you can make it a hell of a lot harder to find which bytes have to be changed, and at the very least, you can avoid having a string that says "the byte you are looking for is right here".

Sylverdrag
Please don't confuse "able to see the source" with "open source"; the latter has an open licence implication, whereas the former does not necessarily guarantee that right.
Rob
How do you not have it output any string message but still notify the user? Even if you do a license check and output in two different methods, you'll still have a the binary decision "if(!ValidateLicense(LicenseCode)) {NotifyUserOfInvalidLicense(); throw new LicenseException();}" or something, no?
lc
@Rob: "Able to see the source"/"Open source". I was only referring to the fact that accessing the code is almost as easy with a .NET assembly. Of course, just because you can see the code doesn't give you the right to do so.
Sylverdrag
A: 

An approach I met when trying to hack a little .NET product was to use an unmanaged .DLL for the licence checking. And not only that, the .DLL also contained a lot of code that was actually used in the software. So, to crack product I actually had to crack the unmanaged .DLL (or make a perfect wrapper). Needless to say, this stopped a wannabe cracker like me. :)

Vilx-