I have some experience obfuscating Xamarin Android projects but I'm hitting a wall with Xamarin Forms. The linker does not accept the obfuscated DLL.
Has anyone gotten an obfuscator to work with Xamarin Forms? If so, which?
Thank you all.
I should add that this is a problem with PCL projects only. The linker accepts obfuscated dll's in shared projects (it throws a warning but not an error).
You should mention which obfuscator you use, how you configured the obfuscator and linker and what the exact error is.
Unfortunately I cannot help you there. Obfuscation is a requirement for my current app (on Android), but I didn't try it yet. So I am interested in your findings in this area.
I've used several obfuscators and I would use any one that works.
The LinkAssemblies error is:
Xamarin.Android.XamarinAndroidException: error XA2006: Reference to metadata item...
The problem is a combination of naming protections and when/how to insert the obfuscated dll in the archiving process.
I can do the obfuscation in xamarin android but in xamarin forms how do you obfuscate too dlls ? Any suggestions or hint?
There's no difference between an Android only or a Forms solution.
I ended up using ConfuserEx. The only other option was Crypto Obfuscator but I didn't get it running and their support didn't answer my emails. All other obfuscators either did not support PCL/Android or had no price on their webpages.
First I added an additional task to my Android csproj file:
<Target Name="Obfuscate" AfterTargets="_CopyIntermediateAssemblies" Condition="'$(Configuration)' == 'Release'">
<Exec Command="$(SolutionDir)pathto\Obfuscate.bat" WorkingDirectory="$(SolutionDir)pathto" />
The Obfuscate.bat looks like this:
del %ProjectFolder%\bin\Release\Obfuscated\*.* /q
D:\ConfuserEx_bin\Confuser.CLI.exe %ProjectFolder%\%Project%.crproj -debug
copy %ProjectFolder%\bin\Release\Obfuscated\*.* %ProjectFolder%\bin\Release
copy %ProjectFolder%\bin\Release\Obfuscated\*.dll %ProjectFolder%\obj\Release\linksrc
copy %ProjectFolder%\bin\Release\Obfuscated\project1.* path_to_project1\bin\Release
copy %ProjectFolder%\bin\Release\Obfuscated\project2.* path_to_project2\bin\Release
copy %ProjectFolder%\bin\Release\Obfuscated\project3.* path_to_project3\bin\Release
Be sure to copy the obfuscated dlls to bin\Release, obj\Release\linksrc and their respective bin\release folders! This may be a problem in solutions with multiple projects as the target folders will differ there and it's nowhere documented. If you forget any folder, then you'll get errors later.
And in my project.crproj I have this:
<rule pattern="true" preset="none" inherit="false">
<protection id="anti debug" />
<protection id="anti ildasm" />
<protection id="constants" />
<protection id="ctrl flow" />
<protection id="ref proxy" />
<argument name="mode" value="letters" />
<!-- <argument name="renPublic" value="true" /> does not work -->
<!--<protection id="resources" /> does not work -->
<module path="project1.dll" />
<module path="project2.dll" />
<module path="project3.dll" />
<probePath>C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\MonoAndroid\v7.0</probePath>
<probePath>C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\MonoAndroid\v1.0</probePath>
Resources and rename/renPublic should work for PCLs according to the ConfuserEx wiki, but I couldn't get it running. If anybody knows how to do that, then please let me know how.
I needed to disable rename protection for some Android Adapters. No idea why this didn't work.
thanks for the answer.
Did you guys tied .NET Reactor? Looks like it support for Xamarin, And they have a tools for Visual Studio for one click protect your assembly.
You can try this.
I had no issues using dotfuscator and following this guide: https://www.preemptive.com/dotfuscator/pro/userguide/en/getting_started_xamarin.html
... using the community edition and Visual Studio 2017 CE
Thanks so much for posting your full process to get obfuscation working! I followed everything step-by-step, and finally my files are being properly obfuscated, with no extra hassle when deploying.
I just finished evaluating BabelFor.NET 9.0 with Visual Studio 2017 / Xamarin on Mac OS High Sierra. I'm using Xamarin Forms to develop a PCL project for Android and iOS. After adding AfterBuild task to the .csproj, use of the tool is very easy. My trial version was limited with some features being crippled, but it provided enough functionality for review. Inspection of the resulting DLLs with ILSpy shows that Babel does what it claims.
I'll be evaluating ConfuserEx next.
Has anyone successfully integrated ConfuserEx with Visual Studio 2017 for Mac / Xamarin? I was hoping to apply the build task methodology that I employed for BabelFor.Net (adding the AfterBuild task to .csproj. If so, do you have a sample csproj (or just the relevant part of the csproj) that you could post? Thank you.
I'm about to give up on ConfuserEX for my Xamarin.Forms PCL (Android and iOS) project, but thought I'd give it one more try. Below are the steps that I've followed so far to obfuscate a dll. The result is a process that starts to execute but then fails with
[ERROR] Unknown error occurred
Exception: dnlib.DotNet.Pdb.Managed.PdbException: Failed to read PDB: Invalid signature.
My steps to build and use ConfuserEx on OSX High Sierra are as follows:
Confuser.CLI starts and fails with the output below:
[INFO] ConfuserEx v1.0.0-2-g778190f Copyright (C) Ki 2014
[INFO] Running on Unix 184.108.40.206, 220.127.116.119 (2018-02/39d89a335c8 Thu Sep 27 06:54:53 EDT 2018), 64 bits
[DEBUG] Discovering plugins...
[INFO] Discovered 10 protections, 1 packers.
[DEBUG] Resolving component dependency...
[INFO] Loading input modules...
[INFO] Loading 'App.dll'...
[DEBUG] Building pipeline...
[INFO] Resolving dependencies...
[DEBUG] Checking Strong Name...
[DEBUG] Creating global .cctors...
[DEBUG] Executing 'Name analysis' phase...
[DEBUG] Building VTables & identifier list...
[INFO] Processing module 'App.dll'...
[DEBUG] Executing 'Invalid metadata addition' phase...
[DEBUG] Executing 'Renaming' phase...
[DEBUG] Executing 'Anti-debug injection' phase...
[DEBUG] Executing 'Anti-dump injection' phase...
[ERROR] Unknown error occurred.
Exception: dnlib.DotNet.Pdb.Managed.PdbException: Failed to read PDB: Invalid signature
at dnlib.DotNet.Pdb.Managed.PdbReader.ReadInternal (dnlib.IO.IImageStream stream) [0x00030] in <7872a884084e4681935d37638bb723a0>:0
at dnlib.DotNet.Pdb.Managed.PdbReader.Read (dnlib.IO.IImageStream stream) [0x00007] in <7872a884084e4681935d37638bb723a0>:0
at dnlib.DotNet.Pdb.Managed.SymbolReaderCreator.Create (dnlib.IO.IImageStream pdbStream) [0x0000b] in <7872a884084e4681935d37638bb723a0>:0
at dnlib.DotNet.Pdb.Managed.SymbolReaderCreator.Create (System.String pdbFileName) [0x00006] in <7872a884084e4681935d37638bb723a0>:0
at dnlib.DotNet.Pdb.Managed.SymbolReaderCreator.CreateFromAssemblyFile (System.String assemblyFileName) [0x0000b] in <7872a884084e4681935d37638bb723a0>:0
at dnlib.DotNet.Pdb.SymbolReaderCreator.Create (dnlib.DotNet.Pdb.PdbImplType pdbImpl, System.String assemblyFileName) [0x00010] in <7872a884084e4681935d37638bb723a0>:0
at dnlib.DotNet.ModuleDefMD.CreateSymbolReader (dnlib.DotNet.ModuleCreationOptions options) [0x000b0] in <7872a884084e4681935d37638bb723a0>:0
at dnlib.DotNet.ModuleDefMD.InitializePdb (dnlib.DotNet.ModuleCreationOptions options) [0x00004] in <7872a884084e4681935d37638bb723a0>:0
at dnlib.DotNet.ModuleDefMD..ctor (dnlib.DotNet.MD.MetaData metaData, dnlib.DotNet.ModuleCreationOptions options) [0x0014e] in <7872a884084e4681935d37638bb723a0>:0
at dnlib.DotNet.ModuleDefMD.Load (dnlib.DotNet.MD.MetaData metaData, dnlib.DotNet.ModuleCreationOptions options) [0x00000] in <7872a884084e4681935d37638bb723a0>:0
at dnlib.DotNet.ModuleDefMD.Load (System.String fileName, dnlib.DotNet.ModuleCreationOptions options) [0x00006] in <7872a884084e4681935d37638bb723a0>:0
at Confuser.Core.Services.RuntimeService.GetRuntimeType (System.String fullName) [0x00053] in :0
at Confuser.Protections.AntiDumpProtection+AntiDumpPhase.Execute (Confuser.Core.ConfuserContext context, Confuser.Core.ProtectionParameters parameters) [0x0000b] in <7b854044badf49fbb8fbaf090be38916>:0
at Confuser.Core.ProtectionPipeline.ExecuteStage (Confuser.Core.PipelineStage stage, System.Action1[T] func, System.Func1[TResult] targets, Confuser.Core.ConfuserContext context) [0x0005f] in :0
at Confuser.Core.ConfuserEngine.RunPipeline (Confuser.Core.ProtectionPipeline pipeline, Confuser.Core.ConfuserContext context) [0x00106] in :0
at Confuser.Core.ConfuserEngine.RunInternal (Confuser.Core.ConfuserParameters parameters, System.Threading.CancellationToken token) [0x0044c] in :0
Failed at 4:48 PM, 0:00 elapsed.
1[T] func, System.Func
The .pdb files contain debugging information. You don't want that in your release build.
I have these lines in my .csproj:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
I never tried it on the Mac.
You can try to debug ConfuserEx too. The source seems very complicated to me, but at least you may find out a better reason for the exception than the stack trace provides.
Thank you for your reply. My .csproj contains the same for DebugType and DebugSymbols (for my release build), so I'm not sure why it appears that ConfuserEx is trying to read PDB (on Mac). Babel support has been good, helping me to automate obfuscation of my iOS and Android DLLs as part of my build process, so Babel may be my only viable option.
@MichaelRumpler (Thank you for your post), I need some help please
I can't figure out whats is the project.csproject !!!!!!! you mean the android csproj ???? I'm lost
I have tried to do steps but I don't get to work. Could you explain a few more steps or share a sample Project?
My previous answer was from 2016. A lot changed in the meantime. The build process works completely different now and ConfuserEx failed me and I switched to BabelFor.Net.
Babel also has a feature to merge several dlls together into one. This has the big advantage, that all the public symbols (class and method names) can be renamed so that you don't find them in the result dll anymore. But getting this feature working with the build process in order that it continues without those merged assemblies was a big trouble point. So I decided to document it here again. Hopefully it will help others.
Here is what I did to get obfuscation work in Xamarin.Android 10:
In my .csproj I load a Obfuscate.targets file only in Release mode:
<Import Project="Obfuscate.targets" Condition=" '$(Configuration)' == 'Release' " />
In the beginning I had this stuff in my .csproj directly, but as it got too much, I didn't want to litter the .csproj with it.
The Obfuscate.targets file is something like this:
_BeforeLinkAssemblies executes the obfuscator at the exact right moment in the build process so that the rest works.
<MainAndroidAssembly Remove="@(MainAndroidAssembly)" />
<MainAndroidAssembly Include="@(ResolvedAssemblies)" Condition="'%(Filename)' == '$(AssemblyName)'" KeepMetadata="none" />
I could've also hardcoded the MainAndroidAssembly, but searching within ResolvedAssemblies makes sure that it also works when this runs somewhere else than usual.KeepMetadata="none" is not needed, but it makes the diagnostic log much more readable.
<MergeAssemblies Remove="@(MergeAssemblies)" />
<MergeAssemblies Include="@(ResolvedAssemblies)" Condition="'%(Filename)' == 'MergedAssembly1' Or '%(Filename)' == 'MergedAssembly2' Or '%(Filename)' == 'MergedAssembly3'" KeepMetadata="none" />
This gets the files with complete path to the merged assemblies. The obfuscator merges them directly into the MainAndroidAssembly so that these are not needed anymore.
<SearchDirectories Remove="@(SearchDirectories)" />
<SearchDirectories Include="@(ResolvedAssemblies -> '%(RootDir)%(Directory)')" KeepMetadata="none" />
SearchDirectories is a list of all folders where the dependencies of my solution are saved. Previously the build process copied them together into one folder (linksrc), but this has been removed.
Now call the obfuscator. I use BabelFor.Net, but I won't list all the parameters for calling it here, as it is not relevant for any other obfuscators.
<ResolvedAssemblies Remove="@(MergeAssemblies)" />
<ResolvedUserAssemblies Remove="@(MergeAssemblies)" />
After the obfuscation, the merged assemblies must be removed from ResolvedAssemblies and ResolvedUserAssemblies so that they are not included in the bundle/package.
Xamarin Inc., as a wholly-owned Microsoft subsidiary acting as a separate legal entity, adheres to the Microsoft Privacy Statement: Privacy & cookies