In this article I will explain our genuine experience with various .NET Obfuscator Tools. We end up explaining that .NET Reactor is the one we choose to obfuscate our code for various reasons: reliability, support, seniority, cost and obfuscation options.
There are actually dozens of .NET Obfuscator as listed here obviously we didn’t try them all. Many of these projects are abandoned anyway. On a side note it is surprising to see so many attempts. I guess building an obfuscator is a task considered both fun and not too complicated given reader/writer IL libraries like the Mono.Cecil project. Experience shows that building an obfuscator that works – I mean that obfuscates the code properly without introducing bugs in the obfuscated code – is difficult: .NET Obfuscators that work are more the exception than the rule.
A rule of thumb for web content is to remain positive and don’t harm anyone. Online bashing and hassle is a waste of time, shows a negative image and never outcome to anything productive. However in this post I will explain that some obfuscators were genuinely not the right choice for us for various reasons. Keep in mind that each mentioned product has some real-world users that are happy with it. Also prior publication, the present post has been submitted to each product-owner listed here to make sure everything written is correct.
For more than a decade we relied on Preemptive Dotfuscator to obfuscate our code. Since the early days of .NET in 2002/2003 Microsoft promoted Dotfuscator for .NET users that wanted an obfuscator. My guess is that Microsoft never had wanted to provide a .NET obfuscator. In the early days of .NET, the developers coming from C++ and VB6 didn’t realize straight away that with the new .NET platform their IP was now exposed crystal clear to everyone. This is an aspect of .NET that was seen as a regression compared to C++ and VB6.
Until now our code was .NET 4.0 and .NET 4.5 and Dotfuscator just worked. As a consequence an older version of Dotfuscator was sufficient. However we migrated to .NET 4.7.2, .NET 5/6/7 and .NET Standard and we needed an up-to-date obfuscator that can handle the latest .NET flavors. Dotfuscator can certainly do that (not verified). However in 2021 they changed their subscription price policy with a 25% increase every year with no real added value and there seems to be no upper limit. In the end that literally multiplies the yearly fee we used to pay for a decade.
Preemptive Dotfuscator is a product that works. It is normal to pay a yearly subscription for support and an up-to-date product. However the increasingly high yearly fees is a greedy policy we refused. If we accept these conditions now, we will end up paying an unbounded and uncontrolled fee later. This is not sane and we decided to explore alternatives.
As a lesson learned, keep in mind that if you go with this product you might be well end up in a similar situation.
Eazfuscator.NET has a good reputation, has a very affordable pricing and has lots of fans online. We tried it but figured out that the tool does not provide mapping files. Mapping files of assemblies generated by Dotfuscator make it possible to decode production stack traces, which is essential to track production problems and fix them.
Instead, Eazfuscator.NET encrypts obfuscated symbols with a private key. Thus production stack traces can be decoded with the private key. At first sight this is pretty cool. However there are two significant problems with this approach.
- Encrypted symbols are available publicly. We talked with the author of Eazfuscator.NET and he is pretty certain that encrypted symbols cannot be cracked (which doesn’t sound serious in a mouth of a security expert). Nevertheless this approach is objectively less secure than the mapping file approach where symbols released in the wild have nothing to do with the original ones. Here is a quote on the page of de4dot – a tool to reverse-engineer obfuscated code “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”. Let’s underline that de4dot doesn’t crack Eazfuscator.NET encrypted symbols but the message is clear. However this post DECRYPTING EAZFUSCATOR.NET ENCRYPTED SYMBOL NAMES shows well that a private password based system to secure symbols is much less secure than a private mapping of obfuscated symbols.
- Encrypted symbols size is correlated with the original symbols size. The author claimed that the size is roughly similar. We tend to use large symbols to make our code comprehensive. An additional bonus we had with a mapping file approach is that our assemblies size reduced significantly (10 to 15%) because symbols like “NDepend.Platform.DotNet.VisualStudio.VisualStudioEditionHelper” were shortened to something like “B6U”. NASA sent men on the moon and back in 1969 with 4KB RAM. I used to program my first micro games with a 4KB RAM computer too in the 80’s. Today mobile phone flashlight apps usually weight 10 to 20MB. Call me old-fashioned but I am quite unhappy with this bits inflation. 10/15% less bits in our redistributable matter.
The Eazfuscator.NET author underlined that “On the positive side there is no state in contrast to the stateful nature of mapping files. If you create frequent releases on a variety of build machines this may be a good point for you as it makes things easier”.
He also added that there is no immediate plan for mapping file. Unfortunately this means that Eazfuscator.NET was not the right choice for us.
Same as Eazfuscator.NET, Babel has a good reputation and a very affordable price. It also has the mapping file feature. It looked pretty promising. Unfortunately despite many hours and a lot of discussion with the author to try to make it work on our assemblies, we didn’t obtain a working obfuscated version.
The tool works fine for many other applications so it might work for you. Unfortunately it didn’t for us.
Unfortunately despite trying hard we never succeeded in generating a bug-free version of our code. It has some well known flaws like throwing some TypeLoadException on some overriden methods that we were experiencing. This other issue also was a blocker unless we accepted to not obfuscate all our enums.
I had the chance to discuss with Lex Li, one of the main contributor on Obfuscar over the years and his stance is :
“Obfuscar does have a few design flaws which I was trying to fix but unable to fully address. However, I noticed a fork https://github.com/
We didn’t bother trying the open-source obfuscator ConfuserEx since it hasn’t been touched for years and the project is officially discontinued and unmaintained. The project forked to neo-ConfuserEx that also hasn’t been touched for years either.
What struck me positively first is that its UI is full of tooltips and also contains many links to a massive documentation. The best UI is the one that can be understood intuitively. But for complex enough tools – like an obfuscator – some embedded feature descriptions are welcome: for example I appreciate that when I select the setting “Public Types Internalization” this description is immediately shown to me “If enabled, .NET Reactor will convert all public types of an application into internal ones. This way the accessibility of types and members is reduced”. This way this is all clear and there is no need to go to the online documentation or ask support.
We have the same approach with the NDepend online and embedded documentation. Personally I don’t like to be stuck on a setting or a behavior not well documented. I consider that ISV are not here to sale support but to build solutions that seamlessly solve problems and bring value. More on this digression can be read in You Should Favor Software Products That Include Support in the Price.
.NET Reactor didn’t work straight for us. Generated assemblies had some problems with some resources unavailable once obfuscated. A few override method names were not obfuscated also. Nevertheless we did a few roundtrip with the author until the obfuscated version generated totally bug-free code for our application. The support we received was reactive (no pun intended) and smooth. And we now have a solid obfuscation process with seamless support, for not even 5% of what we used to pay with Dotfuscator.
One key aspect of obfuscators neglected in this post is the various extra protection features like virtualization, string encryptions, anti-tampering… Again it is recommended to do some in-house/custom protection. Keep in mind that some project exists like the aforementioned de4dot tool to reverse-engineer code generated by popular obfuscators.
Everything exposed in this post is genuine and there is no hidden goal to promote .NET Reactor and criticize other mentioned products.
Again quoted obfuscator that didn’t work for us might work for you. Moreover there are certainly other .NET obfuscators out there that do the job well and that we didn’t touch.