Protecting your code with CliSecure
Writing clean code that is easy to maintain, easy to read and understand by your team members (and yourself) is probably one of the most important skills a developer should master.
Clean code is important for so many reasons, but some might argue clean code, (especially in the case of .NET where your code is compiled to MSIL), makes it much harder to protect your code and intellectual property.
Some teams I’ve worked with over the last few years solve this problem by writing the most unreadable and dirty code imaginable, because they figure, if they can’t read it, nobody can. Even though this has (sadly) proven most effective, it’s the worst thing you could possibly do.
A far better solution is to keep the source code clean and make it ‘unreadable’ after it has been compiled. It’s a technique known as ‘code obfuscation’ and I’ve just found the perfect tool for the job.
CliSecure .NET Obfuscator from Secureteam makes it very easy to protect your code and intellectual property with minimal impact on your development and deployment cycle. It offers various methods of code protection and comes with an easy to use user interface, command line tool and an SDK .
Before we get into CliSecure, let’s see why we need it in the first place.
Why do you need to obfuscate your code?
Let’s consider the following (completely fictional) application:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void SayHelloButton_Click(object sender, RoutedEventArgs e)
{
var name = txtName.Text;
if (!String.IsNullOrEmpty(name))
{
SayHello(name);
}
else
{
SayNoInput();
}
}
private void ReverseButton_Click(object sender, RoutedEventArgs e)
{
var name = txtName.Text;
var length = name.Length;
if (length > 0)
{
var builder = new StringBuilder();
for (int i = length - 1; i >= 0; i--)
{
builder.Append(name[i]);
}
txtName.Text = builder.ToString();
}
else
{
SayNoInput();
}
}
private void SayHello(string name)
{
MessageBox.Show(String.Format("Hello {0}", name));
}
private void SayNoInput()
{
MessageBox.Show("You did not specify a name");
}
}
Probably the most common way to ‘disassemble’ the assembly that was generated from this code would be to use IL DASM which comes as part of the .NET Framework SDK, but I’m no MSIL expert (and chances are that those who want to steal your code aren’t either), so I’ll use .NET Reflector instead.
This tool allows you to convert MSIL back to VB.NET or C# code.
The output generated by .NET Reflector is quite verbose, I’ll just show the relevant parts.
The generated code for the ReverseButton Clicked event handler looks like this:
private void ReverseButton_Click(object sender, RoutedEventArgs e)
{
string name = this.txtName.Text;
int length = name.Length;
if (length > 0)
{
StringBuilder builder = new StringBuilder();
for (int i = length - 1; i >= 0; i--)
{
builder.Append(name[i]);
}
this.txtName.Text = builder.ToString();
}
else
{
this.SayNoInput();
}
}
Notice how identical it looks to the original code? In fact, the only change is that all instances of the var keyword has been replaced with the actual types.
The same is true for the other methods:
private void SayHello(string name)
{
MessageBox.Show(string.Format("Hello {0}", name));
}
private void SayHelloButton_Click(object sender, RoutedEventArgs e)
{
string name = this.txtName.Text;
if (!string.IsNullOrEmpty(name))
{
this.SayHello(name);
}
else
{
this.SayNoInput();
}
}
private void SayNoInput()
{
MessageBox.Show("You did not specify a name");
}
As you can see the compile process did nothing to protect your code in any way, and this is where CliSecure comes into play.
CliSecure
When you launch the CliSecure UI, you’ll see a number of tab items, each presenting different methods to protect your code.

The input tab allows you to specify which assemblies you want to protect. In this case I’ll add the assembly which resulted from the sample application above by clicking the ‘Add’ link.

On the ‘Code Protection’ tab I then select the assembly to indicate I want to apply this feature to the assembly and simply press ‘Build’ to generate the protected assembly version.
When you disassemble the protected assembly with .NET Reflector, all you’ll get is this:
[GeneratedCode("PresentationBuildTasks", "4.0.0.0")]
public class MainWindow : Window, IComponentConnector
{
// Fields
private bool _contentLoaded;
internal TextBox txtName;
// Methods
[MethodImpl(MethodImplOptions.NoInlining)]
static MainWindow()
{
<CliSecureRT>.Initialize();
<CliSecureRT>.PostInitialize();
}
[MethodImpl(MethodImplOptions.NoInlining), DebuggerNonUserCode]
public void InitializeComponent()
{
}
[MethodImpl(MethodImplOptions.NoInlining)]
private void ReverseButton_Click(object sender, RoutedEventArgs e)
{
}
[MethodImpl(MethodImplOptions.NoInlining)]
private void SayHello(string name)
{
}
[MethodImpl(MethodImplOptions.NoInlining)]
private void SayHelloButton_Click(object sender, RoutedEventArgs e)
{
}
[MethodImpl(MethodImplOptions.NoInlining)]
private void SayNoInput()
{
}
[MethodImpl(MethodImplOptions.NoInlining), DebuggerNonUserCode,
EditorBrowsable(EditorBrowsableState.Never)]
void IComponentConnector.Connect(int connectionId, object target)
{
}
}
As you can see, the implementations of the methods are no longer visible, but rest assured, the application works just like it did before!
The ‘Control Flow’ tab allows you to hide flow control information from your code, making it much harder for preying eyes to understand what is going on. After applying this feature to the assembly, the disassembled version looks like this:
[GeneratedCode("PresentationBuildTasks", "4.0.0.0")]
public class MainWindow : Window, IComponentConnector
{
// Fields
private bool _contentLoaded;
internal TextBox txtName;
// Methods
public MainWindow()
{
this.InitializeComponent();
}
[DebuggerNonUserCode]
public void InitializeComponent()
{
// This item is obfuscated and can not be translated.
}
private void ReverseButton_Click(object sender, RoutedEventArgs e)
{
string str;
int length;
StringBuilder builder;
int num2;
int num3;
goto Label_001B;
Label_0002:
switch (num3)
{
case 0:
builder = new StringBuilder();
num2 = length - 1;
goto Label_002B;
case 1:
return;
case 2:
num2--;
goto Label_002B;
case 3:
goto Label_005E;
}
Label_001B:
num3 = 3;
goto Label_0002;
Label_002B: ;
if (((num2 >= 0) ? 0 : 1) != 0)
{
num3 = 1;
goto Label_0002;
}
Label_005E:
str = this.txtName.Text;
length = str.Length;
if (length > 0)
{
num3 = 0;
goto Label_0002;
builder.Append(str[num2]);
num3 = 2;
goto Label_0002;
}
this.SayNoInput();
}
private void SayHello(string name)
{
MessageBox.Show(string.Format("Hello {0}", name));
}
private void SayHelloButton_Click(object sender, RoutedEventArgs e)
{
// This item is obfuscated and can not be translated.
}
private void SayNoInput()
{
MessageBox.Show("You did not specify a name");
}
[DebuggerNonUserCode, EditorBrowsable(EditorBrowsableState.Never)]
void IComponentConnector.Connect(int connectionId, object target)
{
// This item is obfuscated and can not be translated.
}
}
CliSecure allows you to take it even further with the ‘Renaming’, ‘Method Call Obfuscation’ and
’String Obfuscation’ features.
Applying all of them to the assembly will produce this:
[GeneratedCode("PresentationBuildTasks", "4.0.0.0")]
public class MainWindow : Window, IComponentConnector
{
// Fields
private bool _contentLoaded;
internal TextBox txtName;
// Methods
public MainWindow()
{
this.InitializeComponent();
}
[DebuggerNonUserCode]
public void InitializeComponent()
{
// This item is obfuscated and can not be translated.
}
private void ReverseButton_Click(object sender, RoutedEventArgs e)
{
string str;
int num;
StringBuilder builder;
int num2;
int num3;
goto Label_001B;
Label_0002:
switch (num3)
{
case 0:
goto Label_009D;
case 1:
return;
case 2:
num2--;
goto Label_002B;
case 3:
str = ?.BQAAAA==%(this.txtName);
num = ?.JwAAAA==%(str);
if (((num <= 0) ? 0 : 1) != 0)
{
num3 = 0;
goto Label_0002;
}
goto Label_009D;
}
Label_001B:
num3 = 3;
goto Label_0002;
Label_002B:
if (num2 >= 0)
{
?.KwAAAA==%(builder, ?.KAAAAA==%(str, num2));
num3 = 2;
}
else
{
this.txtName.Text = ?.EAAAAA==%(builder);
num3 = 1;
}
goto Label_0002;
Label_009D:
builder = new StringBuilder();
num2 = num - 1;
goto Label_002B;
this.SayNoInput();
}
private void SayHello(string name)
{
?.CAAAAA==(?.KQAAAA==
(<CliSecureRT>.cs("G\x009c\x00c0\x00d7\x00c7Z\x0002\x00c2\x00d6"), name));
}
private void SayHelloButton_Click(object sender, RoutedEventArgs e)
{
// This item is obfuscated and can not be translated.
}
private void SayNoInput()
{
?.CAAAAA==(<CliSecureRT>.cs("V\x0096\x00d9\x009b\x00cc\x0013\x001d\x00d2\x00c5
\x0091\x00de\x00c97\x00d7\x0086\x00ef9\x00d0\x00e5\x00052\x0019>6\x0017\x00b5"));
}
[DebuggerNonUserCode, EditorBrowsable(EditorBrowsableState.Never)]
void IComponentConnector.Connect(int connectionId, object target)
{
// This item is obfuscated and can not be translated.
}
}
As you can see, variable names have been replaced with unreadable characters, and the strings in the application are now encrypted.
Combine this with the unique ‘Code Protection’ feature and it’ll be close to impossible for others to ‘decompile’ your application.
CliSecure also allows you to merge multiple assemblies into a single file with the click of a mouse, drastically simplifying various deployment scenario’s.
But it still doesn’t end here!
Licensing
Have you ever tried to build a license system into your application? If you want to do it right, it’s a very daunting and intrusive procedure. CliSecure on the other hand allows you to add Time, Trial, Registration and other product activation features to your applications with minimal effort.
You can deliver hardware locked, time limited, subscription based, hardware locked and feature limited versions of your applications to your customers and allow them to ’upgrade’ their experience at any time.
To enable this you simply use the ‘Licensing’ tab in the CliSecure UI after which you can use the CliSecure SDK to validate licenses and features in your applications.

Let’s say you want to deliver a trial version of your application to potential customers.
The first step is to click the “Project VS.NET Project” button, which will start a wizard for you:

Once you've selected the project, you'll have to create a pair of strong encryption keys, which will be used to protect your project:

Once you’ve completed the wizard, it will generate the license keys,
add the public license key to your project, add the required references and
provide a code template which can be used to start integrating your project with the licensing module.
Now validating a license is as simple as:
LicenseManager.Validate(this.GetType(), this);
Once the code is set up, you can create various licenses, for example a trial license:

The final step is to click the “Create License” button which will generate a license file and some sample code to help you use it in your project:

As you can see the CliSecure UI makes it very easy to protect your code with minimal effort and most importantly does not require you to change the way you write your code in any way. With just a few clicks, you can protect your code and intellectual property. Even with the UI alone you get a lot of value for your money (just think about the value of your code, and what would happen if somebody ran off with it), but there is more to CliSecure than just the UI.
The command line interface
When working on large projects, it can become a little cumbersome to generate the protected assemblies by hand every time. This is where the command line interface comes in. Whether you’re using Visual Studio (with MSBuild) or another IDE, the command line interface can easily be integrated into any of them in order to automate the protection process.
We work with Visual Studio solutions containing many projects, so Visual Studio integration is on the top of our requirements list for anything that changes our build process. In fact, it is one of the reasons we decided not to use some other obfuscating tools in the past, it just complicated our build process, and that’s just not acceptable for large scale projects.
Integrating CliSecure into the VS2010 build process is quite easy:
First you create a new project with the CliSecure UI. Then you have to add the assemblies you want to protect to it. It is however '''very important''' that you add the assemblies from the obj directory and not from the bin directory. The idea here is that CliSecure will protect the assemblies in the obj directory before MSBuild copies them to the bin folder, so make sure you set the output directory to be the same as the input directory:

Next you’ll have to save the CliSecure project to directory where your visual studio solution is stored.
Finally you’ll need to make some changes to your project file (.cproj in my case).
Use notepad or any other plain-text/xml editor and find the following line:
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets"/>
Under that line you can define some new properties and the CliSecure specific task:
<!-- START CliSecure START -->
<PropertyGroup>
<CliSecureLocation>
"E:\Program Files (x86)\SecureTeam\CliSecure.Console.exe"
</CliSecureLocation>
<CliSecureProjectFile>"$(ProjectDir)\clisecure.cls"</CliSecureProjectFile>
</PropertyGroup>
<Target Name="AfterCompile" Condition="'$(Configuration)' == 'Release'" >
<Exec Command="$(CliSecureLocation) /project:$(CliSecureProjectFile)" />
</Target>
<!-- END CliSecure END –>
Of course you’ll have to modify the path to CliSecure.Console.exe to represent the actual location on your system as well as modify the CliSecureProjectFile variable to fit your needs.
Once you’ve done this, all you have to do is reload the project in Visual Studio and build it.
Conclusion
Protecting our software and intellectual property has been a real issue to us up until now. We do not have the resources to implement our own licensing system and even if we did, our code still wouldn’t be protected from preying eyes (disassembly).
If you care about protecting your applications and code and don’t want to waste valuable resources
implementing what might be a half finished solution, you should check out CliSecure right now,
No new comments are allowed on this post.
Comments
Basel
Hello, it is a nice article about the CliSecure solution. I was interested by the licensing part and I have downloaded the demo. I have followed all the steps but when I launch the application, it fails. I have an Cryptographic exception with the message 'The parameter is incorrect' during the 'SecuredComponent' constructor. I hope you can help me to use this promising feature.
TimothyP
Basel, I will forward your question to my contact at CLISecure
Eran Dror
Hi,
I believe this is now solve, please redownload the trial and try again.