Code Encryption

Oct 13, 2020

Babel Obfuscator can rename symbols within an assembly in order to hide the internal structure and make it less understandable. When it comes to hiding the code inside methods, babel has other protections including String Encryption, Control Flow Obfuscation, and MSIL Code Encryption. The latter is one of the most valid protections when it comes to hiding the code. In this article, we will explain how code encryption can help you to better protect your assemblies and realize a feature-based licensed application.

Note that at the moment MSIL Code Encryption is available with the Enterprise edition for all application and software components running at least on .NET Framework 2.0 or .NET Core 3.0. This feature is not available on other .NET Platforms like .NET Standard or Xamarin. If you want to license your applications using the method described here, you need the Company license.

If you look at a method inside a .NET assembly editor like dnSpy, you can almost see the original source code. Code encryption replaces the original method code with a single call to the Babel compiler which compiles and executes the original method in a secure environment that completely hides the original code from any inspection tool.Consider the following method:

        public static void CreateLicense()
        {
            RSASignature rsa = RSASignature.CreateFromKeyFile("Keys.snk");
            string publicKey = rsa.ExportKeys(true);
            rsa.GenerateKeyInfo = true;

            string licenseKey = new XmlLicense()
                .WithUniqueId()
                .ForAssembly(typeof(Program).Assembly)
                .WithField("app", "s3cret P@sswOrD")
                .WithTrialDays(10)
                .SignWith(rsa)
                .ToReadableString();

            File.WriteAllText(LicenseFileName, licenseKey);
        }

The dnSpy tool can reconstruct the source code using only the assembly binary.

Note that the differences with the original code are minimal.

Once Code Encryption is enabled the same method does not resemble the original one. Indeed, the original code is completely gone, replaced by the call to the Babel compiler.

The Babel compiler encrypts the original method code and if necessary, can extract the encrypted code from the assembly storing all the information necessary to reconstruct the original method inside an external binary file. In this way is very easy to make a feature-based license containing the extracted code or the password to decrypt the code.

To better show how code encryption works consider the following .NET Console application which generates and validate an XML license file with Babel Licensing. The example uses encrypted code with a password. This allows us to create a license embedding the password needed to decrypt the code and run the application. 

First, we need to address which code will be encrypted with password. This can be done using the Obfuscation or an XML rule. For simplicity we will use the Obfuscation attribute:

    // Encrypted code
    // This code is encrypted using a password sored inside the license file
    [Obfuscation(Feature = "msil encryption:Source=app;Internal=true;Password=s3cret P@sswOrD", Exclude = false)]
    class Application
    {
        public static void Run()
        {
            Console.WriteLine("Encrypted code running...");
            var lic = LicenseManager.License;

            if (lic.IsTrial)
            {
                var trial = lic.Restrictions.OfType<TrialRestriction>().FirstOrDefault();
                Console.WriteLine("Trial time left: {0:dd} days {0:hh} hours", trial.TimeLeft);
            }
        }
    }

The attribute is applied to the Application class making Babel use MSIL encryption on every method inside the class. The feature string contains some MSIL encryption feature properties we need to set so that babel can tag any encrypted method with a name (Source), keep the encrypted data internal to the assembly (Internal), and finally define a password for encrypting code.

msil encryption:Source=app;Internal=true;Password=s3cret P@sswOrD

I admit I did not have much imagination for the password anyway this password will be used to encrypt all the methods inside the class. Without the password needed to decrypt and compile methods tagged with “app” source, the application cannot run. Now we need a mechanism to access the password when Babel will ask the password to decrypt a method tagged app. At runtime when any method of the class Application is called, Babel compiler will take over and issue a request to get the password for decrypting the method called. The receipt of the request is a method defined inside the assembly having the following declaration:

        [Obfuscation(Feature = "msil encryption get password", Exclude = false)]
        internal static string GetEncryptionPassword(string source)
        {
            return LicenseManager.License.Fields.First(item => item.Name == source).Value;
        }

It is important to have the method declared as internal or public, otherwise Babel will not be able to access the method. We will use a license file filed to store the password. The field name will be the same tag name assigned to the encrypted method. We have everything in place to get the application running encrypted. The license file plays a central role in providing the decryption password. The advantages are that the application cannot run without the license file. You can extend the concept by encrypting different parts of your application using unique source tags and passwords. Partitioning the application in this way will allow you to make feature-based licenses where every field is tied to a specific application functionality that cannot run without the proper password and license.

The complete source code of the discussed example is available to download here: CodeEncryption.zip. To build the solution copy your Company license file inside the solution folder then rebuild the Release configuration.

Pin It on Pinterest

Share This