Please note that it’s still a work in progress then many things need to be completed (see issues) and code must be reviewed and simplified. All documentation is still a TO DO, please refer to both source code and cited SO post. Any help on this (also for documentation) is more than welcome!
.NET Licenser is Registry-based licensing management tool. It implements a licensing system that checks for the availability of a specific Registry key that contains a corresponding value. Your licensed application itself implements no code to write the Registry value but .NET Licenser inserts into your application subroutines that will do that. Registry keys will be set up by the installation/registration licensed application, and since most applications use the Registry anyway, this does not pose a significant development limitation.Licenser is helpful for licensing applications written in any language and designed under Microsoft .NET Framework (C#, VB.NET etc). It supports .NET Frameworks 1.0, 1.1, 2.0, 3.0, 3.5, 4.0, and 4.5.In the Application Title box, enter the title of your .NET application you want to be displayed in the licensing window’s title bar and in messages presented on the licensing windows.
In the Purchase Link box you have to insert an internet link where your customer can make on-line order of your application. The link will be presented on the licensing windows.
You can choose between 2 different ways when your application?s trial evaluation will be finished. You may specify an amount of days for the evaluation (30 days by default). Also you can select an exact date in the calendar when the licensing will start.
You can manage Registry entries of the licensing system. Encrypted installation date will be stored in Registry during your protected software first run. You can specify Registry Path where the date coded value is stored by calling Registry tree interface. The Path exists on your PC and you are not sure if it will be presented on your customer?s PC. The Path you specified will be created in end-user?s Registry at your application activation time.
The same path will be composed at customer PC.
Enter name of Registry entry for the installation date value in the Sub Key Name box.
Registration ID number will be stored in Registry during your protected software registration/activation. You can specify Registry Path where the Registration ID number coded value is stored by calling Registry tree interface.
Enter name of Registry entry for the Registration ID value in the Sub Key Name box..NET Licenser allows you to generate a secure cryptographically encrypted license key after your application has been registered/purchased on-line. Then you can provide customer with the Registration ID key by sending e-mail.
The most important part of the Registration ID interface is the ‘Password for Registration ID number cryptographic encryption’ box. Please insert some password that will be kept. It is important to do NOT change the password for your application. The password gives you ability to generate unique Registration ID. Other Licenser users will not be able to create right Registration ID for your application without the Password. You are licensing your application with some password and put software on the web for downloads. If you change the password you will not be able to generate correct RegID since your application is distributed with the first one.
Put your registered user name into User Name box and then push ?Generate Registration ID? button. You may edit e-mail message that you are going to send to your registered customer.When your software evaluation period expires it will show the ?Evaluation stopped? form and will offer your potential customer to visit on-line purchase registration order page. You can adjust the form message. You can use [ApplicationName] keyword instead of writing down your software exact name. The keyword will be replaced with your application title on the form message..NET Licenser works by providing secure cryptographically encrypted license keys. This assures an easy way to activate .NET application from demo/evaluation to fully functional version. .NET Licenser uses a cryptographic encryption to generate and verify license keys..NET Licenser is a functional software tool for complete license and customer management. Along with Skater .NET Obfuscator it helps you to prepare your product for protection, manage license, encrypt your code and data, send e-mails to registered customers and so on.
WHAT’S NEW IN VERSION 1.0
Client: the machine where application you want to protect is deployed.
Server: the machine where you create licenses. It may be a public accessible web server or simply your development machine but your customers must not have direct access to its content.
Contact: it’s a text string generated at client side which contains some unique identifiers used to uniquely tie one license to a specific machine.
License: it’s a text string generated at server side and used client side which contains information about the license (to whom you licensed your application, its expiration and which features are enabled). License is generated from a contact and it’s indissolubly tied to a specific machine.
How to Use It
This project cannot be used as-is, to be effective you must include full source code in your repository and change it as described here, read carefully these notes. Project is separated in groups:
- Read about Code Obfuscation.
- Code that must deployed together with your application stays in. This assembly also contains code used by server components.
- Code that must be only on your private server (if you wish to have a private license server) stays in
Radev Licensing Server. Your customers must never have an accessible copy of this assembly because it contains your private key.
- Code that must be directly included in your application, possibly in each single assembly you will check for license (for example if you have a modular architecture, where one assembly implements a set of features, you should include one copy of this file in each assembly). A generic template is
LicenseManagerbut it must be customized for your specific use.
To start using this project you have to carefully follow these steps:
- Create a new public/private key pair and save it as XML. Copy public key in
Radev Licensing\Keysand both public and private keys in
- Include a copy of
LicenseManagerin each assembly where you need to check for the license together with a reference to
Featureenum to include all features you want to protect with license. You may simply omit this file (and relative code in
LicenseManager) if you just need to know if there is a license but you don’t protect single features.
- Create an utility (or something automatic, if you have a public licensing web server) to generate a contact:
If you need plain text (for example to send an e-mail) you can use
- Create an utility (or something automatic, if you have a public licensing web server) to generate a license from a contact file:
- When you need to check for license (or for a specific feature) simply call
If in doubt about where you license file should be you may read Where to Save License File.
Please note you can assign a validity interval for your license (I strongly suggest to always make it valid from the day it has been created) and also specify which version (again a range) of your software is enabled by that license.
How It Works
To have an adequate protection few assumptions must be satisfied:
- You want individually license each copy of your software and tie a license to the exact machine to which it has been associated: licenses cannot be copied and reused between different machines.
- Licese file may be hidden but its strength does not come from that nor from obfuscation: even if it is accessible and modifiable your application must have a mechanism to realibly validate it.
- Code that check for the license is reasonably protected and it is not easy to patch it to circumvent the license.
One License for Each Client
First of all we need to uniquely identify a specific machine. There are various IDs and settings we may use but we must combine more than one of them because hardware configuration may change and we do not want to invalidate our license for each small change.
I decided to use WMI queries to read configuration values, because they’re easy to use and to change, and by default (but it can be changed in
Licensing\Token) I read only IDs, because they’re less subject to change compared to – for example – memory size. Note that this choice is not mandatory and you may want to change it implementing your own
Licensing\Client\HardwareAnalyzerclass and changing
Application will compare hardware configuration stored in its license with current live configuration and if they differ more than a specified amount then it will consider license as invalid. For details check
License.MaximumNumberOfHardwareChanges. Currently license will check these values:
- Computer manufacturer and model. These values should not ever change over time, unless you also change motherboard, but they’re not widely available and they may contain dummy text.
- Motherboard manufacturer, model and serial number. These values should not change over time but sometimes (especially on old systems) serial number is fake.
- BIOS serial number. Also this value may be a fake on very old motherboards.
- CPU ID. This value is not a true unique ID of your CPU but it model and stepping, combined with other IDs, will help you to uniquely identify a specific system.
- OS serial number and installation date. Here you rely on Operating System license protection… if they use your application on two different machines then you assume they also need to use two different OS copies (unless they also want to crack OS). Installation date (absolutely optional) lets you detect false claims like I had to reinstall OS because of broken hard disk.
Note that I didn’t use any disk serial number (hard to reliably read) nor MAC addresses (NICs may be turned on and off at run-time).
Note that you may use motherboard and computer manufacturer name to detect virtual machines (Microsoft, Oracle, VMWare and similar). It’s not a reliable method but it has the advantage to be extremly simple. For a more reliable check you have to individually check for virtual machines you know, for more details check Wiki page about Virtual Machines.
Secure License File
After we collected all required information into a contact then we encrypt that data with our public key and then encode it as base64 (to make it easy to transfer, for example, via e-mail). Note that here encryption isn’t strictly necessary (because everything a cracker needs is available and visible in application code).
Server code will then decode and decrypt contact information, fill license as required and then sign result with our private key. Everything is then encoded again as base64. From this moment our application can detect any change to license content because signature (verified with public key) won’t match.
Protect Application Assemblies
Of course you also need to protect application assemblies otherwise they may be tampered. This topic is vast (especially because a cracker has a big surface attack) but you should at least start signing all your assemblies and then – eventually – embed
Radev Licensing into your application assembly as a resource (to make things slightly more complicate for casual crackers), you will load it inside
AppDomain CurrentDomain Assembly Resolve event handler.
There are more things to consider:
- If application can load untrusted/unsigned plugins then cracker may simply use Reflection to bypass/modify already validated in-memory license data.
- Code may be patched at run-time bypassing license checks (the (in)famous NOP instead of CALL).
- WMI information may be faked.
- An entire system may be cloned using virtual machines.
- Application may be shared using Web Access, Terminal Server or similar technology.
The LicenseManager class provides the following static properties: CurrentContext and UsageMode. The class also provides the following static methods: CreateWithContext, IsValid, and Validate.
When you create a component that you want to license, you must do the following:
- Specify the LicenseProvider by marking the component with a LicenseProviderAttribute.
- Call Validate or IsValid in the constructor of the component. Validate throws a LicenseException when it tries to create an instance without a valid license. IsValid does not throw an exception.
- Call Dispose on any license that is granted when the component is disposed or finalized.