We already explained the need for and basics of obfuscation, and yet developers I meet are often still surprised to discover how easy it is to decompile their .NET application and obtain the original source code back from the released .NET assembly DLL. We can add new information on this topic and present details on some available tools now, because Greg Wesner of Autodesk kindly agreed to share his personal experience and research results using obfuscation with Revit applications:
First of all, here is a list of most of the available obfuscators with some additional background information and further links.
I gave up on Dotfuscator because I was having problems obfuscating things for Revit and their interface was not very good. You have to exclude from obfuscation any methods that external apps call into or access. This would include entry points like IExternalCommand and IExternalApplication methods. Virtually any DLL can be obfuscated to the point where it will not run.
I now use {smartassembly} which is working quite well for me. It’s in the medium price range of the tools out there. It does a fairly good job of drilling into the dependencies itself and determining what can and cannot be obfuscated. Setting up the various options in these tools will make all the difference.
To be honest, what really sold me on {smartassembly} was the fact that their trial software was a fully functional installation of their product. You just can’t ship what you obfuscate until you pay for it. Dotfuscator and another one I tried from Rustemsoft called Skater were both limited versions of their software, so it was very difficult to determine how effective they would be. Skater in particular did not do a very good job of string mangling and the result was barely different from the code. If you are going to provide an evaluation copy, is it really a good idea to limit it to the point that it is unimpressive?
Here are some cool features in {smartassembly} beyond obfuscation:
- It can merge in dependent DLLs or embed them. Merging them will improve performance, embedding them just makes it more convenient, because your deliverable can be just one file.
- It will prune code that will never get executed. Actually, I find this to be a nice analysis tool for applications that are developed over long periods of time – I’m amazed at how much code I write that I eventually end up abandoning.
- It will add confusing metadata to the DLL so that .NET Reflector and MS IL Disassembler cannot view it. This is a huge advantage because now you need hacking tools even to see what methods are exposed, and this provides a level of protection for even those methods that you could not obfuscate.
- It will sign your assembly with a strong name after obfuscation.
- It has some memory optimizations that can improve memory usage, which I have not tested.
My approach in setting up my projects was to enable all the security features I could to make it as safe as possible. Then obfuscate the DLL and load and test it. As I mentioned, {smartassembly} does a fairly good job of realizing that some methods are entry points for the DLL and it cannot mangle those signatures. A couple of times I ended up with an obfuscated DLL that would not run. So from there I went back in and began disabling features. I start by excluding whole classes from obfuscation. Once I find the class or classes that cannot be mangled, I try drilling down to see if there are just some particular methods that need to be excluded. This is all I have really needed to do to get it working for me.
I also considered .NET Reactor. The price is really competitive and it has the added feature of creating time bombed versions of your software. But a review I read said it had difficulty with complex applications.
I would have liked more time to evaluate this to determine if it would have worked for me. I highly recommend trying out more than one of these tools before making a decision.
Obviously, these are just unofficial personal opinions, like everything else stated in this blog.
Hello Jeremy – full disclosure – I am a NON-technical employee at PreEmptive Solutions (we make Dotfuscator). I read your blog entry with interest and it raised a few questions for me and also prompted me to write this post.
Now, I realize that you are using (and are satisfied) with another tool – I am not trying to fix something for you that is apparently not broken – but you are obviously putting time into this area and I would hate to have you end up with any misinformation about Dotfuscator.
The first comment that caught my eye was that the Dotfuscator evaluation version was functionally incomplete – in fact, other than requiring a network connection and the deactivation of the command line interface (perhaps this is the feature that you wanted to test?) – the evaluation version is fully functional.
Is it possible that you were using the Community Edition (CE) that is included with Visual Studio? CE is the limited edition of Dotfuscator – but it is not an “evaluation” of the commercial edition – it is simply a lite-weight obfuscator included with Visual Studio.
The observation that you “have to exclude from obfuscation any methods that external apps call into or access” is true for renaming but not control flow (for example). But, more to the point, this renaming constraint would be true for any implementation of renaming – were you under the impression that you had to manually exclude these one at a time with Dotfuscator? (that would be annoying!)
The commercial version of Dotfuscator (The Suite) includes a “library mode” that leaves all entry points alone automatically. PLEASE NOTE – if you have multiple assemblies that call one another (all yours) but do NOT need to publish the calls to OUTSIDERS – Dotfuscator also supports cross-assembly renaming – it will take in multiple assemblies and impose a consistent renaming scheme across them all. This is true even if you add assemblies to the mix AFTER the first obfuscation session at a later date (good for incremental updates, patches, distributed development environments, etc.).
I realize that you gave up on Dotfuscator and so you may not have had the opportunity to evaluate all of these functions, but for completeness – here are my comments on some of the other capabilities you highlight:
The Dotfuscator Suite can:
1. Merge in dependent DLLs or embed them.
2. Prune code that will never get executed.
3. Add confusing metadata to the DLL so that .NET Reflector and MS IL Disassembler cannot view it.
CAUTION – there are easy ways to make this appear more effective by adding INVALID metadata – HOWEVER, the resulting output application will not peverify. If ensuring that your assembly is a verifiable .NET assembly – then this can kill your application (even if all of your QA tests are positive). Control flow obfuscation will also defeat Reflector, etc. – but does NOT output invalid IL.
4. Sign your assembly with a strong name after obfuscation.
Now, as I “disclosed” upfront – I am not technical (I am in marketing), but I would be more than happy to connect you to our live customer support. Again, I am curious – did you evaluate the Community Edition and not The Suite? Did you ever contact our support organization with these issues?
If you are interested in following up with me offline (or get connected with more technical resources), please do feel free to contact me directly at [email protected].
Thank you,
Sebastian.
Posted by: Sebastian Holst | August 30, 2009 at 11:08
PS – the hazards of posting to a blog too quickly – as I re-read your last post, I see that the comments I responded to were from Greg Wesner and not from you directly – apologies - my offer of assistance of course stands – and if you could please pass my questions on to him, that would be terrific. Thanks very much. Sebastian
Posted by: Sebastian Holst | August 30, 2009 at 15:05
Dear Sebastian,
Thank you for the clarification. Yes, I know the hazards of posting too fast all too well. I'll point out your comments to Greg, and I am sure they are also of interest to anyone else following this thread.
Cheers, Jeremy.
Posted by: Jeremy Tammik | August 30, 2009 at 15:37
Just started looking at this. Using Dotfuscator CE v4.0.2008.10000... Getting "Build Error" message with no input as to what is causing the error! How can we use the product if there is no feedback on what is causing the error? The project compiles perfectly through VS 2008.
Posted by: Jim Bish | October 05, 2009 at 14:07
Did you evaluate Crypto Obfuscator? http://www.ssware.com/cryptoobfuscator/obfuscator-net.htm
It is a lot cheaper but still has all of the features found in others, as well as some unique ones like Anti-Debug, Anti-Tamper, etc.
Posted by: LogicNP | February 15, 2012 at 00:32