Dotfuscator renames all classes, methods, and fields to short, meaningless names. This process makes decompiled output much more difficult to understand and reduces the size of the resulting executable.
Most commercial obfuscators apply trivial identifiers as short as a single character. As Dotfuscator processes your code, it selects the next available trivial identifier for substitution. This renaming scheme is irreversible; while the program logic remains intact, the names become nonsense to anyone attempting to analyze the code.
Overload Induction
Dotfuscator employs a patented technique called Overload Induction™. Instead of substituting one new name for each old name, Overload Induction renames as many methods as possible to the same name. This deep obfuscation renders the logic incomprehensible to humans.
The following example illustrates the power of the Overload Induction technique:
- Original source code before Obfuscation:
private void CalcPayroll(SpecialList employeeGroup) {
while (employeeGroup.HasMore()) {
employee = employeeGroup.GetNext(true);
employee.UpdateSalary();
DistributeCheck(employee);
}
}- Reverse-engineered source code after Overload Induction Obfuscation:
private void a(a b) {
while (b.a()) {
a = b.a(true);
a.a();
a(a);
}
}Renaming compacts your application. If a name is 20 characters long, renaming it to a() reduces its size by 95%. Renaming also saves space by conserving string heap entries. When you rename multiple items to a, Dotfuscator stores the identifier only once.
There are several distinct advantages to this methodology:
- Renaming makes decompiled output difficult to understand. Renaming to unprintable characters or illegal names in the target source language is futile since decompilers are equipped to re-rename such identifiers. Considering that Overload-Induction could make one of three method names "
a()", understanding decompiled output is difficult. - Overload-Induction has no limitations except those that exist in all renaming systems.
- Since overload-induction tends to use the same letter more often, it reaches into longer-length names more slowly (e.g.
aa,aaa, etc.). This also saves space.
Overload-Induction's patented algorithm determines all possible renaming collisions and only induces method overloading when it is safe to do so. The procedure is provably irreversible. In other words, it is impossible (even via running Overload-Induction again) to reconstruct the original method name relationships.
Enhanced Overload Induction
Dotfuscator also provides Enhanced Overload-Induction™. This allows a method's return type or a field's type to be used as a criterion in determining method or field uniqueness. This feature provides up to 15% more redundancy in method and field renames. In addition, since overloading on method return type or field type is typically not allowed in source languages (including C# and Visual Basic), this further hinders decompilers.
Limitations
Review the following limitations before enabling renaming:
XAML Assemblies: Dotfuscator does not perform Overload Induction on assemblies containing XAML code due to runtime linking requirements. The Use Enhanced Overload Induction option does not change anything for such assemblies.
Reflection and Configuration: Renaming may cause issues if your application uses any type of reflection, configuration files with entry points, or libraries accessed by external applications.
Xamarin.Android: You must use only Lower Alpha or Upper Alpha renaming schemes for Xamarin.Android builds.
Testing: You must fully test your application after enabling renaming to ensure all references update correctly.
See Renaming scheme for more information.
Specific Exclusions
Presuming Library Mode is turned off, Dotfuscator tries to rename everything it possibly can. Certain uses of reflection can cause Dotfuscator to not update all references to a particular entity upon renaming. In the following example, four classes and their fields are excluded:
The application references these types and members by looking up their names via reflection. If they were to be renamed, the application would be unable to find them at runtime. Therefore, they are excluded from renaming via these checkboxes.
Custom Exclusion Rules
There may be times when you need to make many specific exclusions for a particular coding convention. And even then, when a developer adds more code that follows that convention, they would have to remember to make yet another specific exclusion for their new code.
The solution to this is Custom Exclusion Rules. Using the previous example, let's say you figured out that all types with names ending in "Dungeon", and specific types of fields within those types, need to be excluded from renaming for some reason. Rather than creating a bunch of specific exclusions, you can make one custom rule as follows in the Renaming editor:
Add the rule's root node by clicking the Add Type button.
Enter
.*Dungeonin the Name field.Check the Regular Expression (regex) option to indicate that the name should be treated as a regular expression. This way the node matches types whose names end in "Dungeon".
Check the Exclude Type (excludetype) option to exclude matching types. If you do not select this option, the types that match are not excluded from renaming - only the members specified by their child nodes.
Add a child node by right-clicking the root node and selecting Add Field.
Name the child node
.*and indicate that it should be treated as a regular expression.- Restrict the rule to only cover fields which have the public access modifier (by setting
+public), and whose signature isstring[], as both are necessary in this scenario.
Once you configure a rule, you can select a node and click the Preview button. Dotfuscator highlights the entries that match your custom rule in the tree view on the left. You can see the rule on the right pane.
In this example, when previewing the child node, fields that match the criteria are highlighted. Notice that the Keys field in AdventureGame.Validation is not excluded, because while it matches this child node, its parent type does not match the parent node (the class name "Validation" does not end in "Dungeon").
The resulting configuration of this custom rule is stored as XML in the config file. This example produces the following config XML:
<type name=".*Dungeon" regex="true">
<field name=".*" speclist="+public" signature="string[]" regex="true" />
</type>
Built-In Rules
Built-In Rules are Custom Exclusion Rules that are fairly universally useful; Dotfuscator includes them by default so users do not have to re-implement them.
You can find the exact definitions of each of these rules in an XML file with a name beginning with dotfuscatorReferenceRule in your installation location's Common subdirectory. A typical example is C:\Program Files (x86)\PreEmptive Protection Dotfuscator Professional A.B.C\Common.
For example, Methods with System.Web.Services attributes translates to the following custom rule:
<excludelist>
<type name=".*" regex="true" excludetype="false">
<comment>Exclude all methods that are decorated with attributes from the System.Web.services namespace.</comment>
<method name=".*" regex="true">
<customattribute name="System.Web.Services.*" regex="true" />
</method>
</type>
</excludelist>
Options
For more information on renaming options, see Renaming Editor.