.NET Native; what’s it mean for obfuscation and Dotfuscator in particular
Published on October 28, 2015 by Sebastian Holst
I recently got a question from a client asking why .NET Native (the process of transforming a .NET assembly into a native app to improve performance) did not also make products like Dotfuscator irrelevant. Here’s my response (with personal details removed of course).
First, the .NET Native process is only applicable to Universal Apps distributed through a Microsoft marketplace. If you are developing .NET (using VS2015 or anything else) BUT are targeting anything other than a Universal App architecture – .NET Native does not apply – also, if you’re developing in F# – even if Universal – .NET Native does not apply.
Here’s an excellent blog post from MSFT on this: .NET Native – What it means for Universal Windows Platform (UWP) developers.
While this probably eliminates most dev organizations in the near term, lets assume that a dev organization is fits into this narrow scenario. Let’s focus on comparing obfuscation to native-generation when both are available.
First, there is no doubt that many app dev teams that might have needed an obfuscator to prevent reverse engineering of their apps back into C# will no longer have that requirement.
However, .NET Native is a performance optimizer – NOT an app security tool – and so (while there is most certainly overlap) the two are not synonymous. For example,
- One would not expect to see string encryption happen inside the .NET Native generation process (and sometimes that is all a bad actor is trying to look at)
- None of this addresses “detective controls” (triggering defensive behaviors when an app is tampered with for example) Note – while not technically an “obfuscation transform” this is a feature included with Dotfuscator for non-universal apps.
- When components run on a device as a universal app AND share function calls/name spaces, etc with non-universal components – cross-assembly renaming/obfuscation is still required for the non-universal components and then must be extended into the universal app when they need to interoperate. This can also apply when libraries are distributed across multiple dev organizations – that may not even be part of the same org and so the “protection” is on the library against library dev users.
Our view is that dev orgs should first assess what risks matter to them (not a technical metric) and then take appropriate steps to mitigate ONLY those risks – and for many (but not all) who develop exclusively standalone universal apps distributed through a MSFT marketplace (the VS2015 .NET Native generator in VS2015 is only for your testing – it’s the MSFT marketplace that ACTUALLY does this transform in production) – the .NET Native process will have the added benefit of eliminating the need for a commercial obfuscator. …BUT, there are many scenarios that will not fit neatly into this construct.
PS as a “fun fact” – PreEmptive’s first obfuscation product was for Java (it pre-dates the existence of .NET) and is (still) called DashO (“-o” is the “optimize” command for Java). So yes, the first obfuscator began its life as an optimization tool in the 1990’s – firmly establishing the the connection between optimization and obfuscation – but that does not make them synonymous.
Another “fun fact”, a large part of why MSFT asked us to build the .NET obfuscator in 2002 was because (prior to .NET) MSFT was a Java obfuscation client of ours.