[glowpurple]Decompiling .net and code obfuscation[/glowpurple]

The following is a short tutorial on the decompilation of .net code and the
use of code obfuscation. The examples are done with C# but could be done
with other .net languages.

Why would anyone want to decompile code? By decompiling your code I can
find out your secrets. How your software is built, what algorithms you use,
what the application itself is doing at any one time. I can then go on to
make modified software to distribute on p2p systems to attack other people
or steal information. I can use it in an effort to gain unauthorized
privileges or abilities on your servers. I can use it to bypass or remove
your software licensing system and gain free use of your software forever.
Finally, I can take your handy dandy patented algorithm and sell it to your
competition....corporate espionage anyone?



1> Decompilation

Decompilation is a type of reverse engineering using software tools to
retrieve a source code representation of a program or assembly from the
compiled binary, bytecode or IL.

The interesting thing about .net however, is since the majority of the code
is compiled to IL and since it is all built to be interoperable with
whatever .net enabled language you want to use, you can decompile it to
whichever .net enabled language you are most comfortable with. This means you
can take an assembly you created with C# and decompile it to perl.net or
vb.net if you're more comfortable with either of those languages.

This makes the reverse engineering process that much easier for the
attacker.



2> Decompilation example

Now to get your hands dirty. To do the following examples you will need
.net development tools and an IL decompiler. Here are some free tools to
get you through the examples:

Optional - SharpDevelop IDE (an opensource C# IDE) -
http://www.icsharpcode.net/OpenSource/SD/Default.aspx

Required - .net SDK -
http://www.microsoft.com/downloads/d...isplaylang=en-

Required - IL Decompiler - Ankarino/Exemplar is used in this example, there
is an assortment of options that are available via google however. -
http://www.saurik.com/net/exemplar/


Now once you have your tools installed and are at least minimally familiar
with them we can get to work.

A) Create your example program.

Fire up your handy dandy IDE or text editor and create a new file named
Example.cs (we're working with C# here). Enter the code below into the file
and save it.

//<Code>
using System;

namespace Example
{
/// <summary>
/// Summary description for Class1.
/// </summary>
///

class Example
{
private String strSecret = "My Licensing sucks.";

private string SecretText
{
get { return strSecret;}
}

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
//
// TODO: Add code to start application here
//


Example thisExample = new Example();
thisExample.licenseMe();
thisExample.displayGreeting();
}

private void licenseMe()
{
Console.Out.WriteLine(this.SecretText);
}

public void displayGreeting()
{
Console.Out.WriteLine("We love to reverse engineer

code.");
}
}

//</Code>


B) Compile your example program.

You will need to use whatever process that is required by your IDE. If you
are using the .net sdk it is a simple matter of:
csc example.cs

If you are having problems compiling I would recommend checking you have
entered and saved the code properly, that the sdk is installed properly, and
that you are working from the correct directory.


C) Test your code

Just for the fun of it run your code once. Open up a console window,
navigate to the appropriate directory (wherever you compiled your software
to) and run the app. You should see:

My Licensing sucks.
We love to reverse engineer code.

Yay us.


D) Decompiling the code

Now, if you have your handy dandy decompiler installed you can decompile
your example program.
Open up a console window and enter the following line, making the proper
modifications for your system and configuration:

c:\decompiler\Exemplar.exe "c:\Example\Example.exe" >

c:\example\reversedexample.txt

reversedexample.txt will contain code very similar to:

namespace Example {
class Example {
private string32strSecret59
private string SecretText { get;

} [STAThread] private static void Main(string[]

args) { Example local0; local0 = new

Example(); local0.licenseMe();

local0.displayGreeting(); } private void

licenseMe() { Console.Out.WriteLine(this.SecretText);

} public void displayGreeting() {

Console.Out.WriteLine("We love to reverse engineer code."); }

public Example() : base() { this.strSecret = "My

Licensing sucks."; } }
}


While that is not the exact code you entered, it's very obvious that there
is enough information there to figure out what you are doing and that the
strings used in the program are easy to access.

Another fun way to poke around in files is to use 'strings'. What is
strings you ask (unless you are an experienced linux nerd...)? Strings is a
program generally found on linux systems that will parse through a file
looking for...well...strings. That lovely text you displayed in your
program above will be displayed to the user, any encryption keys you thought
you were hiding in the compiled code will be displayed too. Sometimes you
can find other information that may be used for nefarious purposes such as
developer or other employee names, account names, machine names, passwords,
, ip addresses, etc.


But what if you don't want to run a linux box for this? Simple, you pick up
cygwin. Install the cygwin tools on your winders box, add it's bin
directory to the path environment variable and viola...you have strings
anytime you want to use it in your reverse engineering or software hacking
adventures.


4> Code obfuscation

Code obfuscation is a process used to increase the difficulty of reverse
engineering the software by using software tools to make changes to the code
/bytecode. Generally there are three levels [1] of code obfuscation:

1) Renaming methods and fields - The simplest obfuscators rename the

non-public (if you change the public ones you destroy the interfaces for
your software) methods and fields defined by your code to values that appear
very similar or like garbage data. One example is long strings that differ
by only a single character, another is to use non-printing characters
accepted by the .net runtime but that won't be used correctly by most text
editors.

2) Adding control flow obfuscation - With control flow obfuscation, the

obfuscator tool creates complex sequences of method calls that don't do
anything. This can confuse decompilers and makes the end result code a
nightmare to read. Combined with field/method renaming it can be fairly
effective.

3) Encrypting literal strings - With this, literal strings in your program
are encrypted. This can make secrets harder to find and can slow down the
reverse engineering process by making the low hanging fruit/clues disappear.

If I can't just run strings/grep against the binary or IL to find your
licensing or crypto related functions directly, it raises the bar a little
bit.


5> Obfuscation Example
For this example you will need to pick up the community edition of .fuscator
and install it.

http://www.preemptive.com/products/dotfuscator/

A) If you have not done the examples from above please do them.

B) Once dotfuscator is installed open it up. The community edition will
only allow you to do level one obfuscation, method and field renaming. If
you upgrade to pro you get the other bells and whistles. We'll stick to
community for now.

c) Create a new dotfuscator project.

D) Click the 'Trigger' tab, then browse to and select the example.exe
application you created earlier.

E) Click the 'Build' tab and enter a destination directory (make sure it is
different from the directory that the example.exe application currently
resides in).

F) Click the build button under the destination directory field. This will
make dotfuscator read in the IL from your original application, obfuscate
it, and write it to your new directory.

G) Decompile the new example and review the code

c:\decompiler\Exemplar.exe "c:\Example\obfuscated\Example.exe" >

c:\example\obfuscated\reversedexample.txt

The code may look something like this snippet -

class a {
private string32a59
private string b() { string local0; local0 =

this.a; return local0; } [STAThread] private static void

Main(string[] args) { a local0; local0 = new a();

local0.a(); local0.c(); } private void a() {

Console.Out.WriteLine(this.b()); } public void c() {

Console.Out.WriteLine("We love to reverse engineer code."); }

public a() { this.a = "My Licensing sucks."; this = new

object(); }}
public class DotfuscatorAttribute {
private string32a59
public string


As you can see, some simple renaming has been done to private variables and
methods to make the reverse engineer's job a little more difficult. What is
class a? You'll have to do some exploration to find out now...

This level of obfuscation will only slow the reverse engineer down a little
bit. The following two levels of obfuscation raise the bar but still won't
keep the determined our resourceful attacker out.

Even then, it is an arms race between the obfuscating camp and the
decompiling camp. As each new obfuscation method or tool comes out, a new
decompiling tool will come out to counter whatever advances were made.



[1]: Programming .net Security - Adam Freeman, Allen Jones: 2.6 Decompiling
Explained