-
Notifications
You must be signed in to change notification settings - Fork 21
Protect .NET String values by hiding them into machine code DLL
Every developer must understand how .NET source code protection is important to prevent intellectual property loss. There are a lot of reasons to properly protect .NET project’s source codes. However code protection from obfuscation cannot be obtained, but instead from writing secure code, there are a lot of circumstances why software developers cannot distribute source codes for bunch of reasons.
NOTE: Recently MindSystemm group has released a special tool called Skater.NetDeobfuscator [url: https://github.com/MindSystemm/Skater.NetDeobfuscator] that takes advantage of vulnerabilities of the Skater .NET obfuscator.
Hiding encrypted .NET String values into machine code DLL has been redesigned. Since Skater ver9.7 the algorithm is more secure now.
.NET String variables in .NET source codes are very common and most defenseless members of any .NET class. Because String variables provide valuable tips for hackers trying to decipher .NET source codes it is necessary to protect .NET String values from being reverse-engineered. It will not in 100% avert from hacking your project and make your data visible. But for instance, a hacker trying to break a licensing code procedure apparently would be focused on Strings having to do with licensing to find the corresponding function/method in your source code. Skater makes this complicated by encrypting the strings in .NET assemblies. This is done through adding a decryption mechanism into the assembly binary code and then calling the decryption routine at runtime to get the primary source String values.
Whilst string values are still located inside obfuscated .NET assembly (dll or exe) some of the recent de-compilers figured out how to reverse-engineer the protected Strings. The new de-compilers infringe the decryption routine and can display the original String values in decompiled source code.
Strings are vital code parts. It makes sense to create them in native code. Skater generates a C++ written DLL with the protected Strings. This Skater’s option protects algorithms by coding Strings in native code and store them in a separate machine-code DLL. Native code can be reverse engineered but it is a very tough job. Plus, Strings are encrypt-protected in the DLL.
To learn how it works let’s start a small .NET project. We will be creating a simple .NET Console application that includes a single “Hello World!” string that we want to protect.
C#
using System;
struct Module1
{
private string str = "Hello World!";
void Main()
{
Console.WriteLine(str);
}
}
VB.NET
Imports System
Module Module1
Private str As String = "Hello World!"
Sub Main()
Console.WriteLine(str)
End Sub
End Module
Take a look what we got after the ConsoleApplication1.exe decompilation:
We can see the non-obfuscated "Hello World!" string in the decompiler's interface. Decompilation tools can decompile a .NET assembly directly back to a high level language like C#, VB .NET, or C++. Ok, we are ready to obfuscate the sample ConsoleApplication1.exe executable by using Skater .NET Obfuscator. Open the exe file in . In the Obfuscator interface go to Strings tab and select 'Keep Strings Inside The Output Assembly' under 'Strings Store Location'.
When you run the obfuscated ConsoleApplication1.exe it produces the same result. Take a look what changed inside the simple program. We need to run the decompiler again against the new obfuscated executable and it will give us the following decompilation result:
The “Hello World!” string has been allocated by Skater into a public variable then it was encrypted. We can pretty easily spot the encrypted string inside that decompiled script in the figure above. Should this make it pretty obvious that our code is protected? Is it not simply too easy to decrypt the safe .NET code? Almost. An absolute hacker still can choose a password for the encrypted string and decompile it. It will take more time but it is not impossible. So what can we do more to protect String values in our .NET algorithms?
is using native code to protect vital parts of source code. It protects our algorithm by coding Strings in native code while preserving the user interface in .NET. Skater extracts String values and uploads into C++ source code. Then it compiles the C++ written code and locate the resulting machine-code library (appExtension.dll) file in the output directory. When our final obfuscated assembly runs it will be calling this DLL through platform invoke (Pinvoke Interop) as that is the shortcut way to call the machine-code from .NET app. To see that go to obfuscate the ConsoleApplication1.exe executable again by using Skater .NET Obfuscator. Open the exe file in Skater Obfuscator. But for this time, in the Obfuscator interface go to Strings tab and select 'Strings Stored in Separate DLL (recommended)' under 'Strings Store Location'.
After the obfuscation is done the native-code DLL will be located in the same directory of our output assembly path. Then we need to specify the Separate DLL file name. By default the name is 'appExtension'.
After the obfuscation process done take a look what changed inside the obfuscated ConsoleApplication1.exe program:
As shown in the decompiled script above the "Hello World!" string is now located in the separate appExtension.dll library file. That library is an unmanaged binary machine code COM file. It is not accessible/openable by .NET assembly browsers.
So our source code is reliably stealthy now from the usual means of .NET deciphering. Although it does not imply that our .NET program is totally protected. Of course, this is in some measure much complicated to figure out our algorithm than before, but it is not impossible. Machine code can be reverse engineered but it is a very tough job, particularly when the program gets larger and structurally composite.
A disadvantage with this technique is that we will have to distribute the additional Skater-generated COM DLL to hide our vital code parts in native code. As might be expected, we would prefer to deal with managed code only, but depending on the .NET product, the separated COM library is an opportunity. As a conclusion, no matter what we do, if our code is placed at the end-user's PC, it is not safe. As long as the code is placed at the end-user, all we can do is to make it as unwieldy as possible to get to the original source code, with any luck avoiding most hacker's attempts.
Note. You must include the Separate Strings DLL into your product distribution package and install your final .NET assembly strictly together with that DLL file. Otherwise your .NET assembly will not work. This mechanism is designed to ensure that .NET assembly browsers cannot see and decipher the output assembly’s String objects. It makes String values completely invisible.