NDepend Blog

Improve your .NET code quality with NDepend

.NET – 7 Decompiler Compared (2024)

January 10, 2024 9 minutes read

.NET Decompilers Compared

Looking to reverse engineer or disassemble some .NET code? Then learning how to decompile .NET assemblies is an essential skill for any .NET developer or security engineer. Fortunately, there are many .NET Decompiler tools available.

This article lists all .NET Decompilers along with their pros and cons to help you choose the best one that meets your needs. To ease comparison, for each decompiler a screenshot of the decompiled method ScreenToGif App_Startup() is provided. Also, the title of each section highlights the main fact: free/commercial, OSS or not, and which decompilation language target is supported.

What does it mean to decompile .NET code?

C#, VB.NET and F# code gets compiled to IL code. A DLL file is produced by the compilation of a .NET project (csproj, vbproj…). A DLL file is a binary file that contains IL code compiled with an efficient binary format. IL stands for Intermediate Language. IL code is intermediate in the sense it sits between high-level language like C# and low-level native code executed by the CPU. Consequently, IL is much less human-readable than C# code and much more human-readable than native code.

When you write code in C#, VB.NET, or F#, it gets compiled into IL code, which stands for Intermediate Language. This IL code is then stored in a DLL file. A DLL is a binary file that contains the IL code compiled in an efficient binary format. While IL is less human-readable than C# code, it’s still more human-readable than the low-level native code that the CPU executes.

At runtime, the IL code within the DLLs is compiled by the JIT compiler to native code. The native code is then directly executed by the CPU. JIT stands for Just-In-Time: JIT compiling means that the IL code of a method is compiled to native code only when the method is called for the first time at runtime.

.NET Compilation Illustrated

Here is the .NET compilation process illustrated:

.NET Compilation

.NET Decompilation Illustrated

The .NET Decompilation process is the reverse of C# Compilation. This is why one needs a .NET Decompiler tool: to obtain readable C# source code from compiled IL code.

.NET Decompilation

ILSpy for everyone   [free  OSS  C# IL  multi-platforms]

ILSpy is the de-facto .NET Decompiler. You can install it from the Microsoft Store.

  • It’s open-sourced on github.
  • The project started in 2011 and is nowadays fully mature,
  • It has all the features you might wish for when decompiling one or several assemblies: search a symbol, open a pre-saved list of assemblies, hyperlink navigation between symbols, and assembly metadata explorer…
  • A console version, ilspycmd, can automate decompilation.
  • It can generate a PDB from an assembly. A PDB file, often referred to as a symbol file, is a bridge between an assembly’s IL code and its corresponding project’s source code. PDB is primarily used by debuggers to locate positions in source code, corresponding to the currently executed IL instruction. It means that with ILSpy PDB generation, one can debug the decompiled source code as explained in this stackoverflow answer.
  • It runs seamlessly on Mac and Linux thanks to AvaloniaILSpy. This is not the case for other decompilers listed after.
  • It integrates within Visual Studio and within VSCode (although the VS code version seems to have problems from the comments).
  • Since ILSpy version 8.2, it runs on .NET 6.0 compared to .NET Framework 4.7.2 for previous versions.

ILSpy is mature

ILSpy is actually so mature that Visual Studio itself relies on it to generate source code from .NET assemblies while debugging. You can also read Decompilation of C# code made easy with Visual Studio. This is a great feature when you don’t have access to the source code of a library that your code is consuming (the black-box syndrome). However, it is not recommended to reference closed-source libraries from your code as explained in the fifth lesson of 5x Lessons Learned from Migrating a Large Legacy to .NET 5/6.

ILSpy-Dotnet-Decompiler

Later in the present article, we explain how NDepend and ILSpy can collaborate to achieve powerful decompilation actions like:

  • Decompiling an entire assembly
  • Decompiling two versions of an assembly and diff the results
  • Generate dependency graph directly from the ILSpy element right-click menu

dotPeek for convenient decompilation   [free  C# IL]

dotPeek is the free decompiler by Jetbrains. It runs as a standalone. The tool also naturally integrates within Resharper and thus, within Visual Studio and Rider. It has ILSpy features listed above plus:

  • ILSpy search and navigation are great. However, imagine having the Resharper or Rider super-polished search and navigation features on decompiled code. It’s what you get with dotPeek!
  • IL Viewer panel (see the screenshot below) is quite useful. For each C# decompiled statement, the IL Viewer panel highlights the corresponding IL instructions. To us, this is very useful because we include IL Offset into our production stack traces. Thus with the dotPeek IL Viewer, we can quickly assess the culprit C# line from a production crash. Notice that ILSpy has an “IL with C#” decompilation mode. In this mode, each C# statement is shown as a comment preceding its corresponding group of IL instructions, but I find it less convenient than IL Viewer.
  • I like the dotPeek Process Explorer. It is quite convenient to spy any running process, list its .NET assemblies loaded, and decompile any of those assemblies in a click.

dotPeek has a downside though: on a beefy machine it takes 10 seconds to start. I guess it shares a lot of DLLs with Resharper which notoriously slows down Visual Studio startup. On the same beefy machine Visual Studio 2022 takes 11 seconds to open the 160 projects & 4.200 classes of the OrchadCore solution.

dotPeek-Dotnet-Decompiler

Why do we prefer ILSpy over dotPeek?

We used to rely on dotPeek for our regular decompilation. But the slow startup led us to use more and more ILSpy which is quite fast, not only for the startup but for decompilation as well. It is also reactive on all commands and has lightweight and convenient redistribution (3MB zipped to xcopy). Now I mostly use ILSpy and keep dotPeek for its Process Explorer and C# + IL Viewer features when needed.

dnSpy for gurus, security, and hackers   [free  OSS  C# VB IL]

dnSpy is the .NET Decompiler used by .NET gurus, experts in security, and hackers who want to have a bit-perfect control over a .NET assembly. The tool is open-sourced on github and is now (March 2023) maintained under the dnSpyEx branch. Just download the latest release to try it straight.

The screenshot below shows all the assembly metadata tokens and offsets that the mere-mortal .NET developer doesn’t need. Actually, dnSpy is much more than a decompiler. It can also run and debug a compiled assembly as shown by the screenshot below. The breakpoint set with F9 is just hit 2 seconds after pressing F5 to start debugging. What’s impressive is that the PDB generation step explained above is implicit and very fast. Note that dnSpy can also attach to a running process and debug the decompiled code of its assemblies!

dnSpy-Dotnet-Decompiler

As if it was not enough dnSpy is also an assembly editor. Thus dnSpy supersedes the tool Reflexil developed by my friend Sébastien Lebreton for editing IL.

dnSpy-assembly-edition

Who created dnSpy?

The mysterious creator of dnSpy – wtfsck on github – is the Grigori Perelman of decompilation. He/She? is also authoring the x86 (16/32/64-bit) disassembler icedland/iced and also the tool de4net the .NET Deobfuscator. In short for those that protect their IP with a .NET Obfuscator tool, the tool de4net is here to “try its best to restore a packed and obfuscated assembly to almost the original assembly. Most of the obfuscation can be completely restored (eg. string encryption), but symbol renaming is impossible to restore since the original names aren’t (usually) part of the obfuscated assembly.”. This is why when it comes to securing your code, in addition to using an obfuscator we recommend also having some serious in-house protection!

JustDecompile for everyone  [free  OSS  C# VB IL]  (continued as CodemerxDecompile)

JustDecompile is published by Telerik. As a matter of fact, JustDecompile is to Telerik what dotPeek is to Jetbrains: a free, powerful, and polished .NET Decompiler tool made by a leading tools & components corporation. These companies invested in their free decompilers to build an appealing entry point to their commercial products. The community benefits from the free tools with the maintenance level of large corporations.

JustDecompile is a polished and fast .NET Decompiler with most features mentioned in IL Spy and a plugin model. Its engine is open sourced on github but hasn’t been updated since 2019. In 2021 the project has been forked to OSS CodemerxDecompile on github. Here is the official website of CodemerxDecompile where you can download the Windows, Mac, and Linux versions.

If you wish to decompile to VB.NET and you find the dnSpy tool daunting with all its guru features, then JustDecompile/CodemerxDecompile is the right tool. Also, CodemerxDecompile claims to be the fastest .NET decompiler (I didn’t verify) so if you need performance it might also be the right choice.

JustDecompile-Dotnet-Decompiler

IldAsm for nostalgia  [free IL]

IldAsm.exe is the first .NET Decompiler ever. It was provided by Microsoft since .NET 1.0. Actually, it doesn’t decompile but just produces textual IL code from the binary IL code in a DLL. I used it extensively when I was learning in-depth .NET in the 2002-2003 years. I really felt some nostalgia when producing this screenshot 🙂

ildasm-Dotnet-Decompiler

.NET Reflector for history   [paid unsupported  C# VB IL MC++]

.NET Reflector by Red-Gate is the only both commercial and unsupported .NET Decompiler in this list. With its Buy Now button on its main page, it doesn’t look unsupported but in January 2021 I got this answer from the Red-Gate support: “.NET reflector is an unsupported tool. Support for .NET Reflector is limited to our help center and we encourage you to post on the Forum.”

Why mention .NET Reflector then since it cannot compete by any means with the free, supported, and powerful tools already listed? Because .NET Reflector is the father of all .NET Decompilers – and even dare I say – the father of most non-Microsoft .NET tools.

The history of .NET Reflector (worth reading)

Lutz Roeder originally developed .NET Reflector as a freeware. Its first version can be traced back to July 2002 during .NET infancy! Lutz is a seasoned Microsoft engineer and researcher. He developed the tool in his spare time. .NET Reflector was a super popular tool. Red-Gate acquired it in August 2008. Reg-Gate is a leading DB tool vendor that also proposes tools for .NET developers. They promised “to continue to offer the tool for free to the community” and only charge for new features. Unfortunately, they broke their promises: in February 2011 they ran into a storm of protest when charging for .NET Reflector. This led to the creation of several free alternatives, including dotPeek, JustDecompile and ILSpy. Sad story, fortunate consequences: it led to a plethora of high-quality free decompilers which is great.

.NET-Reflector-Dotnet-Decompiler

NDepend to go beyond decompilation

We created NDepend in April 2004 as a small OSS project to compute some Robert C. Martin metrics on .NET projects to show clients when consulting. The tool was popular enough to create a commercial version in February 2007 and commit to it full-time. The tool evolved a lot. Nowadays it is still fully supported and up-to-date with the latest .NET technologies.

NDepend is not a decompiler like the ones above. Its main source of data are assemblies and IL code but it can also read PDB files, source files, .csproj/.sln files, and even code coverage files produced by various coverage technologies. The tool analyzes all this data to build a rich and queryable model of your .NET assets. Numerous features and use cases are based on this model:

Explore your Code

An NDepend full-featured trial can be downloaded to assess your .NET code quality and structure or reverse-engineer any mysterious .NET DLL. Here the dependency diagram is obtained in 4 seconds (analysis + graph layout) from the ScreenToGif.exe assembly.

ndepend-dotnet-decompiler

NDepend and ILSpy collaboration: .NET decompilation on steroid

Since 2022, NDepend has proposed an ILSpy plugin. This way the tools are collaborating both ways:

From NDepend to ILSpy

Just right click any assembly, namespace, class, method or field in NDepend or Visual Studio (with the NDepend extension installed). There are 3 new menus to:

  • Select the code element in ILSpy
  • Decompile the code element with ILSpy (Target languages: C# and IL)
  • Decompile and Compare: the code element is decompiled from both the baseline assembly and the current assembly and both text files obtained are compared. It is possible to decompile large namespaces or even assemblies. This is especially useful to diff two versions of an assembly. If several classes are decompiled, they are aggregated in the text file in a consistent order, which makes the code review of changes possible.

ILSpy-Decompile-And-Compare

Let’s mention that to compare two sets of assemblies – older bits and newer bits – in order to use the Decompile and Compare menu, just click the Compare 2 versions of a code base link from the NDepend start page. A dialog will let you specify both assemblies sets to compare.

Compare-2-Versions-Of-A-Codebase

ILSpy is a fast decompiler. But decompiling dozens or hundreds of classes can take a few seconds or minutes. This is why a progress dialog appears with an Abort button.

ILSpy-NDepend-Decompile-ProgressBar

From ILSpy to NDepend

It is possible to:

  • Show any code element on the NDepend dependency graph or matrix
  • Analyze with NDepend one or several assemblies selected

ILSpy-to-NDepend

Conclusion

I hope this post was useful to you in deciding which .NET Decompiler suits you best and maybe change your habits. Each tool is mature and has its own enthusiast users. Probably you’ll end up using ILSpy or dotPeek, or maybe dnSpy if you have a need for bit-level details. We explained why ILSpy is the .NET Decompiler tool we use regularly and keep dotPeek at hand when needed. This is genuine and we are not affiliated with the ILSpy team nor Jetbrains, the editor of dotPeek, which is free anyway.

But, wait a minute…

Is decompiling legal?

The short answer is: Yes unless explicitly prohibited. For example, the dotPeek License Agreement states that: “Before using dotpeek for decompilation purposes, you should make sure that decompilation of binary code is not prohibited by the applicable license agreement (except to the extent that you may be expressly permitted under applicable law) or that you have obtained permission to decompile the binary code from the copyright owner.”

The StackOverflow answer

This stackoverflow answer proposes a more liberal discourse:

“Decompiling is absolutely LEGAL, regardless of what the shills say. At most, you can be sued for unauthorized activity relating to software unless you’re redistributing it. Courts in the U.S. have always upheld the right of users to know exactly what code is being installed on their systems by programs they have legitimately obtained.

People REALLY need to quit saying “ILLEGAL” unless they know what they’re talking about. There is absolutely NO law in the U.S. that states you cannot copy for private purposes or decompile software. Companies have tried to sue to stop it, but; a) that’s only civil, not criminal, and therefore not ILLEGAL; and b) they’ve only won when the content was given to an outside party from whom the companies did not receive payment. IE the person has been shown to break the law.”

Nevertheless, a comment on the same question says: “It is, however, illegal if you decode it, take all the source code, maybe change the graphics, package, and some other things and try to pass it off as your own app. It is illegal redistribution of a copyrighted work.”

Protect your Intellectual Property

.NET Obfuscators exist since technically nothing prevents anyone from reverse-engineering your intellectual property. But understand that obfuscators and custom tricks cannot protect your IP from a determined hacker. At best, you can make the hacker’s life (much) more difficult. The only way to really protect your IP is to propose your services through a cloud or web-based approach, where your bits never leave your own server.

 

 

 

Comments:

  1. Nice article Patrick, very useful, thank you.
    Perhaps you have some ideas to share regarding to kinds of those custom protection tricks?

  2. Patrick Smacchia says:

    Glad you find the article useful Sergio!

    >Perhaps you have some ideas to share regarding to kinds of those custom protection tricks?

    I wrote about that in this post. The best you can do is to multiply your in-house & tricky DLL integrity checks to discourage most crackers to lose their time. I wrote about this here:
    https://blog.ndepend.com/dont-rely-on-someone-else-to-protect-your-software/

  3. Red Gate got greedy when it charged money for Reflector. I am glad we have free and better alternatives.

  4. Hi Patrick, great writeup! How did you come to know that Grigori Perelman is the creator of dnspy? Dnspy is a perfect production debugger where you can debug any .NET application without source code. I was shocked to see that it was archived but as you pointed out work seems to continue now.

    1. Patrick Smacchia says:

      Hi Alois, the reference to Grigori Perelman…
      “The mysterious creator of dnSpy – wtfsck on github – is the Grigori Perelman of decompilation.”
      … is because I found this project absolutely impressive by ay mean size, feature, performance… and it is free & OSS!!

      It reminded me the work done by GP that rejected the prize of one million dollars offered by the Clay institute for having demonstrated the Poincaré conjecture https://en.wikipedia.org/wiki/Grigori_Perelman

Comments are closed.