ground rules of the .NET platform, as well as with the native language of the
.NET platform: MSIL. I’ll go over some simple MSIL code samples and analyze
them just as I did with IA-32 code in earlier chapters. Finally, I’ll introduce
some tools that are specific to .NET (and to other bytecode-based platforms)
such as obfuscators and decompilers.
Ground Rules
Let’s get one thing straight: reverse engineering of .NET applications is an
entirely different ballgame compared to what I’ve discussed so far. Funda-
mentally, reversing a .NET program is an incredibly trivial task. .NET pro-
grams are compiled into an intermediate language (or bytecode) called MSIL
(Microsoft Intermediate Language). MSIL is highly detailed; it contains far
more high-level information regarding the original program than an IA-32
compiled program does. These details include the full definition of every data
structure used in the program, along with the names of almost every symbol
used in the program. That’s right: The names of every object, data member,
and member function are included in every .NET binary—that’s how the .NET
runtime (the CLR) can find these objects at runtime!
This not only greatly simplifies the process of reversing a program by read-
ing its MSIL code, but it also opens the door to an entirely different level of
reverse-engineering approaches. There are .NET decompilers that can accu-
rately recover a source-code-level representation of most .NET programs. The
resulting code is highly readable, both because of the original symbol names
that are preserved throughout the program, but also because of the highly
detailed information that resides in the binary. This information can be used
by decompilers to reconstruct both the flow and logic of the program and
detailed information regarding its objects and data types. Figure 12.1 demon-
strates a simple C# function and what it looks like after decompilation with the
Salamander decompiler. Notice how pretty much every important detail
regarding the source code is preserved in the decompiled version (local vari-
able names are gone, but Salamander cleverly names them iand j).
Because of the high level of transparency offered by .NET programs, the
concept of obfuscation of .NET binaries is very common and is far more pop-
ular than it is with native IA-32 binaries. In fact, Microsoft even ships an obfus-
cator with its .NET development platform, Visual Studio .NET. As Figure 12.1
demonstrates, if you ship your .NET product without any form of obfuscation,
you might as well ship your source code along with your executable binaries.
424 Chapter 12