A recent project entailed making changes to an existing Windows C# application with the caveat the source code was unavailable (the previous developer refused to provide it). Most developers have experienced a similar situation where the source code cannot be located; sometimes the source code disappears or is lost.

The process of reverse engineering or decompiling an application can be done with the right tools and persistence when working with languages like C++ or C, but it’s not a straightforward process. The managed code (.NET and Java) world provides a much easier approach, as all source code is compiled into Microsoft Intermediate Language (MSIL). The MSIL is converted to machine code by a just-in-time (JIT) compiler when it is executed. The MSIL is well-documented. MSIL includes metadata that provides a wealth of information on the code. For this post, I look at working backwards with a C# application.

Getting started

The starting point for reverse engineering is getting the DLL or EXE files of which you want to learn the inner workings. The next step is locating a tool for decompiling the files (this may be first step, but why do you need a tool without the files?). There are a number of tools available, but the .NET Framework comes with its own tool called Ildasm (MSIL Disassembler). It is installed as part of the Visual Studio and Windows SDKs, so you can access it via the Visual Studio command prompt or the Windows SDK command prompt.

Ildasm takes a file containing MSIL as input (a DLL or EXE file) and outputs source code suitable for the assembler tool (Ildasm.exe). The following command line takes the dll file as input and generates the specified output file (which contains MSIL).

Ildasm compiledFile.dll /output:TRTest.il

Here is a snippet of the MSIL generated by the previous Ildasm command.

.module compiledFile.dll

// MVID: {F5233C6F-701D-4E6B-BA37-ECCAA0B22083}

.imagebase 0x11000000

.file alignment 0x00001000

.stackreserve 0x00100000

.subsystem 0x0003       // WINDOWS_CUI

.corflags 0x00000001    //  ILONLY

// Image base: 0x03370000

// =============== CLASS MEMBERS DECLARATION ===================

.class interface public abstract auto ansi compiledFile.IUpdatableControl


.method public hidebysig newslot specialname abstract virtual

instance bool  get_UpdateAfterCallBack() cil managed


} // end of method IUpdatableControl::get_UpdateAfterCallBack

.method public hidebysig newslot specialname abstract virtual

instance void  set_UpdateAfterCallBack(bool 'value') cil managed


} // end of method IUpdatableControl::set_UpdateAfterCallBack

.method public hidebysig newslot specialname abstract virtual

instance bool  get_AutoUpdateAfterCallBack() cil managed

} // end of method IUpdatableControl::get_AutoUpdateAfterCallBack

.method public hidebysig newslot specialname abstract virtual

instance void  set_AutoUpdateAfterCallBack(bool 'value') cil managed


} // end of method IUpdatableControl::set_AutoUpdateAfterCallBack

This is rather difficult to read and analyze, but it is possible. You can make changes in the MSIL and send it through the assembler (Ildasm.exe).

Exploring other options

I’ve used other tools that simplify the process; I prefer Red Gate’s Reflector, but it’s no longer free — it now requires purchase after a trial period. However, it handles decompiling code and presents the results in an easy to read interface. Figure A shows the results for one DLL. The bottom right portion of the interface includes analysis results where it shows you dependencies.
Figure A

The Reflector interface simplifies reverse engineering code. (Click the image to enlarge.)

Here are three more available options, all of which are free:

  • Dotnet IL Editor (DILE) lets you disassemble and debug .NET code.
  • dotPeek lets you decompile and browse the results.
  • ILSpy is an open source assembly browser and decompiler.

This is only a sampling of the available tools.

Installing roadblocks

While you cannot totally stop others from deconstructing application files/code, you can deter them by using a number of techniques. You can:

  • Use strong-named assemblies that incorporate digital signatures and public keys.
  • Use Microsoft Authenticode.
  • Avoid the all-too-common practice of shipping debug versions of an application. These versions include a wealth of debugging-related information that is beneficial in the reverse engineering process.
  • Consider using obfuscation, which converts your code and symbols into incoherent data while retaining logic. Microsoft offers the Dotfuscator tool for obfuscation, but third-party tools from vendors such as Red Gate are even better.


Whatever the business reason is for reverse engineering code, it is a good skill to be able to use in your everyday work as needed.

Keep your engineering skills up to date by signing up for TechRepublic’s free Software Engineer newsletter, delivered each Tuesday.