Introduction
In the earlier version of this article, I did not provide the source code for implementing the said strategy. I am going to update this article with the required source code lines and hope this will explain my concepts more clearly. Readers who have already been through the earlier version of this article can jump directly to the updated part under header “To accomplish our target, take the following 2 steps:”
A well organized IT company has their strategy makers for controlling software piracy and crack issues, but for beginner and individual developers it is really a painful issue.
Application demo is used for the purpose of publicity and usually a registration option provided with it for upgradation to full version. The registration is accomplished after providing a license-key by customer against an auto-generated license code.
This is the weakest point where if the license-key got cracked, the demo-version can easily be converted to full-version and control of developer’s harvest slips into another’s hands.
Approaches Used to Control Piracy
- Attaching a dongle (hardware) to software
- Provide a license key for registration against license code
In general, license key option is used for this purpose. So the issue is to make an attempt at piracy control at demo-version level and the strategy is to completely isolate demo from the full-version of application.
There are many points which are taken under consideration while making demo-version for an application. Let's take a snapshot of them:
- A finite-days expiration period is provided for the demo. If customer doesn’t register within this period, the demo expires.
- Instead of complete application, only partial features of application are kept in action. Only after registration, the customer can avail the full features of application.
- For registration, a license key has to be provided by the customer against auto-generated license code.
So, the application registration is the point where maximum crack risk resides.
To overcome this situation, the following strategies may be adopted:
- Demo means demo, no provision to upgrade to full version to be provided.
- Out of full version, an isolated portion of demo to be ripped-off with only partial features with finite expiration period.
- An additional feature has to be added, i.e., finite number of re-installations of demo version on each system and each installation with finite days expiration. After completion of finite installations, the demo should not be re-installed unless and until system gets formatted.
For achieving the third point, a separate console application can be used to create a file that holds installation date and installations counter value.
The installation counter shall be incremented by +1
for each time demo gets re-installed and installation date should remain fixed to be used for demo expiration calculation.
Deceiving Crackers
We should attempt to use multiple strategies for keeping the above file contents out of reach of malicious minds. Some suggestions are as follows:
- Installation date and installation counter may be kept in separate files.
- Multiple special folders, SystemRoot and Registry can be used to keep these files/contents separately.
For example special folder “ApplicationData” path can be obtained by:
String appDataPath = Environment.GetFolderPath
( Environment.SpecialFolder.ApplicationData)
And SystemRoot path can be obtained by:
String SysRtPath = Environment.GetEnvironmentVariable("SystemRoot");
- Always store installation date in random format while storing to file which shall be recompiled to proper format whenever our code needs it. Garbage data may also be included with date for creating confusion.
- An encryption strategy can be adopted for data protection.
To accomplish our target, take the following two steps:
Step 1
A console application can be used to create files for holding installation date and re-installation counter information. This console application shall be attached to demo’s setup as primary output and to be executed at the time of installation on client machine to store this information of client system.
For example, if we want to execute this file on clicking Register button while installation, set said console application’s primary output in executable property of Register user dialog of User interface editor in setup.
Note that the below source code uses SystemRoot folder and Registry to store our potential data files. Though the help provided with the source code is self explanatory, yet the main functionality of the source code is as below:
- An install counter with limited installations information in “SystemRoot” folder along with controlling number of installations limit.
- Updating installation date for each incremental installation.
- Information to be stored in a “Registry subkey”.
- Some garbage information also inserted for confusing the crackers which can be edited by programmers as required.
Source Code Sample
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Win32;
using System.IO;
namespace Demdthlp
{
class Program
{
RegistryKey rk, rgsk;
int d, m, y;
string revdt, Dtfor_SysRt;
string syrtdtflpth;
Program()
{
syrtdtflpth = Environment.GetEnvironmentVariable("SystemRoot");
d = 0; m = 0; y = 0; revdt = "MPAD";
}
private void md_instdt()
{
string dd_num = "0";
string mm_num = "0";
DateTime dt = DateTime.Now;
d = dt.Day;
m = dt.Month;
y = dt.Year;
if (d < 10)
dd_num += d.ToString().Trim();
else
dd_num = d.ToString().Trim();
if (m < 10)
mm_num += m.ToString().Trim();
else
mm_num = m.ToString().Trim();
string strdt = dd_num + mm_num + Convert.ToString(y).Trim();
Dtfor_SysRt = strdt;
for (int i = 0; i < 8; i++)
revdt += strdt.Substring(7 - i, 1);
revdt += "NORKREV1602";
}
private void ed_rgy()
{
rk = Registry.CurrentUser;
rk.DeleteSubKey("Software\\abcDem", false);
rgsk = rk.OpenSubKey("Software", true);
try
{
RegistryKey newrk = rgsk.CreateSubKey("abcDem");
newrk.SetValue("adem", revdt.ToString().Trim(), RegistryValueKind.String);
}
catch (Exception s)
{
Console.WriteLine(s.Message);
}
}
private void ed_sysrt()
{
syrtdtflpth += "\\demdt.dtd";
if (File.Exists(syrtdtflpth))
{
string insCounter = RetuInstalCounter(syrtdtflpth);
int ncount = int.Parse(insCounter);
if (ncount >= 5)
{
Console.WriteLine("Sorry, Your Demo Trials Limit is Over.");
Console.ReadLine();
return;
}
else
{
ncount++; string strcount = "";
strcount = ncount.ToString().Trim();
Dtfor_SysRt += strcount;
try { File.Delete(syrtdtflpth); }
catch { }
StreamWriter fsInstDtFile =
new StreamWriter(new FileStream(syrtdtflpth,
FileMode.Create,
FileAccess.Write));
fsInstDtFile.Write(Dtfor_SysRt);
fsInstDtFile.Close();
}
}
else
{
Dtfor_SysRt += "1";
StreamWriter fsInstDtFile =
new StreamWriter(
new FileStream
(syrtdtflpth,
FileMode.Create,
FileAccess.Write));
fsInstDtFile.Write(Dtfor_SysRt);
fsInstDtFile.Close();
}
}
private string RetuInstalCounter(string syrtdtflpth)
{
StreamReader fsInstDtFile =
new StreamReader(new FileStream(syrtdtflpth,
FileMode.Open,
FileAccess.Read));
string instdtAndCounter = fsInstDtFile.ReadToEnd();
fsInstDtFile.Close();
string inscount = instdtAndCounter.Substring(8, 1);
return inscount;
}
static void Main(string[] args)
{
Program p = new Program();
p.md_instdt();
p.ed_rgy();
p.ed_sysrt();
}
}
}
Step 2
A special verification code that has to be executed very first should be attached to our main executable file of application. After demo-version installation, every time application runs, this code verifies the expiration date.
The source code below first reads information stored from file stored in SystemRoot folder and completes the following steps:
- Verifies system date and calculates lapsed days
- Evaluates the expiration
Source Code Sample
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using Microsoft.Win32;
using System.Globalization;
namespace Terminator
{
public partial class MainForm : Form
{
string SysRtDtFilePath;
public MainForm()
{
InitializeComponent();
SysRtDtFilePath = Environment.GetEnvironmentVariable("SystemRoot");
}
private void MainForm_Load(object sender, EventArgs e)
{
SysRtDtFilePath += "\\demdt.dtd";
if (File.Exists(SysRtDtFilePath))
{
try
{
StreamReader fsInstDtFile =
new StreamReader(new FileStream(SysRtDtFilePath,
FileMode.Open,
FileAccess.Read));
string instdt = fsInstDtFile.ReadToEnd();
if (String.IsNullOrEmpty(instdt) == false)
doEvaluation(instdt);
fsInstDtFile.Close();
}
catch
{
MessageBox.Show("File Read or system date format error", "Information",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
MessageBox.Show("Either evaluation period expired or file manually corrupted.",
"Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
private void doEvaluation(string insdt)
{
string rightdt = insdt.Trim();
string dy = rightdt.Substring(0, 2);
string mon = rightdt.Substring(2, 2);
string yr = rightdt.Substring(4, 4);
string mdt = dy + "/" + mon + "/" + yr;
DateTime curdt = DateTime.Today;
IFormatProvider culture = new CultureInfo("fr-FR", true);
DateTime Finstdt =
DateTime.Parse(mdt, culture, DateTimeStyles.NoCurrentDateDefault);
if (curdt < Finstdt)
{
label4.Text = "Invalid System date";
MessageBox.Show("Invalid System date", "Information",
MessageBoxButtons.OK, MessageBoxIcon.Information);
Application.Exit();
}
DateTime maxdt = Finstdt.AddDays(2);
TimeSpan diffs = maxdt - curdt;
int d = diffs.Days;
if (d < 0)
{
label4.Text = "nil";
MessageBox.Show("Your evaluation period has been expired
or not Activated." + "\n" +
"This trial version is only for Demo purposes.
To freely use Data Theft controller (Demo) software" + "\n" +
"created by ABC Technologies,
you need to purchase this Software from ABC Technologies.");
Application.Exit();
}
else
{
label4.Text = d.ToString().Trim() + " days left";
btnStart.Visible = true;
}
}
private void btnStart_Click(object sender, EventArgs e)
{
Form fm = new Form1();
this.Hide();
fm.ShowDialog(this);
}
private void btnCancel_Click(object sender, EventArgs e)
{
this.Close();
}
}
}
Now add the following lines of code to Program.cs file of our main application:
namespace Terminator
{
static class Program
{
public static string strPwdFilePath =
Environment.GetEnvironmentVariable("SystemRoot");
public static bool isPwdEnabled = false;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
Summary
Once again, I want to repeat that this article provides just basic knowledge to beginners for protecting their application. Strategies can be more complicated and competitive at their level.