Article Author: MohammadSadeq Dousti
Introduction
The act of using software illegally for commercial purposes is called software piracy . This includes making use of an illegal copy of software, even if no money is exchanged. According to BSA-IDC Piracy Study (May 2005), the United States is in the bottommost of pirating countries list and yet even with this position more than 1/5 (21%) of the software sold in the US is illegal! And if you work for an international enterprise, things are much worse- in some countries the piracy rate is more than 90%.
You may have also heard of another term- copyright infringement. This term is broader than software piracy, in that it includes any noncompliance of software copyright or license agreement, even if there are no commercial benefits. For example, some license agreements may prohibit the legal owner of the software from making backups for his/her sole purpose.
So, what should be done? You should arm your software with one or more protection schemes. But, the question is: which scheme is the best? This is a rather general question, and should be answered with respect to your needs and your software audience. However, I should warn you not to think that there is a silver bullet out there. In fact, there’s no perfect solution for protecting software, every lock has a key. Each scheme can be broken with enough effort by someone with sufficient knowledge. This is an "intellectual war", and your enemies are amongst the most clever people in their field. They are commonly called crackers (The similar term " hacker" has a very different meaning), and their job (or even their entertainment) is to crack software locks. So, if a third-party company claims they have created a protection scheme that no cracker can break, do not believe them, it’s just an advertisement. If your software is really popular, you may find a crack for it on the net in an hour or two after you release it.
At this point, you may think why on earth would you protect your software if it will get cracked anyways? This is a critical question, and it has a variety of answers. Firstly, and the most obvious answer, is that you decrease the number of illegal copies of your software distributed over the Internet. After all, how many real geniuses are out there and how many people have access to them?
The second answer is a bit subtle. According to a recent survey conducted by UGO.com (see Macrovision brochure in the links section) most people are willing to get 0-day (newly released) games: 33% will buy the game in the first week after its release if they can’t find a cracked version, 14% will buy it a week later, 9% will buy it in the third week, and 16% prefer to wait till the forth week and then buy the game in despair of not finding a cracked version. Although these percents are for games only, they can be generalized for any other piece of software, too. This doesn’t imply that the numbers will remain the same, but it suggests that people usually want a software title within a few days of its release, and a robust protection scheme may cause more people to purchase the product.
The bottom line is that if you can make it harder for crackers and hence slow down the process of cracked versions of your software becoming available, then more people will buy the licensed version. A similar point is that, if you protect your software against crackers and provide frequent updates and a good customer support for legitimate users, they will be more willing to buy it rather than using cracked or illegal copies of your software.
In this article, I’m going to introduce you to one of the many protection schemes, namely activation. In this scheme the user is usually asked to enter an activation code which is obtained after purchasing the software. This activation process then allows the user to continue using the software or it may unlock some features that the user needs. I will start by looking further into the details of the activation scheme and then jump into showing an example.
Why Activation?
There are various software protection schemes that are used today: serial numbers, hardware locks (a.k.a sentinel or dongle ), CD/DVD copy protection, packing, crypting, and so on. But, many products today have incorporated activation as their protection scheme. Microsoft is currently improving its Windows Product Activation (WPA), along with introducing a new activation scheme called Windows Genuine Advantage ( WGA ). All Adobe CS and CS2 product series (like Photoshop and Illustrator) use activation. Almost all antivirus products have some type of activation built into them as well.
So, why is activation becoming more popular everyday?
Let’s see some examples screenshots of activation in action. Figure 1 shows the Windows 2003 activation process. We can see that there are two distinct means for getting an activation code: over the Internet, or by phone.

Figure 1. Activating Windows
Figure 2 shows the Adobe Photoshop/ImageReady CS activation. Both Over the Internet and By telephone are present here as well.

Figure 2. Activating Adobe Products
The third example shown in Figure 3 shows the activation process for Dr DivX, a very popular MPEG-4 player and encoder allows three methods for getting an activation code: Web (same as the Internet), Fax, and Phone.

Figure 3. Dr DivX Activation
I think these examples have provided enough for the rest of the discussion. Activation is excellent for a variety of reasons:
- Activation provides a means of after-sale product and customer tracking. No other protection scheme is capable of this.
- Activation can be used in schemes like "Try Before You Buy" or "Play Before You Pay". I have seen some games which allow the gamer to play for an hour, and then they are asked for an activation number. Software protected with hardware locks, or games protected with CD/DVD-protection schemes are not capable of this, or at least they can’t be distributed over the Internet. (Can you imagine downloading bits of hardware from a website?)
- Software vendors can issue, renew, or even revoke the license through activation. A great example of this is provided by some antivirus vendors, whose software deactivates itself or otherwise refuses to function if it detects a stolen license is used when retrieving updates.
Activation has a number of drawbacks, however:
- Activation requires the user to connect to the Internet. Most vendors overcome this limitation using other options such as activation by phone but as you will see soon, this opens the door to crackers.
- Activation is not enough by itself. You should use activation plus some other protection schemes to secure the client (the software in question) from getting reverse engineered. Obviously you also need to secure the network connection (eg. by using https for activation-related communications) and the server.
- Activation is believed to compromise privacy by some people. Just take a look at the Microsoft Windows Product Activation Privacy Statement (see links section to read it) to get a feel of how big companies deal with privacy.
Activation via Internet vs. by Phone
In my own experience, most crackers exploit the activation by phone method because they cannot hack the server on the Internet, and patching the client can be difficult. Crackers reverse engineer the software, find the activation-code-generator algorithm, build a key generatorand they have now compromised your software. At this point anyone can use this key generator to acquire an activation number, and hence activate the software by phone. My advice is to use the by phone method only if the added user convenience for users who don’t wish to use the Internet is particularly important for your software.
Well, enough theory! Let’s see activation in action.
System Requirements
- IIS web server running on Windows XP / 200X
- .NET Framework version 1.x
- VS.NET 2003 or later.
This solution was developed on Windows Server 2003 Enterprise Edition SP1, .NET Framework 1.1 SP1, and Visual Studio 2003.
Installing and Compiling the Sample Code
The sample code consists of pairs of client / server programs. The client is configured to connect to a localhost server (127.0.0.1), but this can be changed to use a remote server. To run the code, just copy LicenseServer_v* directory to wwwroot directory of your IIS, give this directory the ability to host applications (from within Internet Information Services console), and run the client. (In Client_v* directory) The ASP project files are in LicenseServer_v* Project directory. All the code in this article uses C#. ( ~*’ corresponds to 1 or 2, e.g. LicenseServer_v1 or LicenseServer_v2 ).
Design Issues
The concept behind activation is simple, you have a product that needs to be activated (the client), a server that does that job and provides an activation number, and a database validates and stores licenses, as shown in Figure 4.

Figure 4. The concept behind activation
The details can be very complex, however. The client-side code must be secured. The client-server connection must be secured. If the database resides on a host different than the main server, the server-database connection must be secured, as well. The algorithms you use to generate activation number should be robust enough to keep crackers from easily reverse engineering it. Your server should not have any security holes at the OS or software level. In fact, entire books are devoted to explaining each part of this scheme (e.g. network security, OS security and DB security). To avoid this complexity, I’ll first provide you with a dummy client-server program, and then provide more details to enhance the model and make it more secure. I have also chosen to not implement the database in order to simplify the example.
The sample application takes some information from user and provides them with an activation number. It’s obvious that this scheme is not suitable for real world practices. After all, you need to differentiate legitimate users from the others. However, this model helps you get the big picture, and be able to focus on other details. I will discuss more complex issues to consider later in the article.
First we need to determine what information should be taken from a user in order to provide them with an activation number?
If you read the Microsoft Windows Product Activation Privacy Statement you will find that Windows activation uses the hardware on the system during activation. But, how does it understand which hardware belongs to a legitimate user? The answer is simple: It uploads the serial number you provided during the Windows setup. This model is called per-computer licensing.
Another model, called per-user licensing does not have to deal with hardware configurations. It only asks for some of the information the user provides on purchasing the software, e.g. name, company, and telephone number.
The Server Code
To keep this part of article simple, I used the per-user model, which only asks for user name. Then I use an algorithm to generate an activation number for that user. Here comes the challenging part of most of protection schemes: What algorithm should be used to generate a number given a set of information? I have chosen to use a very basic algorithm first, and describe a more complex version in more detail later. The algorithm converts each character of the username to its ASCII form, applies some substitutions and transpositions (more on this later), and returns an activation number. The following code snippet shows this process (the code is from the License.aspx.cs file from the LicenseServer_v1 project ):
private void Page_Load(object sender, EventArgs e)
{ if(IsPostBack) { StringBuilder sb= new StringBuilder(); String s= txtName.Text; if(s.Length==0) return; //make string length even if(s.Length % 2==1) s+=‘X’; //transposing odd and even bytes, //while converting each char to ASCII (hex) for(int i=0; i< s.Length; i+=2) { sb.Append(((byte)s[i+1]).ToString("X")); sb.Append(((byte)s[i]).ToString("X")); } s= sb.ToString(); //applying substitution s= s.Replace(‘0’,’-’); actNo.InnerText= s; }
}
Figure 5 shows the results of running the sample server application. As a test, I entered my name, and clicked Generate . Notice that the activation number is generated and displayed, this can be used to activate the client.

Figure 5. Generating an activation number from username
A Sample Client Application
Before diving into the details of the client, let’s see how it looks and behaves. Figure 6 shows the sample client in which activation protection scheme is incorporated.

Figure 6. The sample client application s Activate Help menu
When you click the Activate menu item, the dialog box shown in Figure 7 appears. You can click the link to make your web browser navigate to the activation server (which is at: http://localhost/LicenseServer_v1/License.aspx ), where you can get your own activation number. Then you simply enter the data into the client Activation Form and click Activate to see the dialog box shown in Figure 8. Be careful, however. If you enter the wrong activation number, the dialog box shown in Figure 9 will be displayed.

Figure 7. Entering activation information into the dialog

Figure 8. The dialog box displayed when the correct activation information is entered

Figure 9. The dialog box displayed when incorrect activation information is entered
The sample application has an About dialog box used to display activation information. Figure 10 shows it before activating, and Figure 11 shows it after activation.

Figure 10. About dialog box before activating

Figure 11. About dialog box after activation
Now let’s take a look at the important parts of the client code (the code is from the ActivationForm.cs file inthe Client_v1 project):
private void btnActivate_Click(object sender, System.EventArgs e)
{ StringBuilder sb= new StringBuilder(); String s= txtName.Text; if(s.Length==0) return; //make string length even if(s.Length % 2==1) s+=‘X’; //transposing odd and even bytes, //while converting each char to ASCII (hex) for(int i=0; i< s.Length; i+=2) { sb.Append(((byte)s[i+1]).ToString("X")); sb.Append(((byte)s[i]).ToString("X")); } s= sb.ToString(); //applying substitution s= s.Replace(‘0’,’-’);
if(txtActNo.Text==s) doRegistrationProcess(); else MessageBox.Show("Wrong! Try again.", "Activation Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
I intentionally used the wrong client-side method. The mistake here is that the client and server methods are almost the same! This is one of the worst things a programmer can do! As I noted previously, a cracker can always reverse engineer the client and rip the algorithm into a key generator, but he can’t normally do this on the server.
So, never use the same algorithm on both sides. The algorithm should be invertible, and the client should use the inverse algorithm of the one the server used. Figure 12 shows this concept. The user first enters their name as an input for the activation-number-generator algorithm. This algorithm, symbolically denoted by function f () (Note that it is not mandatory, and usually not applicable to use a function to generate activation numbers. Technically speaking, most of these algorithms are many-to-one relationships.), is executed on the server and returns the activation number. The user then obtains this number and enters it into the client. The client then should use an inverse function (better to say an inverse algorithm), f-1() , to see if the entered activation number matches the user name. Math savvies may ask, if it’s a many-to-one relationship (and not a function), how can it be invertible? The answer is subtle. The output of f-1() is a pattern, not the exact user name. If this pattern matches the user name, the activation process will succeed. Otherwise, it fails and the user is informed.
Here are a few examples to clarify this (s is a string):
- f(s)=0xF5689 is not invertible, because it has a fixed output which does not provide a meaningful pattern. As a non-trivial example, I can name hash functions ;
- f(s)={transpose odd and even character positions of s} is a function (one-to-one relationship) and thus invertible;
- f(s)={substitute every occurrence of ~x’ with ~-’ in s } is not a function, but it provides a pattern and fits into the invertible class of algorithms.
The algorithm used in the preceding code falls into the third category (not a function, but invertible). So the client code can be corrected to use the inverse algorithm. But, because the code is very simple, it’s not even worth the try. I’ll give you a much better code in Encryption and Hashing section of this article. Also notice that this demo suffers from the "activation by phone" drawback noted previously.

Figure 12. The correct way of validation on the client side
Let’s take a look at another part of the client. You probably noted a function called doRegistrationProcess() in the preceding code. This function registers the activation information on the client computer. Why? Because you don’t want your users to have to register the product every time they launch it. In my opinion, this is the most challenging part of any protection scheme, where to store the registration information? Some developers put it on a hardware lock (dongle), some write it on special tracks of CD/DVD-ROM, and some save it on the hard drive of the computer (including the Windows Registry). Any of these methods can be used, but whichever one you pick, this information is inevitably stored locally, which unfortunately leaves the door open for the crackers to simulate activation by putting the same data where the activation process stores it. That’s why I called it challenging, I have some ideas about fighting this limitation that are discussed later in the article. Let’s take a look at the code in doRegistrationProcess() which uses the simplest way and stores this information unencrypted, and in the Windows Registry.
private void doRegistrationProcess()
{ MessageBox.Show("Thank you! The product is now fully activated.", "Successful Activation", MessageBoxButtons.OK, MessageBoxIcon.Information); this.Close(); //create a registry key to save activation info RegistryKey regkey= Registry.LocalMachine.CreateSubKey("SoftwareOur Software"); regkey.SetValue("Username", txtName.Text); regkey.SetValue("Activation Number", txtActNo.Text); } <p></pre><!--@END —>
The About dialog box uses the same Registry data to detect if the product is activated:
private void AboutForm_Load(object sender, EventArgs e)
{ //read registration info from Registry try { RegistryKey regkey= Registry.LocalMachine.OpenSubKey("SoftwareOur Software"); lblUsername.Text= regkey.GetValue("Username").ToString(); lblActNo.Text= regkey.GetValue("Activation Number").ToString(); }catch(Exception) { //do nothing. The software is supposedly not activated. } } <p></pre><!--@END —>
Note the use of a try/catch block to ensure the existence of a special subkey in the Registry.
Further Improvements
The first example built above is of very little use in the real world. It was used to show you how the basic scheme works, but there’s a lot of improvement that needs to be added to make it a real-world protection scheme. As you are professional ASP programmers, I’m sure the following explanation will be enough for you to change the code to suit your needs.
Using a Back-End Database on the Server
One of the most unrealistic aspects of the first example was its lack of a database. You need a database to distinguish legitimate users from false users. This database should log all activation attempts. It depends on you and your method of activation (per-user or per-computer) which information should exist in the database, but typical examples include some of:
- User name (Forename, Surname, and Middle name)
- User address
- Company name
- (Part of) Credit Card Number
- Number of licenses purchased
- Date of purchase
- License expiration date
- Serial number (used during setup)
- Hardware configuration (Including Display Adapter, SCSI Adapter, IDE Adapter, NIC type and its MAC address, RAM Amount, Processor Type, Processor Serial Number, Hard Drive Device, Hard Drive Volume Serial Number, and CD-ROM / CD-RW / DVD-ROM Drive Model)
- IP address of the computer trying to activate
Note that not all the items in this list should be entered manually. The client software can programmatically collect hardware configuration information and upload it to the server. Also, note that this information might be considered private for some individuals, so to avoid legal issues, do yourself a favor and mention whatever the client will upload to the server in your EULA.
Keep in mind that crackers may also try to attack your database through various methods such as a SQL injection (or SQL piggybacking) . More information on this and other techniques can be found in the links section. You can minimize this type of attack by following best practices and using parameterized stored procedures.
Integrating Activation into the Client Using Web Services
As I mentioned previously, it’s not a good idea to prompt the user for an activation number. It’s better to ask the user for information, and then verify against an activation server, if the user is authenticated, the server sends some signal back to the client and the client stores the details somewhere that the product is activated. The process is totally transparent to the user, and no activation number is provided. The client only maintains state, which is either activated or not. A good method to do this is to use a web service. They provide the means of automating a client application to communicate with the server and free the user from having to do the job manually.
Using a non-Default Port
Every step that makes the life harder for a cracker is a bargaining chip, even if that step is very simple. Most web servers listen on port 80. You can change this to a non-default port in your IIS configuration. (This can be done for each website you create in IIS). This step should be accomplished after you have integrated the activation into the client. This will stop some lower skilled crackers but a skilled cracker can detect what port is being used with a basic packet sniffer.
Encryption and Hashing
Encryption algorithms are divided into private (symmetric) key encryption and public (asymmetric) key encryption algorithms.
Private-key encryption algorithms are composed of two basic transformations: Substitution, and Transposition. In a substitution transform each symbol or group of symbols is replaced by another symbol or group of symbols. Transposition transform, in contrast, reorders the symbols but does not disguise them. A typical symmetric encryption algorithm applies these two types of transformation iteratively in order to make it harder for a cracker to obtain the relevent data, eg. the serial number, from the encrypted message. There are many private-key encryption algorithms: DES, 3DES, and AES are popular ones. The drawback of using private-key encryption is that you have to incorporate the secret (private) key into the client.
Public-key encryption encompasses a very useful class of algorithms. Interestingly, you can give a cracker your client software code that checks the validity of the activation number and if the keys used are large enough, they still won’t be able to create a key generator for your software! That’s because computing the activation-generator key (private key) from the activation-checker key (public key) is not possible (within a reasonable amount of time). Of course, the cracker could still patch the client code, but that’s harder than just reverse engineering it. There are a number of public-key encryption algorithms – RSA and ElGamal are common ones.
A special type of encryption is called hashing . Hash algorithms are almost always used to provide a fixed-length output (a.k.a Message Digest ), and they are not invertible, meaning that you can’t find an algorithm which takes a Message Digest (MD) and gives the message. Because of this, they are also known as one-way hashing. Another feature of hashing algorithms is that they do not provide unique output, i.e. there can be found two inputs which give the same output.
As I noted previously, it’s best to use inverse algorithms in client code to make it more difficult to crack. So, you can’t use hashes as your encryption algorithm because they cannot be decrypted. But hashes may be used to provide a pattern. The following code, from the file License.aspx.cs , in the LicenseServer_v2 project, shows this in action. Note that this code uses a class BigInteger, which handles large integers, and which is supplied by Chew Keong Tan on CodeProject, at http://www.codeproject.com/csharp/biginteger.asp. I’ve slightly modified the class to make it suitable for this article, and the modified version is available with the download for this article – or you can see the original class along with Chew Keong Tan’s article explaining the class at the URL just given.
You might want to either skim through the code or, if you want to look at it in detail, read a good cryptography reference, because it’s math intensive and there isn’t space in this article to go into the math in detail. A good (and free!) reference is " Handbook of Applied Cryptography " available in the Related Links section. Chapter 2 provides the mathematical background, chapter 8 discusses the "public-key encryption" and chapter 9 describes the "hash algorithms". The code uses RSA and MD5
private void Page_Load(object sender, EventArgs eventArgs)
{ if(IsPostBack) { String str= txtName.Text; if(str.Length==0) return; // Hashing the input string into a 128-bit message, m MD5 md5 = new MD5CryptoServiceProvider(); byte[] rawBytes = ASCIIEncoding.ASCII.GetBytes( str ); byte[] hashData = md5.ComputeHash( rawBytes ); BigInteger m = new BigInteger(hashData); // Adding some randomness Random r= new Random((int) DateTime.Now.Ticks); m= (m & new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFF0000" ,16)) + new BigInteger(r.Next(65535)); // To understand RSA Algorithm, it’s highly recommended to obtain // a good cryptography book, and study it carefully. "Handbook of // Applied Cryptography" is a free book you can download from // http://www.cacr.math.uwaterloo.ca/hac // Chapter 8 describes RSA. // p and q are 96-bit primes // p= 59643976065507859597668572603 // q= 62003406621903890192692205963 // n= p.q BigInteger n = new BigInteger( "3698129700536787156524403190375288912342364576629495031689", 10); // phi= (p-1).(q-1) // The following command could be used to generate phi // BigInteger phi = new BigInteger( // "3698129700536787156524403190253641529654952826839134253124", 10); // private exponent, d // d should have two properties: // 1 < d < phi, and // GCD = 1 // Only activation number checker requires d // BigInteger d = new BigInteger( // "682177846516523109736125121888176871427969701470860838473", 10); // public exponent, e // e should have two properties: // 1 < e < phi, and // e.d = 1 (mod phi) // The following command could be used to generate e // BigInteger e = d.modInverse(phi); // Only activation number generator requires e BigInteger e = new BigInteger( "1273767639057494911224755028484082710578337717510160766193", 10); //c= (m ^ e) mod n BigInteger c = m.modPow(e, n); // add sum dashes (’-’) to beautify the generated number actNo.InnerText= FormatNumber(c.ToHexString()); }
}
FormatNumber() is used to make the number more human readable (by adding dashes to it). Here’s the code for this function (from the same file):
// FormatNumber splits a number into 8-digit groups.
// Groups are separated with ‘-’.
private String FormatNumber(String s)
{ StringBuilder sb = new StringBuilder(); for(int i=0; i< s.Length; i+=8) { if(i >= s.Length – 8) { sb.Append(s.Substring(i, s.Length – i)); break; } sb.Append(s.Substring(i, 8)); sb.Append(’-’); } return sb.ToString();
}
Before diving into the code, it’s necessary to discuss some points:
- This code is taken from a real-world application. I have changed the numbers, and improved it (added better hashing and randomness). So, you can be sure that you’ll end up with "real" protection.
- Almost all common encryption/decryption techniques are provided in the code.
- The code uses the MD5 algorithm to hash the input string, and RSA public-key algorithm to encrypt and decrypt the hashed string. If you want to have your own RSA keys, I highly recommend you to download RSA-Tool 2 found in the Related Links section.
The client uses RSA to decrypt and test the activation number entered. Note that in presenting this I removed those comments that are common between client and server, to make the code shorter .this code is from the file ActivationForm.cs in the Client_v2 project,
private void btnActivate_Click(object sender, EventArgs eventArgs)
{ String str= txtName.Text; if(str.Length==0) return; // Hashing the input string into a 128-bit message, m MD5 md5 = new MD5CryptoServiceProvider(); byte[] rawBytes = ASCIIEncoding.ASCII.GetBytes( str ); byte[] hashData = md5.ComputeHash( rawBytes ); BigInteger m = new BigInteger(hashData); //remove rightmost 16 bits to provide the pattern m = m >> 16; //removing dashes (’-’) from Activation Number String strActNo= String.Concat(txtActNo.Text.Split(’-’)); try { BigInteger actNo= new BigInteger(strActNo, 16); BigInteger n = new BigInteger( "3698129700536787156524403190375288912342364576629495031689",10); BigInteger d = new BigInteger( "682177846516523109736125121888176871427969701470860838473", 10); BigInteger b = actNo.modPow(d, n) ; b >>= 16; if(b==m) doRegistrationProcess(); else throw(new Exception()); } catch(Exception) { MessageBox.Show("Wrong! Try again.", "Activation Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; }
}
Securing the Connection Using SSL and IPSec
Up to now, I didn’t talk much about network security. There are at least two issues related to this topic: integrity , and confidentiality . Integrity refers to keeping a message intact, while confidentiality refers to keeping it secret. You should use SSL (Secure Socket Layer), also known as TLS (Transport Layer Security) to encrypt messages in the transport layer of the TCP/IP protocol stack, so it can be useful to keep confidentiality and integrity of messages. This is necessary when the client wants to contact with the activation server over the Internet, or vice versa. There are several good articles on the ASPToday site about how to use SSL with ASP.NET, I have provided a list in the Related Links for this article.
IPSec (Internet Protocol Security), on the other hand, has to do with protecting data between different servers. If you use different servers as a web server, application server, and a database server you can secure the connection between them using IPSec.
Always-on Applications
Some programs are designed to work online. These programs can be made so as they check the state of activation on a regular basis. By checking the validity of the software periodically or at each web update you can revoke the license at any time if need be. One other benefit is that you don’t have to put activation information locally!
Protecting the Client Source Code
When you compile a .NET program, the compiled code is stored in an .exe file in the form of Microsoft Intermediate Language (MSIL, pronounced like "missile"). MSIL can be decompiled easily (there are commercial and non-commercial MSIL decompilers on the web), and your code will be exposed to the world (which can be patched easily!). To avoid this, use a code obfuscator – this will make the source code much more difficult to patch. One of them, called Dotfuscator Community Edition , is installed by default when you install Visual Studio 2003.
Third-Party Products
I have provided several links to popular third-party products in the links section that you can review – you can use these to incorporate activation into your software. Sometimes it is easier or cheaper to purchase a product, it really depends on the environment you work in.
Conclusion
In this article, you’ve learned what a protection scheme is and how to implement one for yourself. You were also introduced to many real-world aspects of implementing activation, from securing client code to network and database security. You will now be able to add a complete ASP.NET activation server and its client to your application. Whether you implement it yourself or buy a third-party product, you have an in-depth knowledge of what should be expected from a protection scheme. I advise you to track cracking sites to see if/when a crack is released for your product. You will need to update your software and its protection scheme at that point in order to motivate people to purchase the new version and forget the cracked one.

