Reputation: 1129
Is there anything out there that does obfuscation? I have tried Crypto Obfuscator for Android and when I de-compiled using dex2jar, I see no difference between obfuscated and normal assembly. So far I have went through following links:
http://forums.xamarin.com/discussion/14962/light-obfuscation
Mono for Android, code obfuscation
Upvotes: 4
Views: 6167
Reputation: 21
Dotfuscator CE (free in Visual Studio) or Dotfuscator PRO (paid license) obfuscates Xamarin applications: See the Xamarin manual here: Protecting Xamarin Apps
Using Dotfuscator, the most consistent and secure method of obfuscating your Xamarin apps is to integrate it 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. In order for the obfuscated outputs to be processed properly by Xamarin, Dotfuscator's "Mono Compatible" global setting should be set to "Yes" and a project property of "controlflow.disabled_manglers" with a value of "ILSpyBreaker" should be added.
Xamarin's platform specific utilities use reflection heavily, so as a starting point it is recommended to simply exclude the input assemblies from renaming (while still allowing control-flow obfuscation). Once that is working, you can then enable renaming if desired, and take the time to determine the minimum amount of exclusions needed for your application.
In each Android or iOS csproj file you should then add a reference to the Dotfuscate task and a target for AfterBuild, like so:
<UsingTask TaskName="PreEmptive.Tasks.Dotfuscate" AssemblyFile="$(MSBuildExtensionsPath)\PreEmptive\Dotfuscator\4\PreEmptive.Dotfuscator.Tasks.dll" />
////SNIP////
<Target Name="AfterBuild">
<PropertyGroup>
<DotfuscatorProperties>
<OutDir>$(OutDir)</OutDir>
<OutputPath>$(OutputPath)</OutputPath>
</DotfuscatorProperties>
</PropertyGroup>
<Dotfuscate ConfigPath="Obfuscate.Android.xml" Properties="$(DotfuscatorProperties)"/>
</Target>
Notice that we are passing in certain properties from the build process to the Dotfuscator process. Specifically OutDir and OutPath. By using project properties with default values we can specify paths in the Dotfuscator project file to allow us to configure the project using the stand-alone Dotfuscator UI, while having the build process handle where they actually are at build time.
In order for the Xamarin platform specific build process to properly find the obfuscated assemblies, they have to be copied back into the original assembly locations after obfuscation. Android has an additional restriction in that the original obfuscated PCL must be copied back to its project specific location as well. The easiest way to accomplish this is to have a post-build event in the Dotfuscator project to do the copying:
Adding a "ObRelease" and/or "ObDebug" configuration can be useful to only obfuscate when explicitly needed and wanted. This can be accomplished by adding a Condition property to the Dotfuscate element in the csproj (for instance: Condition=" '$(Configuration)' == 'ObRelease' "). Note that when adding a new "Release" config for Android, one needs to disable "Use Shared Runtime" and "Enable developer instrumentation" in the Android Options under the Packaging tab.
Once these steps are complete, you should be able to see Dotfuscator's build output during your builds in either Visual Studio or Xamarin Studio.
Upvotes: 1
Reputation: 697
You refered to a forums post on xamarin.com ("Light Obfuscation"). There, now I have added an explanation of how to obfuscate with Xamarin Studio and Babel for .NET.
I will repeat it here:
You don't need to have the full Visual Studio to get an easy and comfortable way of obfuscating. I now use Babel for .NET with Xamarin Studio (in Windows). I haven't tried to get Babel running on a Mac, maybe it's possible.
So, here I will explain how to obfuscate your Android app in Xamarin Studio:
The good thing is that Xamarin Studio uses the MSBuild mechanism and Babel can be integrated in a MSBuild process.
For me (except for installing Babel) there were only two steps necessary:
(Step 1)
Edit you .csproj file with a text editor. Xamarin Studio must not be running.
<Project>
[... All existing stuff ...]
<UsingTask TaskName="Babel" AssemblyName="Babel.Build, Version=6.4.0.0, Culture=neutral, PublicKeyToken=138d17b5bd621ab7" />
<Target Name="AfterBuild" Condition=" '$(Configuration)' != 'Debug' ">
<Babel InputFile="$(TargetPath)" OutputFile="$(TargetPath)" GenerateDebug="true"
[...]
RulesFiles="babel.xml"
SuppressIldasm="false" ObfuscateTypes="true" ObfuscateProperties="true" ObfuscateEvents="true" ObfuscateMethods="true"
ObfuscateFields="true" VirtualFunctions="true" FlattenNamespaces="false"
StringEncryption="true"
/>
</Target>
</Project>
Whenever you build your app and the build mode is not Debug (so it is Release), this Task is applied. You can specify an xml file where you can define fine-grained rules for the obfuscation process. (e.g. exclude certain classes etc.)
By the way: A rule of thumb is: Define every class, interface, delegate or enum as "internal", not as "public". By default, types that have to be visible outside the assembly (public types) will not be obfuscated. Internal types will be obfuscated by default. The only class I marked as "public" is "MainActivity".
(Step 2)
When I started the first try for my app, I got the following error message:
BABEL : error : Could not resolve assembly: 'Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065'
Which I could not understand first, because a Hello-World Android app was obfuscated without problems. After some hours of research, I found the reason for the error. My activity (my game has only one activity) had the following attribute:
[Activity(
Label = "The name of my game",
MainLauncher = true,
WindowSoftInputMode = SoftInput.AdjustPan,
ConfigurationChanges = ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden | ConfigChanges.Orientation | ConfigChanges.ScreenSize
)]
"Label" and "MainLauncher" turned out not to be the problem. But "WindowSoftInputMode" and "ConfigurationChanges" were the problems.
To fix it, I fully removed the [Activity (...)] attribute from the .cs file and added the necessary information by hand to the AndroidManifest.xml. This way, the obfuscation worked without problems.
You may wonder why the Activity attribute caused a problem. I realized that ILSpy also had a problem when this attribute was applied to the C# Activity class with "WindowSOftInputMode" and "ConfigurationChanges". So I think it is not a problem of Babel, but a problem of Xamarin. The reason might be that, while "Label" and "MainLauncher" are fundamental types (string and bool), the other two are not. Their types are defined in Mono.Android.dll which seems to be refered to in a wrong way. The best thing would be if Xamarin removed the attribute for the compiled dll because it is only used for making the AndroidManifest.xml in the build step.
Upvotes: 5