Foo Infusion

A periodic infusion of foo from the world of a junior developer

Tuesday, August 14, 2007

Dofuscator, Reflection, .NET Properties, and Attributes....

Recently the team I work on encountered some buggy behaviour that only exhibited itself in the obfuscated build, leading us to believe the bugs were a result of the obfuscation.

It was discovered that Dotfuscator's 'Library Mode' setting was to blame for the bugs.

From Dotfuscator's user guide:

Library Mode By Assembly

This setting tells Dotfuscator that a particular input assembly constitutes a library. (For Dotfuscation purposes, a library is defined as an assembly that is going to be referenced from other components not specified as one of the inputs in this run) This has implications for renaming and pruning, regardless of any custom excludes you may have set.

Here are the rules when using the library option:

1. Names of public classes and nested public classes are not renamed.
Members (fields and methods) of these classes are also not renamed if they have public, family, or famorassem access.

2. In addition, no virtual methods are renamed, regardless of access specifier.
This allows clients of your library to override private virtual methods if need be (this is allowed behavior in the .NET architecture).

3. Any user-specified custom renaming exclusions are applied in addition to the exclusions implied by the above rules.

4. Property and Event metadata are always preserved.

5. Pruning Rules. Public classes are not removed, even if static analysis determines they are not required. Fields of these classes are not removed if they have public, family, or famorassem access. Methods of these classes are not removed if they have public, family, or famorassem access. In addition, such methods are treated as entry points, so their call trees are followed and all subsequently called methods are also protected from removal.



If you do not have the library option set for an assembly, then you are telling Dotfuscator that your input assembly is a standalone application, or that it will only be referenced by other input assemblies. In this case obfuscation is much more aggressive:

1. Everything is renamed except methods that override classes external to the application (i.e. classes in assemblies that are not included in the run.)

2. Property and Event metadata is removed, since this metadata is not required to run the application (it is meant for “consumers” of library code).

3. As usual, user specified custom renaming exclusions are also applied.

4. Pruning Rules Specifically included classes, methods, or fields are not pruned. All trigger methods and fields are not pruned.



All classes, members, and fields that are excluded from renaming also become excluded from pruning. All other classes, fields and methods that are unreachable from some included class, method, or field are pruned.



We have some stuff built to make serializing a class to XML easier and more automatic. It uses three VB.NET concepts to accomplish this : .NET Properties, property attributes, and Reflection.

The XML serializer inspects an object using reflection, asking for a list of all 'properties', and then cycles through the list looking for properties which have the special XML serialization attributes (these are called annotations in Java).

When Dotfuscator was using 'Library Mode' on the assembly, there were no problems, as the 'property metadata' was preserved.

When Dotfuscator was not using 'Library Mode' on the assembly, the obfuscated assembly no longer contained the 'property', but rather had the property split up into the corresponding 'get' and 'set' methods. In this case, the XML serializer's call to the object for a list of properties returned an empty list as they were no longer considered properties but methods. Thus, the XML serializer didn't work very well.

I think I've determined that in our case there aren't any real negative consequences to using 'library mode' other than the obvious (but likely, slight) reduction in actual obfuscation.

If you're doing anything that combines using .NET properties for storage and you're relying on that special 'property' structure to be maintained through to the other side of the obfuscation, you need to obfuscate your assembly using Dotfuscator's 'library mode'.

In the Professional edition like we use, this property must be set (or not) on each assembly individually (as opposed to the Community edition, in which you set it for all assemblies or none).