Mark Pearl

In part 1 of Crack .Net Applications I demonstrated how easy it was to reverse engineer an an unprotected .Net application. In this post my aim is to highlight a few techniques that one can employ to protect ones code from this type of hacking.

So, my take on software protection is that one can never be 100% protected – given infinite time you can guarantee someone with enough intelligence will be able to bypass all security measures that you ever implement – that being said, we don’t have infinite time and you can use this fact to your advantage – what you want to achieve with software protection is to make it take as much time as possible for someone to bypass your security that it is cheaper for them to buy a license. To achieve this you need to identify the weakest links in your security, and reinforce them before anything else.

If we look at .Net, the weakest link is really that it is easy to view and edit the IL code. So how do we strengthen that?

There are a few options that spring to mind…

Don’t have the code there if you don’t need it. If you have to have the code there, then make it if someone edits the code, it won’t run… If you have to have the code there, make it as hard as possible for someone to easily browse and understand what your code is doing. I’m going to briefly explore all three options…

First - My Killer Application… Before I show any of these techniques I am first going to write the killer application that will make me tons of money… yes, it is a console application and what it does is ask the user for a registration code… if they input the correct code it gives them the full version menu options, else it shows the trial version menu options.

static void Main(string[] args) { Console.WriteLine(“Enter your registration code :”); if (Console.ReadLine() == “123”) { Console.WriteLine(“Full Version Options…”); } else { Console.WriteLine(“Trial Version Options…”); } Console.ReadLine(); }

I am obviously going to make tons of money with this application so how do I protect it?

1…Don’t have the code there if you don’t need it… While this is not always feasible, if it is an option then it is probably one of the more secure techniques. What you want to do is decide on what modules you are going to offer in your trial version. You then are going to go through your code and mark the full version options with preprocessor directives.

When you compile your application, based on the conditional compilation symbols the compiler will either include or omit your full version code from the trial application. The downside of this approach is that

There will be extra work for your users who decide to upgrade from the trial version to the full version (they will have to download a new install), and Your paid for version will still have to have all the code and so someone who buys the software could still crack it and release it (but that’s why we have lawyers isn’t it?) Let me demonstrate this briefly with my killer application.

using System; using System.Collections.Generic; using System.Linq; using System.Text;

namespace ConsoleApplication2 { class Program { static void Main(string[] args) { #if (FULLVERSION) Console.WriteLine(“Enter your registration code :”); if (Console.ReadLine() == “123”) { Console.WriteLine(“Full Version Options…”); } else #else { Console.WriteLine(“Trial Version Options…”); } Console.ReadLine(); #endif } } } As you can see above, my full version code is omitted from the application, and if I view the application through Reflector the full version code is gone as well so they could edit my code as much as they like and still not get anywhere because the areas that are disabled are physically not there…

2010-08-31 08-59-04 PM

That’s all good, but the second you sell your first license, you have in effect exposed yourself to potential risk so we need to look at this technique as a potential first layer of protection, but we will also need additional layers – let’s look at technique 2 & 3.

2…If you have to have the code there, then make it if someone edits the code, it won’t run… There is a way to make a .Net Application verify the version of its assembly and only run if it is the correct version. This is done by strong signing an assembly.

You can read a bit about this topic from the following blog post. Unfortunately it seems like strong name signing, while useful is still easily bypassed with certain tools.

One tool that I found that did this was on codeplex (here) which explained the process.

In addition, it seems like reflexil now supports strong name removing as well, so if someone has access to reflexil they can simply choose to do any of the following to an assembly…

Register the assembly for verification skipping on the pc Resign the assembly with a new key Remove Strong Naming altogether Mark the assembly as delayed signed So while strong name signing will add an additional layer of protection, I would not suggest that it be the only layer of protection that you emply.

  1. If you have to have the code there, make it as hard as possible for someone to easily browse and understand what your code is doing. In short this is called obfuscation. The definition of obfuscation is the concealment of the intended meaning in communication, making communication confusing, intentionally ambiguous, and more difficult to interpret and this is exactly what a .Net obfuscator does to IL code.

A quick search on Stack Overflow for obfuscators revealed a list of potential candidates… I am going to make mention of two of them for demo purposes…

Dotfuscator CryptoObfuscator The reason I mentioned Dotfuscator is because VS2010 now comes with a free community edition of it – in fact have a look on the menu in VS2010 and you will see it there already…

2010-09-01 06-53-56 AM

Using it is quite simple, click on the menu item and it will bring up a license agreement that you need to agree to (first time only).

It will then bring up the Dotfuscator window. To obfuscate an assembly, you need to add it to Dotfuscator by by right clicking on the menu item on them left (ass illustrated below).

2010-09-01 06-57-57 AM

Once the assemblies have been added you then click the build button…

2010-09-01 07-13-27 AM

And it will go to work creating an obfuscated assembly.

If we then compare the un-obfuscated code to the obfuscated code through reflector we can see that the obfuscated code has jumbled a few things up and changed a few names.

2010-09-01 07-18-25 AM

(Un-obfuscated above / Obfuscated below)

2010-09-01 07-17-38 AM

We can still see that the code is understandable – this is because the free community edition of dotfuscator does not obfuscate everything. I believe the commercial edition does a much better job.

Now lets have a look at another obfuscator called CryptoObfuscator to which I do have a commercial license for.

2010-09-01 07-22-52 AM

You can see with a commercial licensed obfuscator there are a lot more options to enable. If we obfuscated the same application using the default settings with Crypto we get the following…

2010-09-01 07-25-39 AM

As you can see from the above illustration, the obfuscated program is extremely hard to understand, string shave been encrypted etc making it extremely hard to reverse engineer the application.

While choosing the right obfuscator is a personal decision, it is important to note the limitations of an obfuscated application. Namely if you are making use of reflection within your application you may have issues and need to apply specific attributes to those sections of code so that the obfuscator can tread carefully around them.

Also, you need to be careful to check that once you have obfuscated an application that it still works – I noticed on several of the threads on Stack Overflow that certain obfuscators crashed the application in certain circumstances. Always check your application after obfuscation.

Closing Comments So that brings me to the end of this series in cracking .Net applications. I understand it was extremely brief but hopefully if you are new to this area then you might have gained a few pointers or places to find out more info.

Like I said before, with security it is a layered approach, meaning implement as many different layers of abstraction as your application warrants. Security seems a bit like a oxymoron as we are told time and time again when we are learning to code to make everything understandable and clear, while with security it is the total opposite – hide and confuse seems to be the name of the game.

Hope you enjoyed these two blog posts - if you have any useful input please leave a comment – I love hearing from experts in each field as this increases my own knowledge base and expands my understanding.

Other Useful Blog Posts Obfuscator General Info - http://www.cumps.be/en/Blog/Read/obfuscation-making-reverse-engineering-harder

Obfuscator General Info - http://howtoselectguides.com/dotnet/obfuscators/1st#sc_obfuscators

Obfuscator General Info - http://stackoverflow.com/questions/2699049/good-obfuscator-for-vs2010-and-net-v4-projects-with-built-in-visual-studio-integ

Dosfuscator - http://msdn.microsoft.com/en-us/library/ms227240%28VS.80%29.aspx

IL Assembly - http://www.codeproject.com/KB/msil/ilassembly.aspx

Reflexil - http://sebastien.lebreton.free.fr/reflexil/

Reflexil - http://www.codeproject.com/KB/msil/reflexil.aspx

Reflexil - http://www.cumps.be/en/Blog/Read/reverse-engineering-with-reflector-and-reflexil

Mono.Cecil - http://www.mono-project.com/Cecil

Neocoder - http://www.codeproject.com/KB/security/NeCoder01.aspx

Code Signing - http://www.cumps.be/en/Blog/Read/code-signing-as-reverse-engineering-protection

Strong Name Signing - http://www.codeproject.com/KB/security/StrongNameRemove20.aspx



blog comments powered by Disqus

Want to get my personal insights on what I learn as I learn it? Subscribe now!


/