Contact Us Blog Register Login
PreEmptive -
  • Home
  • Products
    • Application Protection
      • Dotfuscator for .NET
        • Overview
        • Features
        • Compare Editions
        • Xamarin Protection
        • Videos & Resources
        • Pricing
        • Downloads
      • DashO for Android & Java
        • Overview
        • Features
        • Videos & Resources
        • Pricing
        • Downloads
      • JSDefender for JavaScript
        • Overview
        • Features
        • Pricing
        • Downloads
      • PreEmptive Protection for iOS
        • Overview
  • Support
    • Product Support
      • Dotfuscator for .NET
      • DashO for Android & Java
      • JSDefender for JavaScript
      • PreEmptive Protection for iOS
    • Resources
      • White Papers
      • Glossary
      • Videos
      • Submit Support Request
  • Solutions
    • App Protection Solutions
      • Mobile App Protection
      • Desktop & Server App Protection
      • General Data Protection Regulation (GDPR)
      • Security Development Lifecycle
      • Mobile RASP
      • PCI Mobile Payment Acceptance Security
  • Company
    • About
      • Why PreEmptive?
      • About Us
      • Careers
      • Blog
    • Contact
      • Contact Us
      • Submit Support Request
    • Legal

Dotfuscator and MSBuild

April 30, 2009 9344 Views Bill Leach

As of Dotfuscator Professional 4.37 there is a much faster, easier, and more reliable way to integrate Dotfuscator into MSBuild. These instructions are still valid, but you should consider the new approach first.

This is the first in a series of what I hope to be informative postings around the theme of “Dotfuscator Tips, Tricks, and HOWTOs”.  Today's topic, if you missed the title, is MSBuild integration. Dotfuscator Pro ships with an MSBuild task that is by default installed into the MSBuildExtensionsPath directory (e.g. C:\Program Files\MSBuild) under “PreEmptiveDotfuscator4.0”. In this directory, you will also find PreEmptive.Dotfuscator.Targets, the file that contains a common definition for the “Dotfuscate” target.

Dotfuscator’s user’s guide contains a reference for the Dotfuscate task, describing its inputs and outputs, but does not contain any examples. I hope to rectify that here with some working examples that demonstrate how to use the Dotfuscate task to its full potential. I’m assuming that you are familiar with MSBuild and have used Dotfuscator.

Dotfuscator Project Files in Visual Studio

First off, if you want a quick look at an MSBuild script that uses Dotfuscator and you are using Dotfuscator’s Visual Studio integration (VS 2005 and above), you should know that the Dotfuscator project file is persisted in MSBuild format. In fact, you can take any solution that contains a Dotfuscator project and feed it to MSBuild on the command line—MSBuild will build the solution the same as it does inside Visual Studio, including the Dotfuscation step.

Dotfuscator project files have a “.dotfuproj” file extension. If you open one in a text editor, you will see that it defines an MSBuild Project whose default target is “Dotfuscate”. It defines several property and item groups, then imports the PreEmptive.Dotfuscator.Targets file. It turns out that many of the property and item groups are defined primarily for Dotfuscator’s internal use when integrating with Visual Studio and are not strictly required for MSBuild. Let’s take out the extra things and build a minimal MSBuild script for invoking Dotfuscator.

The Bare Minimum

Here is a minimal MSBuild script that invokes Dotfuscator.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Dotfuscate" ToolsVersion="3.5">
<PropertyGroup>
<DotfuscatorBinPath>$(MSBuildExtensionsPath)PreEmptiveDotfuscator4.0</DotfuscatorBinPath>
<DotfuscatorDataPath>$(MSBuildExtensionsPath)PreEmptiveDotfuscator4.0</DotfuscatorDataPath>
</PropertyGroup>
<PropertyGroup>
<!-- Required: specify path to dotfuscator configuration file -->
<ConfigPath>.dotfconfig.xml</ConfigPath>
</PropertyGroup>
<Import Project="$(DotfuscatorDataPath)PreEmptive.Dotfuscator.Targets" />
</Project>

The first two properties are required to locate the Dotfuscator targets file and MSBuild task DLL. Beyond that, the only other required property is “ConfigPath”, which should be set to the location of your Dotfuscator configuration file. In this example, the Dotfuscator configuration file is located in the same directory as the MSBuild script, and is called dotfconfig.xml.

For maximum flexibility, Dotfuscator’s MSBuild task is designed so that it consumes the same Dotfuscator configuration files that the command line interface consumes. These are the same files that the Visual Studio and standalone user interfaces generate for you when you configure a Dotfuscator project.

If you save this file and run MSBuild on it, MSBuild will use the default target, “Dotfuscate”, which is defined in the imported targets file. Assuming the referenced Dotfuscator configuration file exists, Dotfuscator will run as configured.

Build Integration

Typically, you will want to run Dotfuscator as part of a larger build process. For example, you might not want a separate Dotfuscate target—perhaps you want to run Dotfuscator as part of another build step. You might also want to do something with the Dotfuscated output assemblies, such as copy them to a staging directory.

The next examples demonstrate these build integration scenarios by invoking the Dotfuscate task and using its output properties. First, let’s look at an example that runs the Dotfuscate task through a dependency relationship on a “Custom” build target.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Custom" ToolsVersion="3.5">
<PropertyGroup>
<DotfuscatorBinPath>$(MSBuildExtensionsPath)PreEmptiveDotfuscator4.0</DotfuscatorBinPath>
<DotfuscatorDataPath>$(MSBuildExtensionsPath)PreEmptiveDotfuscator4.0</DotfuscatorDataPath>
</PropertyGroup>
<PropertyGroup>
<ConfigPath>.dotfconfig.xml</ConfigPath>
</PropertyGroup>

<Import Project="$(DotfuscatorDataPath)PreEmptive.Dotfuscator.Targets" />

<!-- Create a 'Custom' target that depends on the Dotfuscate target.  After running, the Dotfuscate task outputs are available -->
<Target Name="Custom" DependsOnTargets="Dotfuscate">

<!-- Access outputs from Dotfuscator task (map file, output assemblies, output debug symbols, etc.-->
<Message Text="Dotfuscator Mapping File: @(DotfuscatorMappingFile)" />
<Message Text="Dotfuscated Output Assemblies: @(DotfuscatedAssemblies)" />
<Message Text="Dotfuscated Debug Symbols: @(DotfuscatedDebugSymbols)" />

</Target>
</Project>

Running MSBuild on this script invokes the “Custom” target. Since “Custom” depends on the “Dotfuscate” target, “Dotfuscate” is invoked first. Once that’s done, you can manipulate the Dotfuscate target’s outputs. The MSBuild Task Reference in the Dotfuscator User’s Guide documents the complete list of available outputs. You can also see them directly by opening up the PreEmptive.Dotfuscator.Targets file in a text editor. This example simply displays the paths of the renaming map file, the output assemblies, and the associated PDB files.

Up until now, the examples have invoked Dotfuscator implicitly by referencing the Dotfuscate target defined in PreEmptive.Dotfuscator.Targets. You can also invoke the Dotfuscate task explicitly from your own target. This example demonstrates:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build" ToolsVersion="3.5">
<PropertyGroup>
<DotfuscatorBinPath>$(MSBuildExtensionsPath)PreEmptiveDotfuscator4.0</DotfuscatorBinPath>
<DotfuscatorDataPath>$(MSBuildExtensionsPath)PreEmptiveDotfuscator4.0</DotfuscatorDataPath>
</PropertyGroup> <PropertyGroup> <ConfigPath>.dotfconfig_explicit.xml</ConfigPath> </PropertyGroup> <!-- This targets file defines the Dotfuscate task --> <Import Project="$(DotfuscatorDataPath)PreEmptive.Dotfuscator.Targets" /> <!-- Explicitly invoke the Dotfuscate target from this target --> <Target Name="Build"> <!-- You can do other stuff here, before invoking Dotfuscate
... --> <Dotfuscate ConfigPath="$(ConfigPath)"> <Output TaskParameter="OutputAssemblies" ItemName="DotfuscatedAssemblies" /> </Dotfuscate> <!-- Copy output assemblies to a staging directory.--> <PropertyGroup> <StagingDir>.staging</StagingDir> </PropertyGroup> <MakeDir Directories="$(StagingDir)" /> <Copy SourceFiles="@(DotfuscatedAssemblies)" DestinationFolder="$(StagingDir)" /> </Target> </Project>

Here we are invoking the Dotfuscator task directly in the “Build” target. We’ve essentially copied the definition of the Dotfuscate target out of the PreEmptive.Dotfuscator.Targets file and stripped out the things we aren’t using (for brevity). After Dotfuscator runs, the script creates a staging directory and uses MSBuild’s Copy task to copy the Dotfuscated output assemblies to it.

Setting Dotfuscator Properties from MSBuild Scripts

As you may know, Dotfuscator has its own string macro facility, called properties. These shouldn’t be confused with MSBuild properties. Dotfuscator properties are primarily a means for making Dotfuscator configuration files more general and more portable. Configuration files can reference properties in any element that takes a file name or directory; they can also define properties-- but properties become more powerful when the definition is passed in as Dotfuscator is invoked. For example, you can define properties from Dotfuscator’s command line interface using the /p switch. Not surprisingly, you can also define properties from MSBuild scripts. This is what the Dotfuscate Task’s “Properties” property is for.

For example, let’s assume you have a Dotfuscator configuration file that specifies the renaming map file like this:

<!-- "configdir" is a built-in Dotfuscator property that is always the directory of the configuration file -->
<mapoutput overwrite="false">
<file dir="${configdir}${reportdir}" name="map.xml" />
</mapoutput>

The location of the renaming map file is a subdirectory (whose name will be provided in the reportdir property) of the configuration file’s directory.

Now, in your MSBuild script, define an MSBuild Property (in this case, called MyDotfuscatorProperties). Inside that property, define each Dotfuscator property using its name as an XML element, and its value as content. Content can consist of any text, including MSBuild property references. For example:

<PropertyGroup>
<MyDotfuscatorProperties>
<reportdir>Reports</reportdir>
<mypropertyname>$(MyMSBuildProperty)</mypropertyname>
</MyDotfuscatorProperties>
</PropertyGroup>

This example defines two Dotfuscator properties:

  1. reportdir = Reports
  2. mypropertyname = content of MyMSBuildProperty

Next, when invoking the Dotfuscate task, set its “Properties” property to the value of the MSBuild property you just defined:

<Dotfuscate ConfigPath="$(ConfigPath)" Properties="$(MyDotfuscatorProperties)">
<Output TaskParameter="OutputAssemblies" ItemName="DotfuscatedAssemblies" />
</Dotfuscate>

Putting all this together and running MSBuild, Dotfuscator writes the renaming map file to a subdirectory named “Reports”.

Conclusion

Hopefully I have shed some light onto the process of using Dotfuscator with MSBuild. I’d like to expand on this introduction in future posts, so let me know what you’d like to see. I welcome your suggestions, questions, and comments-- MSBuild related or not!

Categories

  • Dotfuscator

  • Dotfuscator CE

  • DashO

  • Press Releases

  • Mobile Protection

  • Risk Management

  • Support Corner

Latest Blog Posts

Protecting C# Applications That Use Dynamic Types



The dynamic type in C# provides flexibility that is not available in other statically-typed languages. Since its introduction in C# 4.0 (.NET 4.5), we have worked with customers who wanted to know more about how dynamic types are impacted by the obfuscation process.

Read more

Non-Traditional Attack Vectors: Three Questions Every CISO Needs to Ask



Malicious actors — like any thieves — live by a simple rule: If the front door is locked, break the window.

It’s why threats like fileless malware and crypto-jacking have seen substantial gains over last few years. It’s why — despite increasing employee education and IT training — hackers are still hooking phish by developing more sophisticated and authentic-looking email spoofs. Cybercriminal communities, meanwhile, continue to grow on the dark web, allowing attackers to share info, purchase exploit kits and identify potential targets.

What does this mean for CISOs? That typical defense efforts are being outpaced as familiar attack vectors are replaced with non-traditional threats. But it’s not all bad news; here are three questions every CISO needs to ask to help close the doors, bolt the windows and leave hackers out in the cold.

Read more

Q&A With PreEmptive CEO Gabriel Torok



Gabriel, you have been in the security industry for over 2 decades. You have seen many different tools and services. Why create a company around something as specific as obfuscation and in-app protection?

Our customers build a lot of really innovative apps that enable their users and customers to do new and cool things. These apps frequently run on untrusted client computers/devices and they control access to customer’s sensitive data or critical devices.

And after all the effort of designing, building, debugging, and deploying their applications, the last thing they want is for an attacker to steal their work or use it to look for vulnerabilities to break into their system.

Long ago, we built a Java code optimizer, but it became clear to us that our customer cared more about the obfuscation effects of the optimization than the actual performance improvement. That is when we really began to focus on app protection. First with Java, then .NET, Android, iOS, Xamarin, JavaScript, etc.

Read more

The Secret to Effective In-App Protection



Gartner calls In-App Protection “crucial” in their July 2019 Market Guide for In-App Protection In-App Protection. The guide’s summary advises security and risk management leaders to “take due care in protecting their application clients” in order to avoid “security failure.”

This raises the question – what constitutes “due care?” Obviously, no development organization looks to recklessly expose their applications or sensitive data to attack or compromise. On the other hand, over-engineered (or poorly engineered) security controls can quickly lead to excessive development costs, performance and quality issues, and, ultimately, unacceptable user experiences. While terms and terminology may vary, there is broad consensus on how to best define “due care” for any given application/user scenario.

Read more

Symbol Renaming: App Security’s Maginot Line?



If you don’t follow application security closely, you might think of application obfuscation and symbol renaming as being synonymous – and with good reason. Many platforms and languages, like .NET, Java, and JavaScript have popular obfuscators that do little else--our own Dotfuscator Community Edition for .NET and ProGuard for Java are good examples. However, obfuscation is far more than symbol renaming – and in-app protection is far more than obfuscation. Much of this expansion has been driven by new security requirements, shifting attack vectors, the rise of mobile and IoT computing and, lastly, the growing recognition inside regulations and legislation of the exposure that can result from inadequately protected software.

Read more

preemptive logo

767 Beta Dr. Suite A
Mayfield Village, OH 44143

Tel: +1 440.443.7200

solutions@preemptive.com

Latest Blog Posts

Protecting C# Applications That Use Dynamic Types

December 4, 2019
Read more

Non-Traditional Attack Vectors: Three Questions Every CISO Needs to Ask

November 5, 2019
Read more

Q&A With PreEmptive CEO Gabriel Torok

October 31, 2019
Read more

The Secret to Effective In-App Protection

October 16, 2019
Read more

Symbol Renaming: App Security’s Maginot Line?

October 3, 2019
Read more

Twitter

RT @dinodaizovi: It's great to see more cloud services advertising encryption at rest by default. That's just table stakes, however. It tur… Dec 05 • reply • retweet • favorite

Copyright © 2019 PreEmptive

  • Home
  • Contact Support
  • Blog
  • Contact
Scroll to Top

PreEmptive uses cookies to improve the functionality of our website. By using this site, you agree to the use of cookies.