PreEmptive Protection - Dotfuscator 4.31
User Guide

Configuration File Reference

Dotfuscator configuration files may have any name or extension, but usually have a .xml extension. Configuration files contain information about how a given application is to be obfuscated. The configuration file is an XML document conforming to dotfuscator_v2.4.dtd (or one of its predecessors), referenced in the appendix.

This section documents Dotfuscator’s XML configuration file. It contains detailed descriptions of each configuration option, making it useful as a reference, even if you are using Visual Studio, the standalone GUI, or the command line interface to generate a configuration file for you.

Version

The .xml file version attribute must be present and must be applicable to your version of Dotfuscator. It should match the version number of the DTD to which it conforms. Point releases of Dotfuscator are designed to be able to use unmodified configuration files from earlier versions. For example, you should be able to run Dotfuscator 1.1 using a version 1.0 configuration file without having to edit the configuration file.

Note: The configuration file version is not always the same as the version of Dotfuscator. Every version of Dotfuscator expects to see a specific, but not necessarily identical, version of the configuration file.

Version:

<dotfuscator version="2.2">

Property List and Properties

The optional <propertylist> section allows for the definition and assignment of variables known as <properties> that may be used later in the configuration file. Property definitions defined in this section are referred to as internal properties.

Internal Properties:

<!-- define expandable properties -->
<!-- optional -->
<propertylist>
  <property name="projectname" value="myproject"/>
  <property name="projectdir" value="c:\myprojects"/>
</propertylist>

Variables, or property references, may be used in the configuration file without being defined in this section. For example, they may be defined on the command line or come from the environment. Properties work via string substitution, using the following algorithm to find a value associated with the property:

  1. Check the external property list for a value.
  2. If not found, check for an environment variable with the same name as the property,
  3. If not found, check for an internal definition in the propertylist section of the configuration file,
  4. If still not found, use the empty string as the value.

External properties are passed in on the command line using the –p option. There are three built-in external properties:

  • applicationdir, which reflects Dotfuscator’s installation directory.
  • appdatadir, which reflects Dotfuscator’s local data directory.
  • configdir, which reflects the directory in which the configuration file resides.

Properties are useful for creating configuration files that act as templates for multiple projects, for different versions of the same project, or for simple portability across different build environments. A property is referenced with the following syntax:

Property Syntax:

${property_name}

Property references are case sensitive, therefore ${MyProjectDir} references a different property than does ${myprojectdir}. Currently, property references may only be used as values in the dir or name attributes of the <file> element, and not just anywhere in the configuration file. Here is a list of sections that use the <file> element:

  • inputassembly
  • mapinput
  • mapoutput
  • output
  • tempdir
  • assembly
  • removalreport
  • transform
  • key
  • loadpaths
  • program
  • filelist
  • smartobfuscationreport
  • pfx

A property reference is interpreted literally in any other place in the configuration file. Property references may not be nested as doing so results in an error.

Here is an example of a property reference in use:

<output>
  <file dir="${testdir}\output"/>
</output>

Global Section

The optional global section is for defining configuration options that apply across the entire run. This section describes each global option in detail.

Note: Global options are not case sensitive.

Library Global Option

This option was deprecated in Dotfuscator 3.0. It has been replaced with a more granular library option that can be applied to individual input assemblies. When reading older configuration files, Dotfuscator reads this option and honors it, but the user interface saves the configuration file using the new options. See Library Mode By Assembly.

Library Global Option:

<global>
 <!—set library option -->
 <option>library</option>
</global>

Verbose, Quiet, and Investigate Global Options

These options are the same as the corresponding command line options. Setting the command line option sets the global option at run time. Alternatively, if the global option is set and the command line option is not set, then the global option takes precedence. In other words, there is no way to unset a set global option from the command line.

Verbose, Quiet, and Investigate Global Options:

<global>
 <!-- run in verbose mode -->
 <option>verbose</option>
 <!-- run in quiet mode -->
 <option>quiet</option>
 <!-- investigate only and generate a map -->
 <option>investigate</option>
</global>

SuppressIldasmAttribute Global Option

Setting this option tells Dotfuscator to prevent Microsoft's Ildasm utility from displaying the assembly IL. This is only valid for assemblies targeting .NET 2.0 and above.

SuppressIldasm Option:

<global>
   <option>suppressildasm</option>
</global>

Debug Global Option

Setting these options tells Dotfuscator to create a symbol file in PDB format for each output assembly. Debuggers use these files to provide useful information in a debugging session. Typically, they contain information such as line numbers, source file names, and local variable names. The PDB files are placed in the output directory with the output assemblies.

This option is useful for assemblies that already have associated PDB files (i.e. you told your compiler to generate debugging symbols). In this case, Dotfuscator uses information in the original PDB file to create the new PDB file for the obfuscated version. In this case, the line numbers and source file names correspond to the information in the original assembly.

If an input PDB file is missing, then the PDB files created by Dotfuscator will contain line numbers that correspond to the low level Microsoft Intermediate Language instructions in the obfuscated assembly.

Debug, Debuglmpl, DebugOpt, and Pdb Global Options

<global>   
   <!-- Disable JIT optimization,create PDB file, use sequence points from PDB -->
   <option>debug</option>
   <!-- Disable JIT optimization,create PDB file, use implicit sequence points -->
   <option>debugimpl</option>

   <!-- Enable JIT optimization, create PDB file, use implicit sequence points --> 
   <option>debugopt</option>

   <!-- Create the PDB file without enabling debug info tracking --> 
   <option>pdb</option>
</global>

DebugImpl, DebugOpt and Pdb global options are supported for assemblies targetting .Net 2.0 and above. If these options are used with assemblies targeting .Net 1.0 or 1.1, Debug global option will be used instead.

NoDotfuscatorAttribute Global Option

Dotfuscator, by default, inserts a custom attribute into your application named DotfuscatorAttribute. The attribute contains information about the Dotfuscator version used to obfuscate the program, including product ID (CE vs. PE) and version numbers. The purpose is threefold:

  • To identify which Dotfuscator version was used on a program.
  • Future Dotfuscator versions will use this information to identify already obfuscated third-party assemblies used as inputs, as special treatment may be required in these cases.
  • PreEmptive Solutions is actively working with other tool vendors to ease the pain of debugging obfuscated code; the attribute helps those tools know what they are dealing with.

If these things are not as important to you as the increased security of an anonymously obfuscated program, or if size reduction is a higher priority, then you can disable insertion of the attribute by manually setting a global option in the configuration file, called nodotfuscatorattribute.

NoDotfuscatorAttribute Global Option:

<global>
   <option>nodotfuscatorattribute</option>
</global>

Input Assembly List

The input assembly list contains the file names and directories of the assemblies and/or packages you want to obfuscate. It also contains configuration options that are set at the package or assembly level.

If you have a multi-module assembly, only list the module containing the manifest.

Input Assembly List:

<input>
   <asmlist>
      <inputassembly>
       ...
        <file dir="c:\temp" name="myproj.dll"/>
       </inputassembly>
     ...
   </asmlist>
</input>

Library Mode By Assembly

To specify Library Mode for an input assembly, add a library option to its <inputassembly> element.

      <inputassembly>
        <option>library</option>
        ...
      </inputassembly>

Declarative Obfuscation By Assembly

Enabling or Disabling Declarative Obfuscation

To enable Declarative Obfuscation for an input assembly, add an honorOAs option to its <inputassembly> element.

      <inputassembly>
        <option>honoroas</option>
        ...
      </inputassembly>
Stripping Obfuscation Attributes

To enable obfuscation attribute stripping for an input assembly, add a stripOA option to its <inputassembly> element.

      <inputassembly>
        <option>stripoa</option>
        ...
      </inputassembly>

Injection Processing By Assembly

Dotfuscator allows you to control code injection for specific input assemblies. This section describes the effects of setting these options.

When injection is enabled, Dotfuscator honors and strips unnecessary instrumentation and check attributes from the output assemblies. This default behavior can be overridden at the input assembly level by specifying one or both:

  • nohonorsos prevents Dotfuscator from processing instrumentation and check attributes declared in the assembly.
  • nostripsos prevents Dotfuscator from stripping unnecessary instrumentation and check attributes from the assembly after processing them.

Injection Processing by Assembly:

      <inputassembly>
        <!-- do not strip instrumentation and check attributes -->
        <option>nostripsos</option>
        <!-- do not honor instrumentation and check attributes -->
        <option>nohonorsos</option>
        ...
      </inputassembly>

Transform XAML By Assembly

This setting tells Dotfuscator that a particular input assembly may contain markup, either XAML as found in Silverlight applications or compiled XAML resources (BAML) as found in Windows Presentation Foundation applications; and any markup should be analyzed and included for renaming. For Dotfuscation purposes, markup that is transformed will have identifiers renamed in conjunction with any code-behind references of the elements. Properties that are referenced from markup resources will have their property metadata retained but will be renamed.

To specify Transform XAML mode for an input assembly, add an <option> element to its <inputassembly> element.

Transform XAML Mode by Assembly:

      <inputassembly>
        <option>transformxaml</option>
        <file dir="c:\temp" name="myproj.dll"/>
      </inputassembly>

User Defined Assembly Load Path

Dotfuscator needs to load assemblies referenced by your input assemblies in order to discover information about types you are using in your input assemblies. Dotfuscator uses discovery rules similar to the rules used by Visual Studio and the CLR itself.

If a referenced assembly cannot be found using the default search rules, Dotfuscator provides a way for you to specify additional directories in which to look for referenced assemblies. Dotfuscator searches these directories in the specified order as the last step in its algorithm. However, if the prepend option (the Search First checkbox in the Project Properties and Settings Tab) is used, then Dotfuscator searches the load path before applying its standard search.

To add a User Defined Assembly Load Path to your XML configuration file:

Adding a User Defined Assembly Load Path:

  <input>
    <loadpaths>
      <option>prepend</option>
      <file dir="C:\temp" />
       ...
    </loadpaths>
    ....
  </input>

Output Directory

This is the directory where output assemblies are written. The application always overwrites files in this directory without prompting the user.

Output Directory:

<!-- destination directory is required -->
<output>
<file dir="c:\work"/>
</output>

Temp Directory

This section is optional and specifies Dotfuscator’s working directory. If not specified, the working directory defaults to the system’s temporary directory. The application uses the working directory to run ildasm and ilasm on the input assemblies. The disassembled output is stored in this directory along with any resources embedded in the input assemblies. These files are automatically deleted after processing.

Temp Directory:

<!-- scratch directory is optional -->
<!-- If absent, defaults to system's temp dir -->
<tempdir>
<file dir="c:\temp"/>  
</tempdir>

Obfuscation Attribute Feature Map

The feature map is for Declarative Obfuscation. For a complete description of Dotfuscator’s support for Declarative Obfuscation, see Declarative Obfuscation via Custom Attributes. That section describes the Feature Map and lists the native feature strings that Dotfuscator understands.

In the configuration file, the <obfuscationattributemap> element is where you can map strings obtained from an obfuscation attribute’s Feature property to one or more feature strings that Dotfuscator understands.

Here is what such a mapping looks like in the XML configuration file:

Obfuscation Attribute Feature Map:

  <obfuscationattributemap>
    <feature name="testmode">renaming, controlflow</feature>
  </obfuscationattributemap>

Renaming Section

The renaming section allows you to specify options that are specific to renaming, input and output mapping file locations, and fine-grained rules for excluding items from renaming.

The renaming section is optional. If not present, the following defaults apply:

  • Default renaming (namespaces are removed).
  • New names are chosen using the loweralpha renaming scheme.
  • No mapping file is read for Incremental Obfuscation.
  • The mapping file is written to {CurrentWorkingDir}/Dotfuscator/Map.xml.
  • No exclusions beyond those dictated by your application type.

The section on identifier renaming describes the renaming options, the mapping file, and custom exclusions in great depth. The following sections present an overview of each.

Renaming Scheme

Dotfuscator allows you to choose from several predefined algorithms for generating obfuscated identifier names:

  • Lower Alpha. This is the default renaming scheme used by all versions of Dotfuscator and uses lower case alphanumeric characters: {a,b,c,...}
  • Upper Alpha. This scheme uses upper case alphanumeric characters: {A,B,C,...}
  • Numeric. This scheme uses numeric characters only: {0,1,2,...}
  • Unprintable. This scheme uses unprintable high Unicode code points.

The renaming scheme is an attribute of the <renaming> element. Allowable values are: loweralpha, upperalpha, numeric, or unprintable.

Renaming Scheme:

<renaming scheme="unprintable">
...
</renaming>

Renaming Options

Dotfuscator allows several options that govern how namespaces are treated by the renaming algorithm. These are: "keepnamespace" and "keephierarchy" and are explained in detail in the section on identifier renaming.

Dotfuscator allows you to specify that obfuscated type names must be prefixed with a default or user-specified string. To use this feature, specify the prefix option. Please see Renaming Prefixes for full details.

Turning on the Renaming Prefix Feature:

<renaming>
   <!-- this turns on the renaming prefix feature -->
   <option>prefix</option>
...
</renaming>

Dotfuscator also allows an enhanced level of Overload Induction that adds return type to the mix. The option to turn this on is: enhancedOI and is explained in detail in the section on overload induction method renaming.

Apply Enhanced Overload Induction:

<renaming> <!--  Apply Enhanced Overload Induction. -->
 <option>enhancedOI</option>
 ...
</renaming>

Enhanced Overload Induction is, by default, not applied to classes marked as serializable. If you wish to apply enhanced overload induction to all types, including serializable types, use the enhancedOIOnSerializables option:

Apply Enhanced Overload Induction Serializeable Option:

<renaming>

<!--  Apply enhanced Overload Induction even on serializable types. -->
<option>enhancedOIOnSerializables</option>
...
</renaming>

You can change the renaming algorithm to rename types and members in a way that’s compatible with the XML Serializer.

Change Renaming Algorithm to be Compatible with XML Serializer:

<renaming>

<!--  XML Serialization compatibility. -->
<option>xmlserialization</option>
...
</renaming>

For more information, see XML Serialization and Renaming.

Using the <explicitoverrides> renaming option lets Dotfuscator rename more methods by allowing it to introduce explicit (i.e. non-syntactic) method overrides. In other words, overridden methods can have different names than the methods they override. For example, ordinarily, if a method overrides Object.ToString(), Dotfuscator would not be able to rename it without breaking the override relationship, since typically the Object class is not in an input assembly and therefore its ToString() would not be renamed. With this setting, Dotfuscator can rename the overriding method and introduce metadata that tells the CLR that the method is meant to override Object.ToString(). For more information, see Introduce Explicit Method Overrides When Renaming.

Introduce Explicit Method Overrides:

<renaming>
<!-- Allow overriding methods to have different names than the
       methods they override -->
   <option>explicitoverrides</option>
</renaming>

If you want to rename overloaded methods with the same name, then you would not use the <explicitoverrides> renaming option.

Using the <randomizeRenaming> option causes Dotfuscator to assign the new names in a non-linear order. So instead of assigning Lower Alpha names in the order {a, b, c, d,...}, you would get something more like {u, p, k, f,...}. This option will work with any Renaming Scheme.

Use Random Name Assignment:

<renaming>
  <!-- Use random name assignment -->
  <option>randomizeRenaming</option>
...
</renaming>

Note: Renaming options are not case sensitive.

Renaming Exclusion List

This section provides a dynamic way to fine tune the renaming of the input assemblies. It can contain a list of exclusion rules that are applied at runtime. If a rule selects a given class, method, field, property, or event then that item is not renamed.

  • These rules are applied in addition to rules implied by global options such as the library option.
  • The rules are logically OR-ed together, so any item that is selected by at least one rule is not renamed.
  • The exclusion list has support for excluding names by type, method, field, property, event, assembly, module, or namespace.
  • Each type of rule is explained in detail in the section on identifier renaming.

Renaming Referenced Rules

Referenced rules allow you to import rules from an external file so they can be shared among configurations. Dotfuscator’s Built-In renaming rules use this to import rules from %ProgramData%\PreEmptive Solutions\Common. The rule is referenced via the rulekey attribute whose value is a GUID defined by the rule being referenced.

Reference Rule List:

<referencerulelist>
   <referencerule rulekey="{0D471A86-E98F-4493-849B-85BD4CC884A1}"/> 
   <referencerule rulekey="{C9D9BF84-4F0D-4e9f-B3EC-3038235AE741}"/> 
</referencerulelist>

Output Mapping File

This feature of Dotfuscator produces a log of all the renaming mappings used by Dotfuscator during a specific run. It also provides a statistics section.

Specifying this option instructs Dotfuscator’s renamer to keep track of how things were renamed for both your immediate review and for possible use as input in a future Dotfuscator run. A file is created from this option that is then used in the incremental input file option.

Accidental loss of this file can destroy your chances of incrementally updating your application in the future. Therefore, proper backup of this file is crucial. For this reason, Dotfuscator automatically renames an existing map file with the same name before overwriting it with a new version of the map file.

If you do not want Dotfuscator to rename existing map files before overwriting, set the attribute overwrite="true".

The format of the mapping file is discussed in the section on identifier renaming.

Setting the Attribute to Overwrite:

<renaming>
...
<mapping>
  <mapoutput overwrite="true">
   <file dir="c:\work" name="testout.xml"/>
  </mapoutput>
</mapping>
</renaming>

HTML Renaming Report

The output mapping file is natively formatted as an XML document suitable for parsing. For a human readable renaming report, you can tell Dotfuscator to transform the output mapping file into an HTML formatted document. Dotfuscator will apply a predefined XSL document to the mapping file to accomplish the transformation. If you do not like the default HTML report, you can optionally specify your own XSL document to use for the transformation. The output report is placed in the same directory as the XML formatted mapping file. The filename will be the same as the XML file, but will have a .html extension rather than a .xml extension.

HTML Renaming Report:

<renaming>
...
<mapping>
  <mapoutput overwrite="true">
   <file dir="c:\work" name="testout.xml"/>
   <transform>
      <!-- specifying your own XSL file is optional --> 
      <file dir="c:\mytransforms" name="map.xsl"/>
   </transform>
  </mapoutput>
</mapping>
</renaming>

Input Mapping File

In Dotfuscator, the input mapping file allows you to import names that Dotfuscator created in a previous run (a process known as Incremental Obfuscation). Dotfuscator will make a best-effort attempt to rename classes, methods, and fields to the names indicated in the input mapping file.

The <mapinput> element allows you to specify the input mapping file. It also has an optional obfuscatereferences attribute, which defaults to "true" if not present. This attribute controls how Dotfuscator handles names contained in the input mapping file that are not defined within the set of input assemblies. When true, references to these names within the current set of input assemblies will be renamed.

Input Mapping File:

<renaming>
...
<mapping>
  <mapinput obfuscatereferences="true">
   <file dir="c:\work" name="testin.xml"/>
  </mapinput>
</mapping>
</renaming>

Control Flow Obfuscation Section

The control flow section allows you to specify options that are specific to control flow obfuscation, including fine-grained rules for excluding items from control flow obfuscation.

The control flow section is optional. If not present, control flow obfuscation is disabled.

Control Flow Obfuscation Level

The level of control flow obfuscation may be set to one of three values: "low", "medium", or "high". These levels correspond to the aggressiveness of Dotfuscator’s control flow obfuscation algorithms. A higher level generally results in stronger obfuscation at the cost of increased code size and degraded performance. This is because more aggressive control flow obfuscation involves adding more branch instructions to the code.

The level of control flow obfuscation applies globally to all methods being obfuscated.

Control Flow Obfuscation Options

The "disable" option is primarily for convenience and troubleshooting purposes. When set, Dotfuscator skips control flow obfuscation altogether, regardless of what’s in the rest of the control flow section.

Control Flow Obfuscation Options:

<controlflow level="high">
<!-- Skip control flow, ignoring rest of section-->
<option>disable</option>
...
</controlflow>

Note: Control Flow options are not case sensitive.

Control Flow Exclusion List

This section provides a dynamic way to fine tune control flow obfuscation of the input assemblies. It can contain a list of exclusion rules that are applied at runtime. If a rule selects a given class or method, then that item is not subject to control flow obfuscation.

Note: The library option has no effect on control flow obfuscation, unlike renaming.

The rules are logically OR-ed together, so any item selected by at least one rule is not subject to control flow obfuscation.

The exclusion list has support for excluding methods by type, method, assembly, module, or namespace.

Each type of rule is explained in detail in the section on control flow obfuscation.

String Encryption Section

The string encryption section allows you to specify options that are specific to string encryption, including fine-grained rules for specifying types and methods subject to string encryption.

The string encryption section is optional. If not present, string encryption is disabled.

String Encryption Options

This option is primarily used for convenience and troubleshooting purposes. When set, Dotfuscator skips string encryption altogether, regardless of what’s in the rest of the string encryption section.

User String Encryption Options:

<stringencrypt>
<!--Skip string encryption, ignoring rest of section-->
<option>disable</option>
...
</stringencrypt>

Note: String Encryption options are not case sensitive.

String Encryption Inclusion List

This section provides a dynamic way to fine tune string encryption of the input assemblies. It contains a list of inclusion rules that are applied at runtime. If a rule selects a given class or method, then that item is subject to string encryption.

Note: Unlike renaming, the library option has no effect on string encryption.

The rules are logically OR-ed together, so any item that is selected by at least one rule is subject to string encryption.

The inclusion list has support for including methods by type, method, assembly, module, or namespace.

Each type of rule is explained in detail in the section on user string encryption.

Removal Section (a.k.a. Pruning)

The <removal> section allows you to specify options that are specific to the removal functionality and fine-grained rules for specifying types and members subject to removal.

The <removal> section is optional. If not present, removal is disabled and no removal occurs.

Disable Removal Option

This option is used primarily for convenience and troubleshooting purposes. When set, Dotfuscator skips the removal step altogether, regardless of what’s in the rest of removal section.

Disable Removal Option:

<removal>
<!--Skip removal (pruning), ignoring rest of section-->
<option>disable</option>
...
</removal>

Note: Removal options are not case sensitive.

ConstOnly Option

This option is used to enable Constant-Only Removal. In this mode, only constant declarations will be removed. Unused types, methods, and fields will be propagated to the output assembly.

Removal Option:

<removal>
<!--Use Constant-Only Removal instead of full Removal-->
<option>constonly</option>
...
</removal>

Note: Removal options are not case sensitive.

Removal Trigger List

In the context of Removal, triggers are starting points for the static dependency analysis that Dotfuscator performs in order to determine which types, methods, and fields are used by your code. In other words, these are the entry points for your application or library.

Triggers are analyzed by Dotfuscator to determine which classes, methods, and fields are required for your application or library to function. For example, all methods called by your triggers, and methods called by those methods, are deemed required by Dotfuscator. That is, if you tell Dotfuscator a specific main method is required, then all the methods that main method calls are required as well.

A trigger list is not required, but is honored, if the library global option is used.

The trigger list is used in addition to triggers implied by global options such as the library option.

The trigger list specifies triggers in the same way that elements are selected for exclusion and inclusion in other parts of the configuration. It contains a list of rules that are applied at runtime. If a rule selects a given method or field, then that becomes a trigger.

The rules are logically OR-ed together, so any item that is selected by at least one rule becomes a trigger.

The trigger list has support for specifying fields, methods, properties, and events by type, method, assembly, module, or namespace.

Each type of rule is explained in detail in the section on Removal.

Conditional Includes List

A type must be conditionally included if it is not detectable by the static dependency analysis, i.e. if it is dynamically loaded; meaning, the type itself is included in the dependency analysis, but its members are still subject to removal. Please see Understanding Include Triggers and Conditional Includes for a deeper explanation of this feature.

This section provides a dynamic way to specify conditionally included types. It contains a list of inclusion rules that are applied at runtime. If a rule selects a given type, then that item is conditionally included.

The rules are logically OR-ed together, so any item that is selected by at least one rule will be conditionally included.

The inclusion list has support for selecting types by name, assembly, module, or namespace.

Each type of rule is explained in detail in the section on Removal.

Removal Referenced Rules

Referenced rules allow you to import rules from an external file so they can be shared among configurations. Dotfuscator’s Built-In removal rules use this to import rules from %ProgramData%\PreEmptive Solutions\Common\dotfuscatorReferenceRule_v1.4.xml. The rule is referenced via the rulekey attribute whose value is a GUID defined by the rule being referenced.

Referenced Rules:

<referencerulelist>
   <referencerule rulekey="{0D458786-E99F-4593-849B-8512493884A1}"/>
   <referencerule rulekey="{C1159284-4F0D-4e9f-B3EC-303828419741}"/>
</referencerulelist>

Removal Report

The removal report provides a summary of all the elements removed by Dotfuscator during a specific run, including a statistics section. Dotfuscator writes the removal report in a parsable and easily transformed XML format. Like the renaming map file, Dotfuscator has a default transform that can generate a human readable HTML formatted version of the report.

Dotfuscator automatically renames an existing removal report with the same name before overwriting it with a new version.

If you do not want Dotfuscator to rename existing removal reports before overwriting, set the attribute overwrite="true".

The XML format of the removal report file is discussed in the section on Removal.

Removal Report:

<removal>
<removalreport overwrite="true">
  <file dir="c:\work" name="report.xml"/>
  <transform>
     <!-- specifying your own XSL file is optional -->
     <file dir="c:\mytransforms" name="removal.xsl"/>
  </transform>
</removalreport>
</removal>

Linking Section

The linking section allows you to specify options that are specific to the assembly linking. For more information about the linker, see Assembly Linking.

The linking section is optional. If not present, assembly linking is disabled.

Disable Linking Option

This option is used primarily for convenience and troubleshooting purposes. When set, Dotfuscator skips the linking step altogether, regardless of what’s in the rest of the linking section.

Disable Linking Option:

<linking>
<!--Skip linking, ignoring rest of section-->

Note: Linking options are not case sensitive.

Linked Assemblies

A <linkedassembly> element specifies that one or more input assemblies should be linked into a specified output assembly. The linking section can contain multiple <linkedassembly> elements; therefore, you can use the linker to create multiple output assemblies. The only limitation is that you cannot link the same input assembly into multiple output assemblies.

The <linkedassembly> element contains sub-elements that allow you to specify options for the link step, such as the name mangling policy, the primary assembly, the list of input assemblies, and the name of the output assembly.

Options

Currently the only option you can specify is the name mangling policy, which may be one of:

  • donotmangle
  • manglesilently
  • mangleandwarn

Primary Assembly

The <primaryinput> element identifies the prime assembly whose manifest information is used to create the output assembly’s manifest. This assembly must also be listed in the subsequent <assemblylist> element.

The assemblies you want to link are listed using an <assemblylist> element. Each must also be listed as an input assembly.

Output Assembly

The <outputassembly> element allows you to specify a name for the output assembly and an optional entry point method. The assembly is written to the destination directory with the given name.

Example

The example <linkedassembly> element specifies that input assemblies Driver.exe and LibraryC.dll should be linked into an assembly named out.exe. The entry point method is explicitly set to the Main method in the Driver assembly.

Note: An entry point only needs to be explicitly specified in ambiguous cases. For example, the output assembly is an .exe and the input assemblies contain more than one entry point.

Linked Assembly:

    <linkedassembly>
      <option>donotmangle</option>
      <primaryinput>
        <assembly>
          <file dir="${configdir}" name="Driver.exe" />
        </assembly>
      </primaryinput>
      <assemblylist>
        <assembly>
          <file dir="${configdir}" name="Driver.exe" />
        </assembly>
        <assembly>
          <file dir="${configdir}" name="LibraryC.dll" />
        </assembly>
      </assemblylist>
      <outputassembly name="out.exe">
        <entrypoint>
          <type name="Driver.Form1">
            <method name="Main" signature="" />
          </type>
        </entrypoint>
      </outputassembly>
    </linkedassembly>

PreMark Section

The premark section allows you to specify options that are specific to watermarking. For more information about watermarking assemblies, see Watermarking.

Note: The premark section is optional. If not present, watermarking is disabled.

PreMark Options

The watermarker supports several configuration options.

The usepassphrase option tells the watermarker to encrypt the watermark string before applying it to the selected assemblies.

The truncatestring option tells the watermarker to truncate the watermark string if it will not fit in a given assembly. The default action is to halt the build if the watermark string is too large. See Watermark String Length for more details.

The disable option is used primarily for convenience and troubleshooting purposes. When set, Dotfuscator skips the watermarking step altogether, regardless of what’s in the rest of the premark section.

PreMark Options:

 <premark>
<!--Skip watermarking, ignoring rest of section-->
<option>disable</option>
<!--Encrypt the watermark string -->
<option>usepassphrase</option>
<!--Truncate the string and continue if the string is too big -->
<option>truncatestring</option>
...
</premark>

Note: PreMark options are not case sensitive.

PreMark Elements

The premark section contains sub-elements that allow you to specify which input assemblies you would like to watermark, a passphrase to use if you are encrypting your watermark string, a character encoding to use, and the watermark string itself.

Assemblies to Watermark

The assemblies you want to watermark are listed using an <assemblylist> element. Each must also be listed as an input assembly.

<passphrase>

The <passphrase> element specifies the passphrase to use when encrypting the watermark string. The watermark string will be encrypted if you have set the usepassphrase option and the passphrase itself is set.

<encoding>

- The <encoding> element specifies the character encoding, or character map, to use when encoding the watermark string. The <encoding> element has a name attribute that you can set to a supported character map. Character maps and their names are described in the Character Maps section.

<watermark>

The <watermark> element specifies the string that you want to apply to the selected assemblies. The string is first encoded using the character map, then optionally encrypted.

Example

This example configures PreMark to apply a watermark to MyApp.exe. The watermark string, MY WATERMARK is first encoded using the 6bit-a character map, then encrypted with the passphrase "mommy".

PreMark Elements:

  <premark>
    <option>usepassphrase</option>
    <option>truncatestring</option>
    <assemblylist>
      <assembly>
        <file dir="${configdir}" name="MyApp.exe" />
      </assembly>
    </assemblylist>
    <passphrase>mommy</passphrase>
    <encoding name="6bit-a" />
    <watermark>MY WATERMARK</watermark>
  </premark>

Signing Section

The signing section allows you to specify if and how you want Dotfuscator to sign your strongly named output assemblies. For more information about assembly signing, see Obfuscating Strong Named Assemblies.

The signing section is optional. If not present, your strongly named input assemblies will not be resigned after Dotfuscation, and Authenticode Digital Signing will not be applied.

Specifying <key> Element

You can specify the key or key pair that you want Dotfuscator to use when signing with a <key> element. A <key> element can contain either a <file> or a <container> sub element. A <file> element references the file containing the key or key pair. A <container> element has a "name" attribute that specifies the name of the key container.

<file> Element:

      <key>
        <file dir="c:\temp" name="key.snk" />
      </key>

<container> Element:

      <key>
        <container name="foo"/>
      </key>

<resign> Element

To resign an assembly that was already signed before Dotfuscation, use a <resign> element. If the assembly has custom attributes that specify the key to use, you do not need a <key> element. If you wish to ignore the attributes, set the dontuseattributes option and provide a <key> element. If our assembly does not have custom attributes that specify the key, you must provide a <key> element.

This example tells Dotfuscator to ignore any custom attributes that specify the key and instead manually specifies a key file.

<resign> Element:

  <signing>
    <resign>
      <option>dontuseattributes</option>
      <key>
        <file dir="c:\temp" name="key.snk" />
      </key>
    </resign>
    ...
  </signing>

<delaysign> Element

If your input assembly is delay signed and you want Dotfuscator to automatically complete the signing process, you can provide a <delaysign> element with a <key> sub-element.

<delaysign> Element:

  <signing>
    ...
    <delaysign>
      <key>
        <file dir="c:\temp" name="key.snk" />
      </key>
    </delaysign>
  </signing>

Digital Signing Section

The digitalsigning section allows you to specify if and how you want Dotfuscator to perform Authenticode Digital Signing on your output assemblies.

The digitalsigning section is optional. If not present, Authenticode signing will not be applied.

Specifying <pfx> Element

You can specify the PKCS #12 file that was provided to you by your code-signing authority for use in Authenticode signing with a <pfx> element. A <pfx> element contains a <file> sub element which describes the location of the PKCS #12 (.pfx) file containing your code-signing certificate. The <pfx> element also has a password attribute which specifies the password used to unlock the certificate.

<pfx> Element:

      <pfx password="secret123">
        <file dir="c:\temp" name="authenticode.pfx" />
      </pfx>

<digitalsigning> Element

To perform Authenticode signing on output assemblies, you can provide a <digitalsigning> element with a <pfx> sub-element.

The disable option is primarily for convenience and troubleshooting purposes. When set, Dotfuscator skips Authenticode signing altogether, regardless of what’s in the rest of the signing section.

The <timestampurl> sub element provides the ability for you to specify the URL of an Authenticode timestamp service. This URL will be accessed during Dotfuscator's signing process, and will provide additional data which will allow your assemblies' Authenticode signatures to remain valid after your code-signing certificate has expired. This element is optional. If omitted, this additional data will not be included, and your assemblies' Authenticode signatures will become invalid once your code-signing certificate expires.

<digitalsigning> Element:

  <digitalsigning>
    <!--Skip Authenticode signing, ignoring rest of section-->
    <option>disable</option>
    <!--Specify the certificate to use for Authenticode signing-->
    <pfx password="secret123">
      <file dir="c:\temp" name="authenticode.pfx" />
    </pfx>
    <!--Optionally specify the URL to the timestamp service-->
    <timestampurl>http://timestamp.comodoca.com/authenticode</timestampurl>
  </digitalsigning>

EventList Section

The eventlist section allows you to specify pre and post build events. For more information about Dotfuscator’s build events, see Build Events.

The eventlist section is optional.

<event> Element

An event is essentially a program that Dotfuscator runs at a particular point in its build sequence. You can specify the program name, working directory, and command line arguments. In addition, an event can support additional configuration settings using an <option> element.

An <event> element has a type attribute. Currently Dotfuscator understands two event types: prebuild and postbuild. The program to run is specified using a <program> element.

Event <program> Element

The program to run when an event occurs is specified with the <program> element. It contains a <file> element specifying the program and its location, as well as an <environment> element that specifies command line arguments and working directory.

Like files and directories, the commandline attribute can contain property macros.

Property Macros:

      <program>
        <file dir="c\temp" name="copyfiles.bat" />
        <environment commandline="${myproperty}" workingdir="c:\temp" />
      </program>

Pre-Build Event Options

The pre-build event supports one option that can be set using an <option> element nested within the <event> element for the pre build event.

Option
haltonfail If the build event program returns a non-zero error code, halt the Dotfuscator build.

Post-Build Event Options

The post-build event supports several options that can be set using an <option> element nested within the <event> element for the post build event.

Option
haltonfail If the build event program returns a non-zero error code, halt the Dotfuscator build.
runoneachmodule Run the post build event once for each output module.
always Run the post build event all the time, regardless of the success or failure of the Dotfuscator build.
buildfails Run the post build event only when the Dotfuscator build fails.
buildsuccessful Run the post build event only when the Dotfuscator build is successful.
Example

The following example shows an XML configuration file fragment that sets up pre- and post-build events. The pre-build event executes the program c:\temp\copyfiles.bat with no arguments. If the build is successful, then the post-build event executes the program PEVerify on each output assembly. Notice that the output assembly name is passed as a property to PEVerify.

Example XML Configuration File Fragment:

  <eventlist>
    <event type="prebuild">
      <program>
        <file dir="c\temp" name="copyfiles.bat" />
        <environment commandline="" workingdir="c:\temp" />
      </program>
    </event>
    <event type="postbuild">
      <option>runoneachmodule</option>
      <option>haltonfail</option>
      <program>
        <file dir="C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Bin" name="PEVerify.exe" />
        <environment commandline="${dotf.current.out.module}"
                     workingdir="${dotf.destination}" />
      </program>
    </event>
  </eventlist>

PreEmptive Analytics Section

The PreEmptive Analytics section allows you to specify options that control how Dotfuscator processes instrumentation attributes in the input assemblies. For more information about injection and telemetry, see The Injection Editor.

The PreEmptive Analytics section is optional.

The sos element defines a mergeruntime attribute, which can be true (default) or false. When true, Dotfuscator merges the PreEmptive Analytics library into one of the input assemblies. When false, Dotfuscator writes the runtime library DLL to the destination directory along with the other input assemblies.

There are additional options for PreEmptive Analytics: Enable PreEmptive Analytics, Send Analytics Messages, Don’t Send Tamper Messages, Send Shelf Life Messages, and Send Debug Check Messages.

The sendanalytics option tells Dotfuscator to add code to marked assemblies that sends application analytics startup, shutdown, and feature messages to a PreEmptive Analytics Endpoint. Unsetting this option is useful if you want to send tamper messages without analytics.

The dontsendtamper option tells Dotfuscator not to send tamper notifications if tampering is detected. This is useful if you want to detect tampering and have your application react locally, but you do not want the application to send messages to a PreEmptive Analytics Endpoint.

The sendshelflife option tells Dotfuscator to add code to marked assemblies that adds logic to send shelf life status messages. These include the warning, expiration, and sign of life messages.

The senddebug option tells Dotfuscator to add code to marked assemblies that adds logic to send an exception message if an attached debugger is detected.

The disable option is used primarily for convenience and troubleshooting purposes. When set, Dotfuscator skips the attribute processing altogether, regardless of what attributes are in the input assemblies and what options are in the rest of the sos section.

PreEmptive Analytics Processing:

  <sos mergeruntime="true">
    <!-- Disable PreEmptive Analytics processing -->
    <option>disable</option>
    <!-- Send startup, shutdown, and feature messages -->
    <option>sendanalytics</option>
    <!-- Do not send Tamper messages -->
    <option>dontsendtamper</option>
    <!-- Send Shelf Life messages -->
    <option>sendshelflife</option>

    <!-- Send Debugging Check messages -->
    <option>senddebug</option>
  </sos>

Extended Attributes Section

Dotfuscator allows you to tag methods or assemblies with extended attributes without modifying the application source code. Extended attributes can modify existing supported custom attributes in the code, or act as new instances of supported attributes. As it processes and transforms your application, Dotfuscator treats extended attributes the same as their custom attribute counterparts.

Using a <codetransformlist> element, you can also map attributes, even those embedded in code, to a specific supported code transform using extended attributes. This supports attribute overloading, wherein the same set of attributes can drive multiple transforms such as Application Analytics.

Supported attribute arguments may be specified using a <propertylist> element.

Any attribute listed on the Check Attributes and Instrumentation Attributes pages is a supported attribute.

Method-level Attributes

Most extended attributes may be set at the method level. To identify the method, its defining type, name, and signature must be specified.

Example:

<extattributes>
<extattribute name="PreEmptive.Attributes.FeatureAttribute">
  <codetransformlist>
  <codetransform name="analytics"/>
  </codetransformlist>
  <type name = "MyApplicaton.MainForm">
   <method name="Main" signature="string[]" />
  </type>
  <propertylist>
   <property name="Name" value="Execute"/>
   <property name="ActivationStatusSinkElement" value="field"/>
   <property name="ActivationStatusSinkName" value="activated"/>
  </propertylist>
</extattribute>
</extattributes>

Assembly-level Attributes

Extended runtime attributes such as ApplicationAttribute, BinaryAttribute, and BusinessAttribute may be set at the assembly level. To identify the assembly, its name and location must be specified in an <assembly> element.

Example:

<extattributes>
  <extattribute name="PreEmptive.Attributes.ApplicationAttribute">
    <codetransformlist>
      <codetransform name="sosruntime" />
    </codetransformlist>
    <assembly>
      <file dir="${configdir}" name="MyApp.exe" />
    </assembly>
    <propertylist>
      <property name="Version" value="" />
      <property name="Name" value="" />
      <property name="ApplicationType" value="" />
      <property name="Guid" value="00000000-0000-0000-0000-000000000000" />
    </propertylist>
  </extattribute>
</extattributes>

SmartObfuscation Section

Smart Obfuscation allows Dotfuscator to auto detect elements that cannot be renamed or removed based on specific rules for the application type. Smart Obfuscation is turned on by default, and in most cases should be left on. It can be turned off by setting an option in this section in cases where the user believes that aggressive obfuscation will not hurt the application.

Smart Obfuscation includes a reporting facility and this section allows you to configure the verbosity of the report. Allowed values for the verbosity attribute are all, warningsonly, and none. The default value is all.

The Smart Obfuscation report can optionally be written to disk. Dotfuscator automatically renames an existing Smart Obfuscation report with the same name before overwriting it with a new version. If you do not want Dotfuscator to rename the existing Smart Obfuscation report before overwriting, set the attribute overwrite="true".

The XML format of the Smart Obfuscation report is discussed in the Smart Obfuscation section.

SmartObfuscation:

<smartobfuscation>
  <!—- Skip smart obfuscation, ignoring rest of section -->
  <option>disable</option>
  <smartobfuscationreport verbosity="all" overwrite="true">
    <!-- Specifying a destination report file is optional -->
    <file dir="c:\myproject" name="smartobfuscation.xml"/>
  </smartobfuscationreport>
</smartobfuscation>

A Note about XML Configuration Files

Dotfuscator uses XML formatted documents for the configuration and mapping files. When loaded, these documents are validated according to the Document Type Definitions (DTDs) specified in the doctype. In order to perform the validation, Dotfuscator must be able to access the relevant DTD.

Dotfuscator takes the following steps to locate DTDs:

  1. If the DTD URI specifies a local file, Dotfuscator searches for it in the indicated location. If it is not found, an error occurs.
  2. If the DTD URI specifies a web resource, Dotfuscator first searches its cache for a file with the same name as that specified in the URI. Dotfuscator keeps its cache in the %ProgramData%\PreEmptive Solutions\Common directory.
  3. If not found, Dotfuscator accesses the URI to obtain the DTD. If found, Dotfuscator caches the DTD so subsequent requests will not need to access the network. If the DTD is not found, or if Dotfuscator is unable to retrieve it from the network, an error occurs.

Custom Rules

Dotfuscator allows you to customize obfuscation rules for your application. Both Inclusion Rules and Exclusion Rules provide a dynamic way to fine tune the renaming, control flow obfuscation, string encryption, and removal of the input assemblies. These rules are applied in addition to rules implied by global options such as library and they are logically OR-ed together.

Exclusion Rules

The exclude list section provides a dynamic way to fine tune the renaming and control flow obfuscation of the input assemblies. The user specifies a list of rules that are applied at runtime. If a rule selects a given class, method, or field, then that item is not renamed or is excluded from control flow obfuscation.

These rules are applied in addition to rules implied by global options such as library.

Rules are logically OR-ed together.

Regular Expressions (REs) may be used to select namespaces, types, methods or fields. The optional regex attribute is used for this purpose. The default value of regex is false. If regex is true then the value of the name attribute is interpreted as a regular expression; if it is false, the name is interpreted literally. This is important since regular expressions assign special meaning to certain characters, such as the period.

Here are some examples of simple, regular expressions:

.*                  Matches anything
MyLibrar.           Matches MyLibrary, MyLibrari, etc.
My[\.]Test[\.]I.*   Matches My.Test.Int1,My.Test.Internal, etc.
Get.*               Matches GetInt, GetValue, etc.
Get*                Matches Ge,Get,Gett,Gettt, etc.

Please refer to the .NET Framework documentation for a full description of the regular expression syntax.

Excluding Namespaces

This option excludes all types and their members in a given namespace. You can use a regular expression to specify the namespace.

Regular Expression:

<namespace name="My.Excluded.Namespace"/>

Excluding Types

This option excludes a type by name or by attribute specifier. You can use a regular expression to specify the type name. Type names must be fully qualified names. Inner (nested) classes are specified by using the ‘/’ as a delimiter between outer and inner class. For example:

Inner (Nested) Classes:

<type name="Library.Class1/NestedClass"/>

Attribute specifiers are selected or deselected with the speclist attribute. The speclist attribute is a comma-separated list of legal attribute specifiers for types. The legal values are:

Legal Values:

abstract
interface
nestedassembly
nestedfamily
nestedfamorassem
nestedprivate
nestedpublic
notpublic
public
sealed
serializable
enum

A ‘-‘ preceding an attribute specifier negates the rule (i.e. it excludes all classes that do not have the specified attribute). A ‘+’ may be specified but is not required. The rules implied in this list are logically AND-ed together (that is, the set of excluded types is the intersection of all types that match each rule.). For instance, the following rule excludes any type that is public AND

Exclude Public and Sealed Type Rule:

<type name=”.*” speclist=”+public,+sealed” regex=”true”/>

The <type> element may also be used to select a type in order to specify rules for field, method, property, and event exclusion within it. This allows members to be excluded while not excluding their owning type. The optional excludetype attribute is used for this purpose. If not specified, the default value is true, meaning that the type name will be excluded from renaming or control flow obfuscation.

Specify Rules for Field, Method, Property, and Event Exclusion:

<type name="MyCo.Test.MyOtherTest" excludetype="false">
<!-- methods and fields excluded here -->
...
</type>

If a Type rule contains no Property or Event rules, then all property and event names in that excluded type are preserved. If a Type rule contains one or more Property rules, then only those property names will be preserved and all others will be removed. If a Type rule contains one or more Event rules, then only those event names will be preserved and all others will be removed.

Remember: If a type is not excluded and the library option is not set, then Dotfuscator removes property and event names.

Applies only to Renaming:

Type rules can be applied to entire inheritance hierarchies by specifying the applytoderivedtypes attribute. Setting the value of this attribute to true will apply the type rule and any Method, Field, Property, Event, Custom Attribute, or Supertype rules that it contains to the selected type and all types that derive from it. If not specified, the default value is false, meaning that the type rule will only be applied to the specified type.

Excluding Methods

Methods may be excluded by first selecting the type using the <type> element, then providing a rule for selecting methods to exclude. Methods may be excluded by name and attribute specifier, as well as by signature.

Allowed attribute specifiers are:

abstract
assembly
family
familyorassembly
final
private
public
static
virtual

If the attribute specifier is not set explicitly, then the speclist attribute will not be used as a matching criterion.

The following example selects all public instance methods beginning with Set:

<method regex="true" name="Set.*" speclist="+public,-static"/>

Method signatures are specified using the signature attribute. A signature specifies both the return type and the parameter types of the method:

Return Types and Parameter Types

signature=""  <!-- empty signature -->

signature="string(int,MyClass,MyClass[])"

If the signature is not set explicitly, then the method signature will not be used as a matching criterion.

The following example selects a method by signature:

Method by Signature

<method name="DoIt" signature="string(int, System.Console, System.Collection.ICollection, float[])"/>

Global methods may be specified by using a special type selector with the name "Module:mod_name" where mod_name is the name of the module containing the global method.

Excluding Fields

Field exclusion is valid for Renaming only. Fields may be excluded by first selecting the type using the <type> element, then providing a rule for selecting fields to exclude. Fields may also be excluded by name and attribute specifier.

Allowed Attribute Specifiers are:

public
private
static
assembly
family
familyandassembly
familyorassembly
notserialized

If the attribute specifier is not set explicitly, then field attribute will not be used as a matching criterion. The following example selects all static fields starting with "ENUM_":

All Static Fields Starting with "ENUM":

<field regex="true" name="ENUM_.*" speclist="+static"/>

Field signatures are specified using the signature attribute.

A signature specifies the type of the field:

signature=""  <!-- empty signature -->

signature="int"

If the signature is not set explicitly, then the field type will not be used as a matching criterion.

Global fields may be specified by using a special type selector with the name Module:mod_name where mod_name is the name of the module containing the global field.

Excluding Properties

Property exclusion is valid for Renaming only. Property rules are qualified by type rules, so they appear in the rules view as children of type nodes. A property rule will select all properties (in all types matched by the parent type rule) that match your criteria. Supported matching criteria include property name and property attributes.

Allowed Attribute Specifiers are:

public
private
static
assembly
family
familyandassembly
familyorassembly

If the attribute specifier is not set explicitly, then the property attribute will not be used as a matching criterion.

The following example selects all properties starting with "Sample":

<propertymember regex="true" name="Sample.*"/>

Property signatures are specified using the signature attribute.

A signature specifies the type of the property:

signature=""  <!-- empty signature -->

signature="int"

If the signature is not set explicitly, then the property type will not be used as a matching criterion.

Global properties may be specified by using a special type selector with the name Module:mod_name where mod_name is the name of the module containing the global property.

Excluding Events

Event exclusion is valid for Renaming only. Event rules are qualified by type rules, so they appear in the rules view as children of type nodes. An event rule will select all events (in all types matched by the parent type rule) that match your criteria. Supported matching criteria include event name and event attributes.

Allowed attribute specifiers are:

public
private
static
assembly
family
familyandassembly
familyorassembly

If the attribute specifier is not set explicitly, then the event attribute will not be used as a matching criterion.

The following example selects all events starting with "On":

<eventmember regex="true" name="On.*"/>

Global events may be specified by using a special type selector with the name Module:mod_name where mod_name is the name of the module containing the global event.

Excluding By Custom Attribute

Types, methods, fields, and properties may be selectively excluded by custom attribute. A custom attribute rule selects an item (type, method, field or property) based on matching against the names of custom attributes that annotate the item. One or more custom attribute rules may be nested inside any rule that selects types, methods, fields, or properties.

A type, method, field, or property rule may have multiple custom attribute rules associated with it. In this case, an item is selected if at least one of the custom attribute rules selects it.

The following example selects all types that are annotated with either MyCustomAttribute or MyOtherCustomAttribute:

Types Annotated with MyCustomAttribute or MyOther CustomAttribute:

<type name=".*" excludetype="false" regex="true>
   <customattribute name="MyCustomAttribute"/>
...<customattribute name="MyOtherCustomAttribute"/>
</type>

Custom attribute rules can also be written using regular expressions to match custom attribute names. The following example is another way to select all types annotated with either MyCustomAttribute or MyOtherCustomAttribute:

Types Annotated with MyCustomAttribute or MyOther CustomAttribute:

<type name=".*" excludetype="false" regex="true>
   <customattribute name="My.*CustomAttribute" regex="true"/>
</type>

The next example shows how to exclude all methods annotated with a custom attribute named MyCustomAttribute:

Exclude Annotated Methods

<type name=".*" excludetype="false" regex="true">
   <method name=".*" regex="true">
      <customattribute name="MyCustomAttribute"/>
   </method>
</type>

Custom attribute rules can be applied to subtypes or overriding methods and properties by specifying the allowinheritance attribute. When the value of this attribute is set to true then subtypes or overriding methods and properties with the specified custom attribute will also be excluded.

Excluding By Supertype

Types may be selectively excluded by supertype. A supertype rule selects a type based on matching against the names of types that the given type inherits from. One or more supertype rules may be nested inside any rule that selects types.

A type rule may have multiple supertype rules associated with it. In this case, an item is selected if at least one of the supertype rules selects it.

The following example selects all types that inherit from MySupertype:

All Types that Inherit from MySupertype:

<type name=".*" excludetype="false" regex="true">
   <supertype name="MySupertype"/>
</type>

Supertype rules can also be written using regular expressions to match supertype names. The following example shows how to select all types that inherit from either MySupertype or MyOtherSupertype:

All Types that Inherit from MySupertype or MyOtherSupertype:

<type name=".*" excludetype="false" regex="true">
   <supertype name="My.*Supertype" regex="true"/>
</type>

Excluding Assemblies

Assemblies may be excluded by name. When an assembly is excluded, all types and members within any of the assembly’s modules are excluded. It makes sense to exclude an assembly when you have a scenario such as the following:

  • Assembly A should be obfuscated.
  • Assembly B should not be obfuscated.
  • Assembly B depends on assembly A.

In other words, A provides services to B and no one else. You want the references to A embedded inside B to be obfuscated, so you include B in the same run as A, but you exclude B from renaming or control flow obfuscation.

Excluding Assemblies:

<assembly>
  <file dir="c:\projects\project1\" name="ExcludedLib.dll"/>
</assembly>

Excluding Modules

Modules may be excluded by name. Use the assembly attribute to qualify the module to a particular assembly. When specified, the assembly name should be the logical assembly name rather than its physical file name. When a module is excluded, all its defined types and members are excluded.

Obviously, if a given module is shared among multiple assemblies, then the module will be excluded from all the assemblies.

Module Excluded from all Assemblies:

<module name="MyLibResource.dll" assemblyname="MyLib"/>

Inclusion Rules

The include list section provides a dynamic way to fine-tune the string encryption and removal of the input assemblies. The user specifies a list of rules that are applied at runtime. If a rule selects a given class, method, field, property, or event then that item is included for string encryption or removal.

These rules are applied in addition to rules implied by global options such as library.

Rules are logically OR-ed together.

Regular Expressions (REs) may be used to select namespaces, types, methods, fields, properties, or events. The optional regex attribute is used for this purpose. The default value of regex is false. If regex is true then the value of the name attribute is interpreted as a regular expression; if it is false, the name is interpreted literally. This is important since regular expressions assign special meaning to certain characters, such as the period.

Here are some examples of simple regular expressions:

Regular Expressions:

.*                  Matches anything
MyLibrar.           Matches MyLibrary, MyLibrari, etc.
My[\.]Test[\.]I.*   Matches My.Test.Int1,My.Test.Internal, etc.
Get.*               Matches GetInt, GetValue, etc.
Get*                Matches Ge,Get,Gett,Gettt, etc.

Note: Please refer to the .NET Framework documentation for a full description of the regular expression syntax.

Including Namespaces

This option includes all types and their methods in a given namespace. You can use a regular expression to specify the namespace.

Regular Expression:

<namespace name="My.Included.Namespace"/>

Including Types

This option includes a type by name or by attribute specifier. You can use a regular expression to specify the type name.

Type names should be fully qualified names.

Inner (nested) classes are specified by using the ‘/’ as a delimiter between outer and inner class. For example:

Inner (Nested) Classes

<type name="Library.Class1/NestedClass"/>

Attribute specifiers are selected or deselected with the speclist attribute. The speclist attribute is a comma-separated list of legal attribute specifiers for types. The legal values are:

Attribute Specifiers:

abstract
interface
nestedassembly
nestedfamily
nestedfamorassem
nestedprivate
nestedpublic
notpublic
public
sealed
serializable
enum

A ‘-‘ preceding an attribute specifier negates the rule (i.e. it includes all classes that do not have the specified attribute). A ‘+’ may be specified but is not required. The rules implied in this list are logically AND-ed together (that is, the set of included types is the intersection of all types that match each rule.). For instance, the following rule includes all methods within any type that is public AND sealed.

Include Method with Public and Sealed Types:

<type name=”.*” speclist=”+public,+sealed” regex=”true”/>

The <type> element may also be used to select a type in order to specify rules for individual method inclusion within it. This allows string encryption in some methods of a type, while not in others. Note the <type> element’s excludetype attribute is not used in the context of string encryption inclusions.

Allow String Encryption in Some Methods of Type:

<type name="MyCo.Test.MyOtherTest">
<!-- individual methods included here -->
...
</type>

If a <type> element contains no nested <method> elements, then all methods are selected for inclusion. This is in contrast to an exclusion rule.

Applies only to Removal:

Type rules can be applied to entire inheritance hierarchies by specifying the applytoderivedtypes attribute. Setting the value of this attribute to true will apply the type rule and any Method, Field, Property, Event, Custom Attribute, or Supertype rules that it contains to the selected type and all types that derive from it. If not specified, the default value is false, meaning that the type rule will only be applied to the specified type.

Including Methods

Methods may be included by first selecting the type using the <type> element, then providing a rule for selecting methods to include. Methods may be included by name and attribute specifier (as explained in the type section above), as well as by signature.

Allowed attribute specifiers are:

abstract
assembly
family
familyorassembly
final
private
public
static
virtual

If the attribute specifier is not set explicitly, then the speclist attribute is not used as a matching criterion.

The following example selects all public instance methods beginning with Set:

All Public Instance Methods Beginning with Set:

<method regex="true" name="Set.*" speclist="+public,-static"/>

Method signatures are specified using the signature attribute. A signature specifies both the return type and the parameter types of the method:

Return Type and Parameter Types of the Method:

signature=""  <!-- empty parameter list -->

signature="string(int,MyClass,MyClass[])"

If the signature is not set explicitly, then the method signature is not used as a matching criterion.

The following example selects a method by signature:

Select Method by Signature:

<method name="DoIt" signature="string(int, System.Console, System.Collection.ICollection, float[])"/>

Global methods may be specified by using a special type selector with the name Module:mod_name where mod_name is the name of the module containing the global method.

Including Fields

Field inclusion is only valid for removal triggers and removal conditional includes.

Fields may be selected by first selecting the type using the <type> element, then providing a rule for selecting fields. Fields may be selected by name and attribute specifier (as explained in the type section above).

Allowed attribute specifiers are:

public
private
static
assembly
family
familyandassembly
familyorassembly
notserialized

If the attribute specifier is not set explicitly, then field attribute will not be used at all as a matching criterion.

The following example selects all static fields starting with "ENUM_":

Static Fields Starting with "ENUM_":

<field regex="true" name="ENUM_.*" speclist="+static"/>

Global fields may be specified by using a special type selector with the name Module:mod_name where mod_name is the name of the module containing the global field.

Including Properties

Property inclusion is valid for Removal only. Property rules are qualified by type rules, so they appear in the rules view as children of type nodes. A property rule will select all properties (in all types matched by the parent type rule) that match your criteria. Supported matching criteria include property name and property attributes.

Allowed attribute specifiers are:

public
private
static
assembly
family
familyandassembly
familyorassembly

If the attribute specifier is not set explicitly, then the property attribute will not be used as a matching criterion.

The following example selects all properties starting with "Sample ":

Properties Starting with "Sample":

<property regex="true" name="Sample.*"/>

Property signatures are specified using the signature attribute. A signature specifies the type of the property:

Signature Specifies the Type of Property:

signature=""  <!-- empty signature -->

signature="int"

If the signature is not set explicitly, then the property type will not be used as a matching criterion.

Global properties may be specified by using a special type selector with the name Module:mod_name where mod_name is the name of the module containing the global property.

Including Events

Event inclusion is valid for Removal only. Event rules are qualified by type rules, so they appear in the rules view as children of type nodes. An event rule will select all events (in all types matched by the parent type rule) that match your criteria. Supported matching criteria include event name and event attributes.

Allowed attribute specifiers are:

public
private
static
assembly
family
familyandassembly
familyorassembly

If the attribute specifier is not set explicitly, then the event attribute will not be used as a matching criterion.

The following example selects all events starting with "On":

Events Starting with "On":

<event regex="true" name="On.*"/>

Global events may be specified by using a special type selector with the name Module:mod_name where mod_name is the name of the module containing the global event.

Including By Custom Attribute

Types and methods may be selectively included by custom attribute. A custom attribute rule selects an item (type or method) based on matching against the names of custom attributes that annotate the item. One or more custom attribute rules may be nested inside any rule that selects types or methods.

A type or method rule may have multiple custom attribute rules associated with it. In this case, an item is selected if at least one of the custom attribute rules selects it.

The following example selects all types that are annotated with either MyCustomAttribute or MyOtherCustomAttribute:

Types Annotated with MyCustomAttribute or MyOtherCustomAttribute:

<type name=".*" excludetype="false" regex="true>
   <customattribute name="MyCustomAttribute"/>
...<customattribute name="MyOtherCustomAttribute"/>
</type>

Custom attribute rules can also be written using regular expressions to match custom attribute names. The following example is another way to select all types annotated with either MyCustomAttribute or MyOtherCustomAttribute:

Selecting Types Annotated with MyCustomAttribute or MyOtherCustomAttribute:

<type name=".*" excludetype="false" regex="true>
   <customattribute name="My.*CustomAttribute" regex="true"/>
</type>

The next example shows how to include all methods annotated with a custom attribute named MyCustomAttribute:

Including Methods Annotated with MyCustomAttribute:

<type name=".*" excludetype="false" regex="true">
   <method name=".*" regex="true">
      <customattribute name="MyCustomAttribute"/>
   </method>
</type>

Custom attribute rules can be applied to subtypes or overriding methods and properties by specifying the allowinheritance attribute. When the value of this attribute is set to true then subtypes or overriding methods and properties with the specified custom attribute will also be excluded.

Including By Supertype

Types may be selectively included by supertype. A supertype rule selects a type based on matching against the names of types that the given type inherits from. One or more supertype rules may be nested inside any rule that selects types.

A type rule may have multiple supertype rules associated with it. In this case, an item is selected if at least one of the supertype rules selects it.

The following example selects all types that inherit from MySupertype:

Selecting Types that Inherit from MySuperType:

<type name=".*" excludetype="false" regex="true">
   <supertype name="MySupertype"/>
</type>

Supertype rules can also be written using regular expressions to match supertype names. The following example shows how to select all types that inherit from either MySupertype or MyOtherSupertype:

Select Types that Inherit from MySupertype or MyOtherSupertype:

<type name=".*" excludetype="false" regex="true">
   <supertype name="My.*Supertype" regex="true"/>
</type>

Including Assemblies

Assemblies may be included by name. When an assembly is included, all types and methods within any of the assembly’s modules are included.

Including Assemblies:

<assembly>
 <file dir="c:\projects\project1\" name="IncludedLib.dll"/>
</assembly>

Including Modules

Modules may be included by name. Use the assembly attribute to qualify the module to a particular assembly. When specified, the assembly name should be the logical assembly name rather than its physical file name. When a module is included, all its defined types and members are included.

Obviously, if a given module is shared among multiple assemblies, then the module will be included for all the assemblies.

Including Modules:

<module name="MyLibResource.dll" assemblyname="MyLib"/>

dotfuscator_v2.4.dtd

The dotfuscator_v2.4.dtd DTD describes the format of the configuration file produced by Dotfuscator. A copy is available at www.preemptive.com/dotfuscatorresources/dtd/dotfuscator_v2.4.dtd.

Dotfuscator Version 4.31.0.6091. Copyright © 2017 PreEmptive Solutions, LLC