14

Obfuscating Xamarin for Android

posted by admin

Recently Babel Obfuscator introduced obfuscation support for the Mono platform. There are several .NET platforms that that are built around Mono, like Xamarin and MonoGame. In this article we will show how to obfuscate a Xamarin application for Android using Babel Obfuscator.

The sample project that we will use is the Snake game. This is a well know old fashioned game and is enough simple to illustrate various concepts you can use in a real Xamarin project. To follow this tutorial you will need Xamarin installed. The trial version of Xamarin can do the job. You can use Xamarin Studio or Visual Studio to build the project and setup the obfuscation. Basically the steps required are the same. If you have an Android device you can configure it for deployment and connect to your PC to test the obfuscated application. The Snake project is available to download at:

http://developer.xamarin.com/samples/Snake/


Let’s start by opening the Snake solution in Xamarin Studio and after choosing Release configuration press Ctrl+F5 to build and deploy the solution to your device. One note here, the Debug configuration does not add the .NET assemblies to the deployed .APK package so we will use the Release build to test the obfuscated application on the device. After deploying the application you should see the Snake game up and running.

The build process on Xamarin Studio is based on MSbuild so if you open the Snake.csproj in a text editor you will see a standard MSBuild project with imports for MonoDroid targets. This makes the integration with Babel Obfuscator pretty straightforward. 

To obfuscate the Snake assembly, open the Snake.csproj file in your favorite text editor and add the UsingTask element to reference the tasks in the Babel.Build assembly:

<Import Project="$(MSBuildExtensionsPath)\Novell\Novell.MonoDroid.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets.
-->
<UsingTask TaskName="Babel" AssemblyName="Babel.Build, Version=8.0.0.0, Culture=neutral, PublicKeyToken=138d17b5bd621ab7" />

Then in the AfterBuild target add the Babel task as follow:

<Target Name="AfterBuild">
    <
Babel InputFile="$(TargetPath)" OutputFile="$(TargetPath)"
          
VerboseLevel="5"
          
ObfuscateTypes="true"
          
ObfuscateEvents="true"
          
ObfuscateMethods="true"
          
ObfuscateProperties="true"
          
ObfuscateFields="true"
          
VirtualFunctions="true"
          
FlattenNamespaces="false"
          
UnicodeNormalization="false"
          
SuppressIldasm="true"
          
StringEncryption="hash"
          
ResourceEncryption="true"
          
ValueEncryption="true"
          
DynamicProxy="all"
          
ControlFlowObfuscation="goto=on;if=on;switch=on;case=on;call=on"
          
ILIterations="5" />
</
Target>

Note that by setting the InputFile and OutputFile task attributes to $(TargetPath) we will configure Babel to obfuscate the build target assembly in place making Xamarin to deploy the obfuscated assembly in the APK package.

The Babel task above enable some obfuscation features available only in the Enterprise edition of Babel Obfuscator. If you have installed the demo version, you can use the following more relaxed obfuscation settings:

<Target Name="AfterBuild">
    <
Babel InputFile="$(TargetPath)" OutputFile="$(TargetPath)"
          
VerboseLevel="5"
          
ObfuscateTypes="true"
          
ObfuscateEvents="true"
          
ObfuscateMethods="true"
          
ObfuscateProperties="true"
          
ObfuscateFields="true"
          
VirtualFunctions="true"
          
FlattenNamespaces="false"
          
UnicodeNormalization="false"
          
SuppressIldasm="true"
          
StringEncryption="xor"
          
ResourceEncryption="false"
          
ValueEncryption="false"
          
DynamicProxy="false"
          
ControlFlowObfuscation="goto=on"
          
ILIterations="5" />
</
Target>

Now you can rebuild the solution and look at Build Output window to see that Babel Obfuscator processed the Snake.dll in the bin\Release folder. 


By Opening the Snake.dll in ILSpy you can see the resulting obfuscated assembly.


Although the obfuscation was performed, many type names are still visible. This because those types are declared as public. Let’s change the visibility of the public types to internal to see if Babel can do better. In Xamarin Studio change the visibility to internal of the following types:

SnakeActivity
Coordinate
RefreshHandler
Direction
GameMode
TileType

To compile the solution you need to change the visibility of the following methods inside the SnakeActivity class:

internal void SetTextView (TextView newView)
internal void SetMode (GameMode newMode)
internal void Update ()
internal Bundle SaveState ()
internal void RestoreState (Bundle icicle)

And in the TileView class:

internal void ResetTiles (int tileCount)
internal void LoadTile (TileType type, Drawable tile)
internal void ClearTiles ()
internal void SetTile (TileType tile, int x, int y)

If you want you can change the obfuscation setting to hide the namespace information for all renamed types:

FlattenNamespaces="a"

After rebuilding the solution you can now see that the Snake assembly is much better obfuscated:


The SnakeView and TileView classes cannot be changed to internal because they are used in the XML code of the Snake layout view. So is not possible to rename them otherwise we will get an error at run-time. 

Another note is worth to point out, concerns the option UnicodeNormalization. As you noticed this option was disabled. You can try to enable Unicode normalization, but this will result in several compiler errors:


This because Xamarin as part of the build process generates and compiles java classes that are stubs of the .NET obfuscated types. These java classes get the same name as the obfuscated types, and because Unicode characters are not supported by the javac compiler this results in compilation errors. According to java language the only symbols you can use are the underscore and dollar symbols. If you want you can use those characters to generate obfuscated names:

UnicodeNormalization="_,$"

Now we can test the obfuscated assembly on the device:


It Worked! You can download the modified Snake solution from this article.

If you have more questions feel free to contact our support at support@babelfor.net.

Back to List