Dotfuscator provides .NET obfuscation and application protection across a variety of platforms - including Xamarin! An important aspect of obfuscation is ensuring that it is integrated into your build, so it is consistently and automatically applied. This article focuses on build integration; for general obfuscation advice, please see the relevant user guide (Professional, Community Edition).
There are many different methods you could use to obfuscate a Xamarin project with Dotfuscator. The process outlined here is essentially:
- Configure the Xamarin build to run Dotfuscator as an
- Configure a
Copytask to copy the obfuscated binaries back to their original locations
- Configure a
- Configure Dotfuscator
- Specify the inputs
- Exclude things from renaming (as usual / as needed)
- Only use Mono-compatible transforms (Pro-only)
- Build, verify obfuscation, and test
The examples below use a sample application from Xamarin, BugSweeper, and focus on the Android platform. These instructions can be applied to other projects and platforms (e.g. iOS); you'll need to adapt the filenames and paths accordingly. (If you are building a UWP or Windows Phone project, we recommend building the store-ready package (APPX or XAP) first and then running it through Dotfuscator as usual.)
It's always a useful exercise to first see what the unobfuscated application looks like in a decompiler. Try building the BugSweeper.Android project in the Release configuration and opening the two managed DLLs with a .NET decompiler like
ILSpy. They are located in the project's
bin\Release directory (BugSweeper.dll and BugSweeper.Android.dll). In ILSpy, you will see something like this, which looks a lot like the original source code:
These instructions cover both the Community Edition and the Professional Edition of Dotfuscator. Where needed, the differences will be called out.
To use the Professional Edition, simply ensure it is installed and runs without issue.
To use the Community Edition, you'll need a version with command line build support (first released in Visual Studio 2015 Update 3) and you'll need to register it. You can find the command line interface here:
<Program Files>\Microsoft Visual Studio <version>\PreEmptive Solutions\Dotfuscator and Analytics Community Edition\dotfuscatorCLI.exe
Future versions of Visual Studio may install to different locations; you will need to update the path accordingly.
Integrate Dotfuscator into the Xamarin build pipeline
The most consistent and secure method of obfuscating your Xamarin apps is to integrate Dotfuscator into the MSBuild pipeline. This allows you to obfuscate your project using standard build tools, and lets you test your obfuscation using Xamarin's built-in debugger workflow.
We do this by updating each
.csproj file with a new
AfterBuild target, in which we will:
- Run Dotfuscator
- Pass properties to Dotfuscator to tell it where to find inputs and where to put outputs
- Copy Dotfuscator's outputs back to their original input locations, so the remainder of the Xamarin build can operate on them
For the Professional Edition, we'll add a reference to Dotfuscator's custom MSBuild task (
<UsingTask TaskName="PreEmptive.Tasks.Dotfuscate" AssemblyFile="$(MSBuildExtensionsPath)\PreEmptive\Dotfuscator\4\PreEmptive.Dotfuscator.Tasks.dll" />
...and then use that task in the new target:
<Target Name="AfterBuild"> <PropertyGroup> <DotfuscatorProperties> <OutDir>$(OutDir)</OutDir> </DotfuscatorProperties> </PropertyGroup> <Dotfuscate ConfigPath="Obfuscate.Android.xml" Properties="$(DotfuscatorProperties)"/> <!--MORE TO COME, BELOW-->
For the Community Edition, the MSBuild task isn't available, so we'll call the Dotfuscator executable directly:
<Target Name="AfterBuild"> <Exec Command=""C:\Program Files (x86)\Microsoft Visual Studio 14.0\PreEmptive Solutions\Dotfuscator and Analytics Community Edition\DotfuscatorCLI.exe" -p=OutDir=$(OutDir) $(ProjectDir)\Obfuscate.Android.xml" /> <!--MORE TO COME, BELOW-->
In both Editions, we finish the target with:
<ItemGroup> <ObfuscatedFiles Include="$(ProjectDir)\Dotfuscated\*.dll" /> </ItemGroup> <Copy SourceFiles="@(ObfuscatedFiles)" DestinationFolder="$(OutDir)" /> <Copy SourceFiles="$(ProjectDir)\Dotfuscated\BugSweeper.dll" DestinationFolder="$(ProjectDir)\..\BugSweeper\$(OutputPath)" /> </Target>
Please review the following aspects of the XML above:
OutDirrepresents the output path of the Xamarin build. From Dotfuscator's point of view, it is really an input directory.
Obfuscate.Android.xmlis a Dotfuscator config file that we will create in the next step.
BugSweeper.dllwill need to change to match your particular project.
- There are two copy tasks: one that copies the assemblies back to their original locations, and another that copies a PCL (Portable Class Library) assembly back to its project-specific location. That second copy task is required to make the Xamarin Android build succeed.
The overall process for configuring Dotfuscator is the same between Community Edition and Professional Edition, but the UI is different, and the Professional Edition has more options and settings to configure. We'll start with a high-level overview, then show exactly what to do in each product.
1: Run the GUI
Professional Edition will typically be found in the Start Menu. Community Edition will typically be found in the Tools menu of Visual Studio. (If it is missing, you may need to re-run the Visual Studio installer and add the component.)
2: Change settings to enable Xamarin compatability
Dotfuscator Professional supports control-flow obfuscation in addition to the renaming transforms supported by Community Edition. Some of the control-flow transforms are not Mono-compatible, so they have to be disabled in Professional Edition. To do so, go to Settings -> Global Options and change "Use only Mono-compatible transforms" to "Yes".
No changes are required for Community Edition.
3: Configure project properties
The MSBuild Target that we created above uses
OutDir to pass the location of the input files to Dotfuscator. Dotfuscator has to be told to "see" these properties, or it will ignore them.
On the Project Properties (Pro) or Properties (CE) page, add a new property named
OutDir and set its initial value to the full path of the build output (typically ending in "Release"). It will be overridden at build
time by the path that's passed in from MSBuild.
4: Add Inputs
Our sample Android application has two assemblies: the portable code is in BugSweeper.dll, and the Android specific code is in BugSweeper.Android.dll. Add these two assemblies to Dotfuscator on the Inputs page. Instead of browsing for them on the filesystem, type them in so they reference the "OutDir" property:
5: Disable Library Mode, as appropriate
Leave the platform-dependent assembly
BugSweeper.Android.dll in Library Mode. This tells Dotfuscator not to rename the assembly's visible symbols. This is appropriate, since this assembly contains the entry points to the managed code,
called by the runtime. On the other hand, the platform-neutral
BugSweeper.dll, containing most of the application code, does not need to be in library mode, so uncheck the box for Library mode. (In Dotfuscator Professional, you may need
to click the + next to the input, to see the Library mode checkbox.)
6: Manually exclude symbols from renaming, as appropriate
Some names in BugSweeper.dll need to be excluded from renaming, because they are referenced from the application's XAML in ways that will break if they are renamed. In Dotfuscator, you can exclude specific symbols from renaming from the Renaming -> Exclusions page. Exclude these symbols:
Save the Dotfuscator project to the BugSweeper.Android project's directory. Name the file
Build, Verify, and Test
Now you should be able to see Dotfuscator's build output during your builds in either Visual Studio or Xamarin Studio:
You may need to set Visual Studio's "MSBuild project build output verbosity" option to "Detailed" if you want to see Dotfuscator's output in the VS Output Window during the build. You can find this setting in Visual Studio's Options dialog as shown:
To see how the renaming worked, open the output assemblies in a decompiler as before. Here is a view of the same decompiled code as shown above, after being built with Dotfuscator Community Edition:
The renaming created a layer of obfuscation that hides much of the code's intent and makes it more difficult to follow.
Dotfuscator Professional Edition includes additional transforms, such as control flow obfuscation and string encryption, that provide even more protection by making the decompiler output incorrect code, or no code at all:
Community Edition users might want to try a Dotfuscator Professional Edition evaluation!