PreEmptive Protection - Dotfuscator 4.31
User Guide

Building and Debugging

Linking

Dotfuscator can combine multiple input assemblies into one or more output assemblies. Assembly linking can be used to make your application even smaller, especially when used with Renaming and Removal, and can simplify deployment scenarios.

For example, if you have input assemblies A, B, C, D, and E, you can link assemblies A, B, and C and name the result F. At the same time, you can also link D and E and name the result G. The only rule is that you can't link the same input assembly into multiple output assemblies.

The linking feature is fully integrated with the rest of Dotfuscator, so in one step, you can obfuscate, remove unused types, methods, and fields, and link the result into one assembly.

If you have other input assemblies that reference the assemblies you are linking together, Dotfuscator will transparently update all the assembly and type references so the output assemblies will correctly work together.

Linking is not supported for Managed C++ assemblies.

Incremental Obfuscation

Incremental obfuscation allows you to keep a consistent naming scheme across Dotfuscator runs for your application. By referencing a name mapping file, types and members can be consistently renamed over time. Consistent renaming is desirable in multiple scenarios, including the redistribution of a subset of files that constitute a dependant group, and sequential obfuscation of assemblies in a resource constrained environment. Appropriate utilization of this feature offers the additional benefit of more rapid obfuscation, when only some of the assemblies in a project need to be redistributed.

Consider a scenario where you have used Dotfuscator on your application and distributed that application to your customers. Now you would like to make changes to one of the assemblies and provide it as an update. A naive re-execution of Dotfuscator upon your application would likely rename your legacy classes and methods in a different way, forcing you to redistribute the entire application to your customers. Dotfuscator’s incremental obfuscation allows you to keep the same names so you can release the changed assembly.

Incremental obfuscation is useful in sequential build scenarios by allowing the obfuscation of large projects to be broken down into smaller, more manageable groups of assemblies. A hypothetical project consisting of three files, A.exe, B.dll, and C.dll where A references B, and B references C could be built as follows: C.dll could be obfuscated initially, then B.dll could be incrementally obfuscated using the map file from C.dll, and finally A.exe could be obfuscated using the map file from B.dll.

Incremental obfuscation requires an input mapping file containing the names that need to be reused. The format is the same as the output mapping file that Dotfuscator produces after every run. A best practice is to save a copy of the output mapping file in a safe place (e.g. in version control) for every released build of your application. The file can then be used as an input mapping file if an incremental update should ever be necessary.

When performing a run using incremental obfuscation, Dotfuscator must have access to all the application’s assemblies, although it is not required that all the assemblies be included in the project. They only need to be discoverable by the same probing rules used by Dotfuscator to locate referenced assemblies.

Debugging Obfuscated Code

One major drawback of obfuscation is that the task of maintaining and troubleshooting an obfuscated application becomes more difficult. In a well obfuscated application, the names of all types, methods, and fields are changed from their carefully thought out, informative names into meaningless names. This makes using a debugger more difficult, and impacts the usefulness of stack traces sent in from the field.

To solve the debugging problem, Dotfuscator has the ability to output debugging symbol files for obfuscated application that correspond as closely as possible to the original symbol files output by the compiler. Using these files, you can use a debugger to step through an obfuscated assembly and view the original source code.

To solve the stack trace problem, PreEmptive Solutions provides Lucidator, a standalone tool that translates and decodes stack traces emitted by programs obfuscated with Dotfuscator. Lucidator works by automatically decoding obfuscated stack traces using the renaming map file. Given the obfuscated stack trace, Lucidator replaces the obfuscated names with the original names and displays the results. This same translation ability is built into the Dotfuscator GUI, as well.

Lucidator does not need to be run on the same machine on which Dotfuscator is installed, as long as it has access to the appropriate map file.

Obfuscating Strong Named Assemblies

Strong named assemblies are digitally signed. This allows the runtime to determine if an assembly has been altered after signing. The signature is an SHA1 hash signed with the private key of an RSA public/private key pair. Both the signature and the public key are embedded in the assembly’s metadata.

Since Dotfuscator modifies the assembly, it is essential that signing occur after running the assembly through Dotfuscator.

Dotfuscator handles this step as part of the obfuscation process.

Automatically Re-signing after Obfuscation

Dotfuscator automatically re-signs strongly named assemblies after obfuscation, eliminating the need for manual steps after obfuscation. Dotfuscator both re-signs your already signed assemblies, and completes the signing process on delay signed assemblies.

Re-signing Strongly Named Assemblies

As part of the build process, Dotfuscator re-signs assemblies that are already strongly named. You can tell Dotfuscator explicitly where to find the public/private key pair, or you can rely on a location specified by custom attributes on the input assembly (e.g. System.Reflection.AssemblyKeyFileAttribute).

The following example shows an XML configuration file fragment that sets up resigning with an explicit key file. Any key file specified via custom attribute is not used.

Re-signing with Explicit Key File:

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

Finishing Signing Delay Signed Assemblies

If an input assembly is delay signed, Dotfuscator can finish the signing process. Tell Dotfuscator where to locate the private key required to complete the signing.

The following example shows an XML configuration file fragment that sets up delay signing with an explicit key file.

Delay Signing:

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

Re-Signing Obfuscated Assemblies with Authenticode

Authenticode signed assemblies are digitally signed by a code signing certificate issued by a trusted root certificate authority. This allows the operating system and runtime to determine the publisher of an application and to determine if the assembly has been altered after being signed. The signature is a hash encrypted with the private key of a code signing certificate. Both the signature and the public key are embedded in the assembly’s metadata.

Since Dotfuscator modifies the assembly, it is essential that Authenticode signing occur after running the assembly through Dotfuscator.

Dotfuscator's support for Authenticode differs depending on the hash function used. Signing with SHA-1 can be done automatically, while signing with SHA-256 needs to be done manually.

Automatic SHA-1 Signing

Dotfuscator can re-sign output assemblies with SHA-1 based on configuration settings. For more information see the Authenticode Digital Signing section of the Standalone GUI page.

The following example shows a Dotfuscator config file fragment that configures Authenticode signing. It specifies both the password for and the path to the Personal Information Exchange (.pfx) file used for signing.

  <digitalsigning>
    <pfx password="secret123">
      <file dir="C:\test" name="authenticode.pfx" />
    </pfx>
  </digitalsigning>

Manual SHA-256 Signing

Dotfuscator does not re-sign with SHA-256 or any other hash function besides SHA-1. This kind of signing can instead be done using a post build event.

A post build event for signing with SHA-256 can be be configured as follows:

  • Program

    • Command Line:

         sign /fd sha256 /f [certificate file path] /p [certificate password] /tr [certificate timestamp server URL] /as ${dotf.current.out.module}
      
      • [certificate file path] can use ${configdir} to specify a path relative to the Dotfuscator config file's directory.
    • Program Path: The absolute path to the Microsoft Sign Tool. You can find this by opening the Developer Command Prompt and typing where signtool.

  • Run On Each Module: Yes

The following is a Dotfuscator config file fragment that configures the post build event.

<eventlist>
<event type="postbuild">
  <option>runoneachmodule</option>
  <option>buildsuccessful</option>
  <program>
    <file dir="[sign tool dir]" name="signtool.exe" />
    <environment commandline="sign /fd sha256 /f [certificate filename].pfx /p [certificate password] /tr [timestamp url] /as ${dotf.current.out.module}" workingdir="" />
  </program>
</event>
</eventlist>

Dual-Signing

You can combine the instructions from the previous two sections to dual-sign assemblies with both SHA-1 and SHA-256.

Build Events

Dotfuscator allows you to specify programs that run before and after its build sequence.

Pre Build Event

In its build process, Dotfuscator executes the program specified by the pre build event before it does anything else with your input assemblies.

Post Build Event

Dotfuscator executes the program specified by the post build event at the very end of its build process. You can tell Dotfuscator to execute the program only when the build succeeds, only when the build fails, or all the time. In addition, you can tell Dotfuscator to run the program once for each output module.

Build Event Properties

The Dotfuscator build engine exposes several properties that you can use when configuring build events:

Property Name Description
dotf.destination Path to the destination directory.
dotf.inputmap.xml Full path and filename to the input map file if specified.
dotf.outputmap.xml Full path and filename to the output map file if specified.
dotf.removal.xml Full path and filename to the XML removal file if specified.
dotf.config.file Full path to the current configuration file.
dotf.current.out.module Full path to the current output module. Used in the post build event when the program is called for each output module.
dotf.current.in.module Full path to the current input module. Used in the post build event when the program is called for each output module.

You can also reference external properties (environment variables or properties passed on the command line using the -p option) and user defined project properties in your build events.

See Also:

Dotfuscator Version 4.31.1.6114. Copyright © 2017 PreEmptive Solutions, LLC