Forum Xamarin.Forms

Forms project and obfuscation

FrancMoralesFrancMorales JPMember ✭✭

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.


  • FrancMoralesFrancMorales JPMember ✭✭

    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).

  • MichaelRumplerMichaelRumpler ATMember ✭✭✭✭✭

    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.

  • FrancMoralesFrancMorales JPMember ✭✭

    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.

  • codemaster007codemaster007 USMember ✭✭

    I can do the obfuscation in xamarin android but in xamarin forms how do you obfuscate too dlls ? Any suggestions or hint?

  • codemaster007codemaster007 USMember ✭✭

    thanks for the answer.

  • huangjinshehuangjinshe USMember ✭✭✭

    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.

  • knottydevknottydev USMember ✭✭

    I had no issues using dotfuscator and following this guide:

    ... using the community edition and Visual Studio 2017 CE

  • devcatdevcat Member ✭✭


    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.

  • TonyCeliaTonyCelia USMember ✭✭

    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.

  • TonyCeliaTonyCelia USMember ✭✭

    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.

  • TonyCeliaTonyCelia USMember ✭✭
    edited November 2018

    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:

    1. Get ConfuserEx 1.0: git clone ConfuserEx
    2. Update dnlib: git submodule init; git submodule update;
    3. Build Confuser2.mono: Confuser.CLI (I used Visual Studio Community for Mac). 2 build warnings that looked harmless.
    4. Create my crproj file (similar @MichaelRumpler above but with Mac probePaths)
    5. Execute ConfuserEx: mono Confuser.CLI.exe -n app.crproj

    Confuser.CLI starts and fails with the output below:

     [INFO] ConfuserEx v1.0.0-2-g778190f Copyright (C) Ki 2014
     [INFO] Running on Unix, (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'...
     [INFO] Initializing...
    [DEBUG] Building pipeline...
    [INFO] Resolving dependencies...
    [DEBUG] Checking Strong Name...
    [DEBUG] Creating global .cctors...
    [DEBUG] Watermarking...
    [DEBUG] Executing 'Name analysis' phase...
    [DEBUG] Building VTables & identifier list...
    [DEBUG] Analyzing...
    [INFO] Processing module 'App.dll'...
    [DEBUG] Executing 'Invalid metadata addition' phase...
    [DEBUG] Executing 'Renaming' phase...
    [DEBUG] Renaming...
    [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
    at Confuser.Core.ConfuserEngine.RunPipeline (Confuser.Core.ProtectionPipeline pipeline, Confuser.Core.ConfuserContext context) [0x00106] in
    at Confuser.Core.ConfuserEngine.RunInternal (Confuser.Core.ConfuserParameters parameters, System.Threading.CancellationToken token) [0x0044c] in
    Failed at 4:48 PM, 0:00 elapsed.

  • MichaelRumplerMichaelRumpler ATMember ✭✭✭✭✭

    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.

  • TonyCeliaTonyCelia USMember ✭✭

    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.

  • ChdoulaChdoula JPMember ✭✭
    edited January 2019

    @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

  • Cansado2930Cansado2930 ESMember ✭✭

    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?

  • MichaelRumplerMichaelRumpler ATMember ✭✭✭✭✭

    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:

    <Project xmlns="">

    _BeforeLinkAssemblies executes the obfuscator at the exact right moment in the build process so that the rest works.

        <Target Name="Obfuscate">
                <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.

            <ObfuscateTask />

    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.

Sign In or Register to comment.