Observing and Understanding Obfuscated Output

Step 1 – Using a Disassembler

The .NET Framework SDK ships with a disassembler utility called ildasm that allows you to decompile .NET assemblies into IL Assembly Language statements. To start ildasm , make sure that the .NET Framework SDK is installed and in your path and type ildasm on the command line.

Note: if this does not work and you have installed Visual Studio, ildasm is probably not in your path. To open a Visual Studio command prompt, from the start menu, select Visual Studio [version] | Visual Studio Tools | Visual Studio [version] Command Prompt. Type ildasm.

  • Select the File | Open menu and browse to:
C:\Program Files\PreEmptive Solutions\Dotfuscator Professional Edition 4.0\samples\GettingStarted\bin\Debug 
  • and select GettingStarted.exe. Click Open. A view of the disassembled assembly appears:

  • To compare the currently shown, un-obfuscated HelloWorld application to the obfuscated version, start another copy of ildasm. This time browse to
C:\Program Files\PreEmptive Solutions\Dotfuscator Professional Edition 4.0\samples\GettingStarted\Dotfuscated 
  • and select GettingStarted.exe. Click Open.

Place each ildasm window side-by-side. Compare and contrast both figures.

Notice the unobfuscated disassembly contains names of methods that are fairly understandable. For example, it is safe to assume that the ConverseButton_Click: void (object, class [mscorlib]System.EventArgs) method is called when the Converse button is clicked. Now look at the obfuscated version. Which method is called when the converse button is clicked? It is hard to tell. Also notice the missing SaySomething method. It was removed because the method wasn’t being used anywhere in the code.

Double-click the methods SayHello:string() from the original assembly and a:string() from the obfuscated assembly. These two methods are in fact the same; however, when examining the disassembled IL code further, you will notice that the strings have been encrypted in the obfuscated version to make the code harder to read. For example, locate the following line in the un-obfuscated version:

IL_0000:  ldstr      "Hello, my name is "

Now view the obfuscated version, and try to find the above string. If you’re having trouble finding it, it’s because it’s encrypted and looks like the following:

IL_0000: ldstr bytearray (09 42 26 44 29 46 2B 48 26 4A 67 4C 6D 4E 22 50   
                          28 52 73 54 3B 56 36 58 34 5A 3E 5C 7D 5E 36 60   
                          12 62 43 64 )

You can imagine how confusing this can be for people who are trying to reverse-engineer the code, especially with more complex applications.

Step 2 –Decompiling

If you're now thinking your 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 a step further and actually recreate the source code from our application by using a decompiler such as Reflector or Anakrino. These utilities can decompile a .NET assembly directly back to a high level language like C#, VB .NET, or C++.

In this section we use two freely available decompilers:

  1. Reflector for .NET, http://www.aisto.com/roeder/dotnet/
  2. Anakrino (GUI version) / Exemplar (Command Line version), http://www.saurik.com/net/exemplar/

Running Anakrino/Exemplar against the Dotfuscated GettingStarted.exe file will produce the following error:

Exemplar.exe has encountered a problem and needs to close.  We are sorry for the inconvenience.

Running .NET Reflector against the Dotfuscated GettingStarted.exe file and trying to examine a method such as a() will throw the following exception:

This item appears to be obfuscated and can not be translated.

System.NotSupportedException: Cannot resolve local variable 'Label_0047'.
   at Reflector.CodeModel.Memory.GotoStatement.Resolve()
   at _12.VisitBlockStatement(IBlockStatement statement)
   at _111.VisitStatement(IStatement value)
   at _119.VisitMethodDeclaration(IMethodDeclaration value)
   at _125.VisitMethodDeclaration(IMethodDeclaration value)
   at _126.VisitMethodDeclaration(IMethodDeclaration value)
   at _123.VisitMethodDeclaration(IMethodDeclaration value)
   at _146._1(Boolean )

Thus, Dotfuscator Professional was able to successfully prevent two major decompilers from reverse engineering your Dotfuscated code.