Obfuscate member names in .NET code

Private and Public members names obfuscation.
It scrambles names of classes, methods, variables, and other assembly members. It makes assembly code reverse engineering much harder by obfuscating names. Some Skater settings allow to generated names that will prevent recompilation.

Public members in dll libraries are advisedly reserved from obfuscation because they are intended to be used in external assembly code. If you are sure some of public members are not to be accessed from outside, you may want to obfuscate them.
For exe executables you may consider the assemblies to be self-contained, and set obfuscation of all possible names very aggressively, including Public Members.

Skater .NET Obfuscator
More about Skater .NET Obfuscator
Download Skater .NET Obfuscator
Order Skater .NET Obfuscator

Let's try to write a simple command-line application and then obfuscate it. The following console programs are the VB.NET and C# version of the "Hello World!" program, which displays the string "Hello World!" Actually it is not the traditional "Hello World!" and it displays in addition today's date and current time. We have added couple of private variables to see what happen when we obfuscate them.

VB .NET

Imports System
Module Module1
Private str As String = "Hello World! Today is:"
Private today As Date = Now
Sub Main()
Console.WriteLine(str + CStr(today))
End Sub
End Module

C#

using System;
struct Module1
{
private string str = "Hello World! Today is:";
private System.DateTime today = Now;
void Main()
{
Console.WriteLine(str + System.Convert.ToString(today));
}
}

You can see four highlighted members' names. Two are private variables' names today and str. Module1 is name of the class. Main is name of method that is single method in the simple class.
Now we are ready to compile the simple code in .NET environment. We may get ConsoleApplication1.exe executable file as a result of compilation. What is inside in the executable? Why do people say we need to hide our .NET stuff?
The .NET Framework SDK ships with a disassembler utility called ILDasm that allows you to decompile .NET assemblies into IL (Intermediate Language) Assembly Language statements. To decompile the ConsoleApplication1.exe file start ILDasm on the command line. Take a look what we got after the decompilation:

IL

.class private auto ansi sealed beforefieldinit Module1
extends [mscorlib]System.Object
{
.custom instance void [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.
StandardModuleAttribute::.ctor() = ( 01 00 00 00 )
.field private static string str
.field private static valuetype [mscorlib]System.DateTime today
.method private specialname rtspecialname static
void .cctor() cil managed
{
.maxstack 8
IL_0000: ldstr "Hello World! Today is:"
IL_0005: stsfld string ConsoleApplication1.Module1::str
IL_000a: call valuetype [mscorlib]System.DateTime [Microsoft.VisualBasic]Microsoft.
VisualBasic.DateAndTime::get_Now()
IL_000f: stsfld valuetype [mscorlib]System.DateTime ConsoleApplication1.Module1::today
IL_0014: nop
IL_0015: ret
} // end of method Module1::.cctor
.method public static void Main() cil managed
{
.entrypoint
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 8
IL_0000: nop
IL_0001: ldsfld string ConsoleApplication1.Module1::str
IL_0006: ldsfld valuetype [mscorlib]System.DateTime ConsoleApplication1.Module1::today
IL_000b: call string [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.StringType::
FromDate(valuetype [mscorlib]System.DateTime)
IL_0010: call string [mscorlib]System.String::Concat(string,
string)
IL_0015: call void [mscorlib]System.Console::WriteLine(string)
IL_001a: nop
IL_001b: nop
IL_001c: ret
} // end of method Module1::Main
} // end of class Module1

Everything looks pretty obvious and understandable in the IL script. Is not it? Right, it is hard to figure out the IL code for us more mortals. So if you are now guessing your .NET source code will be accessible only to a small circle of technical folks who actually know IL Assembly Language, think again. You can take this step further and actually recreate the source code by using some much sophisticated decompilers. These 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 Skater Obfuscator. In the Obfuscator interface go to Options tab and select 'Alpha-Numeric characters' under 'Naming Conventions'. Choose all Private and all Public members obfuscation mode.
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 ILDasm.exe again against the new obfuscated executable and it will give us the following IL script:

IL

.class private auto ansi sealed beforefieldinit '0AAAA'
extends [mscorlib]System.Object
{
.custom instance void [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.
StandardModuleAttribute::.ctor() = ( 01 00 00 00 )
.field private static string '1AAA0'
.field private static valuetype [mscorlib]System.DateTime '2AAAA'
.method private specialname rtspecialname static
void .cctor() cil managed
{
.maxstack 8
IL_0000: ldstr "Hello World! Today is:"
IL_0005: stsfld string ConsoleApplication1.'0AAAA'::'1AAA0'
IL_000a: call valuetype [mscorlib]System.DateTime [Microsoft.VisualBasic]Microsoft.
VisualBasic.DateAndTime::get_Now()
IL_000f: stsfld valuetype [mscorlib]System.DateTime ConsoleApplication1.'0AAAA'::'2AAAA'
IL_0014: nop
IL_0015: ret
} // end of method '0AAAA'::.cctor
.method public static void '1AAAA'() cil managed
{
.entrypoint
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 8
IL_0000: nop
IL_0001: ldsfld string ConsoleApplication1.'0AAAA'::'1AAA0'
IL_0006: ldsfld valuetype [mscorlib]System.DateTime ConsoleApplication1.'0AAAA'::'2AAAA'
IL_000b: call string [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.StringType::
FromDate(valuetype [mscorlib]System.DateTime)
IL_0010: call string [mscorlib]System.String::Concat(string,
string)
IL_0015: call void [mscorlib]System.Console::WriteLine(string)
IL_001a: nop
IL_001b: nop
IL_001c: ret
} // end of method '0AAAA'::'1AAAA'
} // end of class '0AAAA'

Skater .NET Obfuscator just replaced member names with alpha-numeric combinations that makes harder to understand the code. However it is not so big trick and every Obfuscator can do that. Everyone can replace the alpha-numeric char combinations with some eye-friendly names. Moreover, by using ILasm.exe (one more .NET Framework SDK assembler utility that allows you to compile IL code back into an executable) we can easily recompile the obfuscated IL output and it will work without problems.
Skater .NET Obfuscator can generate a non-recompilable executables. See the IL script below.

IL

.class private auto ansi sealed beforefieldinit '?'
extends [mscorlib]System.Object
{
.custom instance void [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.
StandardModuleAttribute::.ctor() = ( 01 00 00 00 )
.field private static string '?'
.field private static valuetype [mscorlib]System.DateTime '?'
.method private specialname rtspecialname static
void .cctor() cil managed
{
.maxstack 8
IL_0000: ldstr "Hello World! Today is:"
IL_0005: stsfld string ConsoleApplication1.'?'::'?'
IL_000a: call valuetype [mscorlib]System.DateTime [Microsoft.VisualBasic]Microsoft.
VisualBasic.DateAndTime::get_Now()
IL_000f: stsfld valuetype [mscorlib]System.DateTime ConsoleApplication1.'?'::'?'
IL_0014: nop
IL_0015: ret
} // end of method '?'::.cctor
.method public static void '?'() cil managed
{
.entrypoint
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 8
IL_0000: nop
IL_0001: ldsfld string ConsoleApplication1.'?'::'?'
IL_0006: ldsfld valuetype [mscorlib]System.DateTime ConsoleApplication1.'?'::'?'
IL_000b: call string [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.StringType::
FromDate(valuetype [mscorlib]System.DateTime)
IL_0010: call string [mscorlib]System.String::Concat(string,
string)
IL_0015: call void [mscorlib]System.Console::WriteLine(string)
IL_001a: nop
IL_001b: nop
IL_001c: ret
} // end of method '?'::'?'
} // end of class '?'

Sure, the presented above IL code can not be compiled or the compiled executable will not work well. As you can see all member names has the same single '?' character representation. We can get the result by using Skater .NET Obfuscator special settings. In the Obfuscator interface go to Options tab and select '?' characters under 'Naming Conventions'.

The member names obfuscation is the very first essential step of .NET assembly obfuscation. You need to apply other Skater .NET Obfuscator methods and algorithms to better secure your .NET apps.






Copyright © 2001-2014 Rustemsoft LLC