C#: How to Make It Harder for Hacker/Cracker to Get Around or Bypass the Licensing Check

C#: How to Make it Harder for Hacker/Cracker to Get Around or Bypass the Licensing Check?

The #1 law of software licensing: You don't control your software once you allow it to be installed on a computer you don't control.

If you want to keep control over your code, you need to make it a web service and give the end user just a thin client that interfaces to that web service.

In many scenarios, this is unacceptable, because users want to be able to use their software even when they don't have an internet connection.

In almost all cases, you should focus on making the user experience better, and all forms of copy protection make it worse instead. Once you get to the point where the experience of downloading from a warez site and running it through several virus scans is better than doing the license setup for the legit version, you've lost.

How to generate and validate a software license key?

Caveat: you can't prevent users from pirating, but only make it easier for honest users to do the right thing.

Assuming you don't want to do a special build for each user, then:

  • Generate yourself a secret key for the product
  • Take the user's name
  • Concatentate the users name and the secret key and hash with (for example) SHA1
  • Unpack the SHA1 hash as an alphanumeric string. This is the individual user's "Product Key"
  • Within the program, do the same hash, and compare with the product key. If equal, OK.

But, I repeat: this won't prevent piracy


I have recently read that this approach is not cryptographically very sound. But this solution is already weak (as the software itself has to include the secret key somewhere), so I don't think this discovery invalidates the solution as far as it goes.

Just thought I really ought to mention this, though; if you're planning to derive something else from this, beware.

How to prevent spoofing of DLLs in .NET

You mention:

This DLL contains a class, say ScoreKeeper that implements a method called GetHighScore(). The application calls this periodically.

And then:

Is there a way to prevent the .NET application from using a "non-authorized" DLL here in place of the one I am supplying?

Assuming that you want to prevent someone from swapping out the assembly you have provided with an assembly of their own which has the same name and type (which is in the same namespace), you could apply a strong name to the assembly that contains the ScoreKeeper class and have your consumers reference that.

However, we'll see that there are issues that make this not 100% reliable. Strong Names help you protect unaware users from replacement of your DLL with a malicious spoofed copy. But if the user is complicit in the spoofing (which would be the case if he is trying to cheat), then code signing will be no more than a speed bump and provides no real protection. Certainly, Strong Names don't provide protection comparable to e.g. PunkBuster.

Using a Strong Name to verify an assembly publisher's identity

When you add a strong name to an assembly, you are using a private key (part of an asymmetric public/private key pair, more on this later) to generate a cryptographic hash and the public key is included in the assembly name (along with the hash).

Using the public hash and the public key, the CLR is able to verify that the signature of the assembly did in fact come from the private key.

Of course, this means, you should protect the key (internally and externally); if someone else has your key, then they can effectively impersonate you and publish assemblies that people would trust to be from you.

Then, when you add a reference to your signed assembly, if someone tries to put a different assembly in with the same assembly name (not the fully qualified one, just the name without version, hash and public key) and same type name, the CLR fill fail when trying to load the type, indicating that it couldn't find it; the type is resolved using the fully-qualified assembly name, along with the namespace and type name.

Why Strong Names are not 100% secure (is anything?)

1) Hash Collisions

It is still a hash that is being verified. While the hash is quite large (160 bits for the default hash algorithm, SHA-1), any hash that has a finite number of values is subject to a collision. While extremely unlikely, it is possible (impossible vs. improbable). Furthermore, only the last 8 bytes is used by default. Combined with research indicating that SHA-1 is relatively weak, this is a good reason to use SHA-256 Enhanced Strong Naming as described in MSDN.

2) Removal of the Strong Name

The strong name can be removed. However, in this case, because your assembly is referencing the strong named version of the referenced assembly, when your assembly tries to use the compromised version, it will fail at runtime, assuming you've correctly re-enabled verification (see below).

3) Physical access to the assemblies means all the assemblies

If someone has access to the physical machine and can modify the assembly that you are referencing, then your assembly is just as vulnerable. If the attacker has the ability to modify the strong name of an assembly that you referenced, then they can just as easily modify your assembly and all others involved in the execution. To this end, the only way to be 100% sure that the physical assembly isn't hacked is to deny physical access through it. Of course, that brings up a slew of different security concerns.

4) Administrator disabling the Strong Name check

The computer administrator can simply bypass the strong name check, using sn -Vr. According to MSDN:

Registers assembly for verification skipping... A malicious assembly could use the fully specified assembly name (assembly name, version, culture, and public key token) of the assembly added to the skip verification list to fake its identity. This would allow the malicious assembly to also skip verification.

5) Strong Name checking has to be explicitly enabled post .NET 3.5 SP 1

From .NET 3.5 SP 1 on, simply having a strong name doesn't provide any protection:

Starting with the .NET Framework version 3.5 Service Pack 1 (SP1), strong-name signatures are not validated when an assembly is loaded into a full-trust AppDomain object, such as the default AppDomain for the MyComputer zone.

In order to have .NET check the strong name of each assembly loaded into your application, you'll want to insert the following snippet (provided by MSDN) into your application configuration file:

<configuration>
<runtime>
<bypassTrustedAppStrongNames enabled="false" />
</runtime>
</configuration>

Beware, however, that this only protected against removal of the strong name.

When you override the bypass feature, the strong name is validated only for correctness; it is not checked for a StrongNameIdentityPermission. If you want to confirm a specific strong name, you have to perform that check separately.


If in light of the concerns above, you'd still like to pursue Strong Naming your assembly, here's how.

Generating a Strong Name and signing your assembly

You have two options for which key to use when generating a strong name. In Visual Studio, go to the Signing tab on the project properties and click "Sign the assembly":

"Sign the assembly" option on the "Signing" tab of the project properties in VS.NET

From there, you have two options to generate the public/private key, to have VS.NET generate the keys for you, or point to an existing one:

"New" or "Browse" options for choosing a strong name key file

When selecting "New", Visual Studio will prompt you for the name of the file to generate, as well as whether or not you want to optionally use a password to access it:

Create strong name key dialog

At which point, the key will be added to your project:

Key added to project

Now, you can move this to a solution item (if you have multiple projects in your solution).

Visual Studio in this case is really just calling the Strong Name command line tool to generate a public and private key pair. If you'd rather do that yourself, you'd want to call sn.exe with the -k command line option to generate the key, like so:

sn -k keyPair.snk

And then add it via the "Browse" dialog above.

Note that when you do this, it will pull the key into your project. If you don't want to do this (as it copies the key into every project), then delete the key from the project and then add an existing file to the project, but link it. This will clear the "Choose a strong name key file" option, but if you drop it down, you'll see the full path to your linked key file.

Use WebRequest to check if a license is valid

Another way to bypass the license check is to redirect the checking url to localhost returning always the desired text...

A better way is to make a call to a function doing the same thing but make your server response a signed XML including the server response time-stamp, that you can check on addition with the system datetime (use UTC dates in both sides). It is also a good idea to throw exceptions whenever something is not the way you expect it, and control the flow of your program with exception handling.

Check the following to get a how to clue:

How to: Sign XML Documents with Digital Signatures

How to: Verify the Digital Signatures of XML Documents

How to protect .Net exe from Decompiling/Cracking


1- How to make sure that .Net application will not get cracked ?

If a computer can run your code + The hacker can run his own code at a higher privilege level than you, there is nothing that can 100% prevent your app from being cracked. Even if they just have access to the executable but not the target platform they still can step through and mimic what the target platform would do and figure out how the protection is being done.

2- The hacker now knows my code since he has done the modification. What steps should i take ?

Totally rewrite the authentication portion so they have to start from scratch but they will get it again, it is just a matter of how long.

3- I read on the internet about - obfuscators . But the hacker knows my code what should i do ?

The jinni is out of the bottle now that they have the non-obfuscated code. There is not much you can do unless you drastically re-write the software so they have to start from scratch. A obfuscateor will not prevent a determined attacker, they only thing that can prevent it is keeping the binary out of their hands.

4- Any other Pro tips that i can use to avoid getting the software cracked ?

The only copy protection I have seen to remotely delay for any period of time is what Ubisoft did with Assassin's Creed: Brotherhood. They encrypted ther levels with the game disk and it had to download the decryption key from the internet as it was needed (This is the keeping the binary out of their hands approach). But that did not work forever, eventually the hackers did get those levels decrypted and it was fully cracked. This approach is just what I saw take the longest time to get around without legal involvement (See point 2 at the bottom)

5- I am not sure but can these reflector softwares also decompile the App.Config with sensitive data ?

All the reflector software needs to do is look for the section that loads App.config and read what the defaults are. There is no secure place to store information on a computer you do not have full control over. If it is on the computer, it can be read. If it can be read, it can be reverse engineered.


The only real solution I can see to prevent piracy is one of two options.

  1. The person never gets your app, it is streamed from a server under your control and they never get to see the binary. The only thing you send them is the information they need to drive the UI. This is the approach that all MMO's work on. People can reverse engineer what you are sending to the UI and mimic the logic that is going on on your servers but they will never be able to outright see what it is doing and if your software is complex enough it may not be feeseable for the attacker to recreate the server side code. The downside to this approach is you will need to host servers for your users to connect to, this will be a reoccurring cost you will need a way to re-coup. Often this method is called a "Rich Client" or "Thin Client" depending on how much processing is done client side and how much processing is done server side. See Chapter 22 of "Microsoft Application Architecture Guide, 2nd Edition". Specifically I am describing what is shown in figure 4 and 5

  2. The seccond option is whoever you sell your software too have them sign a legal contract not to distribute the software (not a EULA, a actual contract that must be physically signed by the client). In that contract have large fines be applied to the person who leaks the software, then riddle your program with fingerprints that are unique to the person who buys the software so that when the program is leaked you can see who did it. (This is the method the vendor Hex-Rays use for their disassembler IDA. A quick google search could not turn up any cracked versions newer than 6.1, they are on 6.3). This method will not stop piracy, but it may discourage the copy to be leaked in the first place. This also lets you recover some lost costs associated with the program being leaked in the first place. One issue is that you will need to put a lot of fingerprints and they will need to be subtle, if a attacker can get two copies of the program and can compare the files between the two he will be able to tell what is the identifying information and just put whatever they want in so they can't tell who they got it from. The only way to do this is put a lot of red-herrings in that can't just be stripped out or randomized, also make the identifying code non-critical to running the software, if they don't have to work to crack it they are more likely to leave it in.


Update: After revisiting this answer to link to it for another question I thought of a easy way of implementing the #2 solution.

All you need to do is run your code through an obfuscateor and let it rename your classes for every person you sell your software to (I would still make them sign a license agreement, not just click a EULA so you can enforce the next part). You then make a database of the obfuscation mapping, when you see a leaked copy on the internet you just need to find one class anywhere in the project, look it up in your database, and you will know who leaked it and know who you need to go after for legal damages.

Is it possible to 'strip' a .NET DLL?

You could use the InternalsVisibleToAttribute and not make anything public, but...

You're mistaken if you think that anything stops someone from using non-public classes from your DLL. An application with full-trust can access private and internal content no problem, or they can decompile and rebuild the DLL with everything public.

People will suggest obfuscation, but that doesn't do much more.

You should read this answer (and question, but mostly answer): C#: How to Make it Harder for Hacker/Cracker to Get Around or Bypass the Licensing Check?



Related Topics



Leave a reply



Submit