There are many questions from our customers on how to protect .NET applications against cracking and dumping. In this article we will try to describe all the weak moments and details in protection of such specific files.

.NET files are rather different than the native files that can be compiled with C++, Delphi, Pascal and others native compilators. .NET files do not contain instructions (machine code) that are being running on computer’s CPU, they contain a data (set of instructions) to run on .NET virtual processor, which located in .NET runtime libraries. So protection of such files with Enigma Protector (which is mainly designed for protecting of native applications) requires some more attention from developer.

Let’s start with the simple test Windows Forms C# application written in Visual Studio. Application has few fields, it asks user to enter degree angle value and then calculates angle sinus, cosine, tangent by button click.

The code is pretty simple

At this step we can compile the project to .exe file and simply protect with Enigma Protector. Protected file will work well, but it is usually not enough to protect the application from being reverse engineered by advanced cracker.

Obfuscation

Enigma Protector does not obfuscate .net code, so the first thing we have to do after compilation – obfuscate the file. In most of the cases it is enough to use even free, open source .net obfuscation tools, so let’s try to apply ConfuserEx.

In ConfuserEx, we select the folder with executable to obfuscate and the executable file itself.

On the Settings panel, select the file in the left panel and add protection rules. I’ve used Normal preset

No need to enable compression. Click Protect! and wait until it finishes.

As a result, we get folder “Confused” with the obfuscated exe file.

Let’s try dotPeek to see the changes in the code that we got after obfuscation.

Code before obfuscation, almost same as original code
Code after obfuscation. Names are renamed, code is obfuscated

Now let’s try Enigma Protector, open it, create new project, select the file to protect, enter product name and version, then click Protect button

When Enigma finishes, run protected file, check if it works well.

This kind of protection much complex for cracker to analyze. If there is no ways to apply other options described below, that’s already good point for start.

Protection Features

This step is simple to apply, it describes basic features of Enigma Protector which are worth to use:

  • Checkup – Anti-debugger – force protection to quit application if debugger is found. Debugger is a tool that crackers are using to reverse the application
  • Checkup – Control Sum – checks for modification of protected file and protection core in process memory
  • Protection Features – Inline Patching – protects application and protection code against changes in memory
  • Virtual Box – Files – if you have some external files, like .dll, pictures, data files, they all can be hidden from cracker using this feature (files, embedded into Virtual Box, can be removed from disk since they will be emulated by protection in memory)

Protected Strings

We can use protected strings for deeper integration of application into protection. Imagine that cracker dumped the application, somehow got rid of protection, resulting file won’t work (or work correctly) because protected strings will be kept in removed protection, that’s a purpose of using protected strings feature.

Using same example above, we have two strings in source code suitable for protection, they are the following:

Apart of that, in our example, there are strings in form designer module, inside InitializeComponent function. They can also be used for strings protection.

Let’s add strings for protection in Enigma Protector, go to Protection Features – Protected Strings, add couple of strings from source code there. Click Options button and specify the type of data as Wide String:

Finally, list of protected strings should look as following:

After protected strings are loaded in protection, we need to extract them from protection in application. In Visual Studio we need to add Enigma_IDE.cs module to the project (take it from the folder “EnigmaSDK\C# (.NET)\” of installed Enigma Protector). Simply drag and drop this file in project in Solution Explorer:

Now we are able to use Enigma API functions. To extract protected strings from protection we need to call the function EP_ProtectedStringByIDAsWideString/EP_ProtectedStringByKeyAsWideString which both are wrappers of native EP_ProtectedStringByID/EP_ProtectedStringByKey functions.

Note, above we added string with the option Wide String in Enigma Protector. If we specify the option as Ansi String, then we have to use functions
EP_ProtectedStringByIDAsAnsiString/EP_ProtectedStringByKeyAsAnsiString in the application code.

ID or Key parameters should be taken from Enigma Protector. These parameters are unique for each string and protection applies it automatically for new added string, however they can be changed by custom value manually too.

So, when we extract protected string from protection, our code looks as following:

Now we should compile the application, process it with ConfuserEx, protect with Enigma Protector and check if resulting file works well.

Native Library

We are ready to implement the most effective protection of .net files using full power of Enigma Protector. Main idea of this way – moving part of application functionality to native library and protection it with virtual machine feature. Due to specifics of .net files, virtual machine feature of Enigma Protector can’t be used directly for such files (it can be applied to native files only), but we can create external native .dll, protect it using virtual machine, and then use functions of this .dll within .net program.

In our example we are using functions for sinus/cosine/tangent calculation, this is a suitable part to be moved to native library. Let’s create a native dll project, start from empty C++ project in Visual Studio:

Now do the following basic steps for project configuration:

  • Project – Add – New Item, nativelib.c
  • Project – Add – New Item, nativelib.h
  • From “EnigmaSDK\VC\” take three files: enigma_ide.h, enigma_ide.lib, enigma_ide64.lib and copy them to the project folder. Then Project – Add – Existing Item, add enigma_ide.h to the project. This adds Enigma API description module to the project, so we can use Enigma API functions
  • Project – Add – New Item, nativelib.def (used to undecorate the name of exported functions)
  • Project – Properties – General – Configuration Type – Dynamic Library (.dll)
  • Project – Properties – General – Characters Set – Use Unicode Character Set
  • Project – Properties – General – Use of MFC – Use MFC in a Static Library (allows to avoid using of visual studio runtime libraries)
  • Project – Properties – Linker – System – Subsystem – Windows (/SUBSYSTEM:WINDOWS)
  • Project – Properties – Linker – Advanced – Entry Point – DllMain

Use the code from attached project. Make sure you compile file with the Release configuration. Working part of the code is following:

#pragma optimize("", off)
double __stdcall Enigma_Sin(double Angle)
{
	EP_Marker("vm_risc_begin");
	double temp = sin(Angle);
	EP_Marker("vm_risc_end");
	return temp;
}

double __stdcall Enigma_Cos(double Angle)
{
	EP_Marker("vm_risc_begin");
	double temp = cos(Angle);
	EP_Marker("vm_risc_end");
	return temp;
}

double __stdcall Enigma_Tan(double Angle)
{
	EP_Marker("vm_risc_begin");
	double temp = tan(Angle);
	EP_Marker("vm_risc_end");
	return temp;
}
#pragma optimize("", on)

Few comments on this:

  • Pair of calls EP_Marker(“vm_risc_begin”)/EP_Marker(“vm_risc_end”) surrounds the code to be protected with virtual machine
  • pragma optimize(“”, off) disables code optimization by compiler. If we do not use this option, compiler may reorder our code and position of EP_Marker calls will be undefined (but we need EP_Marker to surround the code we protect).

After compilation we get nativelib.dll file, this is a library that exports three functions: Enigma_Sin, Enigma_Cos, Enigma_Tan for calculation of sinus, cosine and tangent from native code.

Now we need to protect this dll file. Open Enigma Protector, select the file nativelib.dll to protect and protect it. Check the protection log, protector has to find 3 pairs of markers. Also, make sure there is no warnings or errors related to markers. Finally we have to get nativedll_protected.dll file.

For .dll protection, same protection features, that we described above for .net exe, can be used, except Virtual Box.

That’s a time to connect protected dll with the .net program and replace part of functionality. In .net program we need to add description of three functions from native dll. It can be done using DllImport statement:

Final point in this chapter is protection of .net exe file together with nativedll_protected.dll. When protecting .exe, in Enigma Protector, go to Virtual Box – Files and add nativedll_protected.dll to %DEFAULT FOLDER%, to hide this file from end user.

Now protect the file. This file should be used alone, without nativedll_protected.dll since we hid it using Virtual Box feature.

Additional: Protect nativedll with MAP file

In the previous chapter we explained how to protect parts of code of nativedll using markers. However, there is one more method of code protection with virtual machine (really it is even better than markers) – using MAP file. MAP file is a special file that is created by compiler, it contains description of the C++ functions used in project. Enigma Protector uses this file to allow you to select the functions you would like to protect.

To move forward with such protection, first we need to remove EP_Marker markers from nativedll code, optimization does not matter in this case anymore, so remove it also.

Code simplifies to following:

Next step, force compiler to generate MAP file. In Visual Studio – Project Properties – Linker – Debugging – Generate Map File set to Yes

Then compile the project. As a result, in the same folder with nativedll.dll we have to have a new file – nativedll.map. Open Enigma Protect, select nativedll.dll to protect, go to Virtual Machine – Functions Selecting panel and click Add Function(s) button. If everything was made OK, then we have to see the list of functions, that the nativedll.dll contains

From the left list we have to select our three functions and add them for protection.

Please note, inside Enigma_Sin function we see the call of __libm_sse2_sin_precise function, double click on it (Enigma Protector will open it’s disassembler listing) and add this function to protection too. Do the same for Enigma_Cos and Enigma_Tan. List of functions for protection will look as following

We may also change the virtualization method for selected functions from RISC VM to Classic VM. RISC VM is very complex to reverse, but it is also slow and heavy. Classic VM is more easy to reverse, but it is small and fast. Depending on requirements select necessary virtual machine to apply.

Protection using MAP file has the same effectiveness as protection with code markers, but due to some specifics, this protection is more recommended.

Additional: Compilation of .net exe file

By default Visual Studio allows to compile exe file in Any CPU platform, resulting file should run as a 32 bit process on Windows x86 and as 64 bit process on Windows x64. Compiled file itself becomes a 32 bit file anyway. Due to this, Enigma Protector x86 should be used for protection and protected file will run in 32 bit environment anyway, independent on Windows version. This is a limitation of protection.

If you wish the file run as 64 bit process, while compilation change the platform to x64. In this case the compiled file will have x64 structure, so Enigma Protector x64 should be used and the protected file will run as 64 bit process.

Having Any CPU feature working after protection is impossible. After protection your file can be either 32 either 64 bit.

Additional: Protection of external .net assemblies in .dll files

Most of .net applications are using components build in external .dll files. Such .dll files are specific by structure and the way how system uses them and it is not possible to protect them such way how we do with .net exe files or native dll.

The only way to protect such files – using of Virtual Box when protecting .exe file that uses them.

So when you create protection project in Enigma Protector, enable Virtual Box – Files feature, add all external dll dependencies to %DEFAULT FOLDER%. After protection, all such embedded files will be emulated in memory, so no need to distribute them with the protected application.

Tutorial Downloads

  • ConfuserEx – obfuscation tool for .net files
  • Test – test .net c# program
  • nativedll – native dll written in C++
  • nativedll – Delphi or Lazarus/FreePascal sources