Skip to main content
Version: 2023.4

4.8. Assemblies Merging

4.8.1. Introduction

Assemblies merging allows to merge several assemblies into one. This may be beneficial from the deployment and security points of view.

By default, assemblies merging is not used during the obfuscation of the assembly.

4.8.2. Instructions

To enable assemblies merging, you should apply specially formed attribute(s) to your assembly. To do that, you can use the instructions below.

Instructions on enabling assemblies merging

  1. Open obfuscatable project inside the IDE

  2. Add new source file to the project and call it ObfuscationSettings.cs (for C#) or ObfuscationSettings.vb (for Visual Basic .NET). You may prefer to use another name instead of ObfuscationSettings.cs or ObfuscationSettings.vb

  3. Fill ObfuscationSettings.cs with the following content (C#):

    using System;
    using System.Reflection;

    [assembly: Obfuscation(Feature = "merge with XXXXXX.dll", Exclude = false)]

    For Visual Basic .NET, fill ObfuscationSettings.vb with the following content:

    Imports System
    Imports System.Reflection

    <Assembly: Obfuscation(Feature:="merge with XXXXXX.dll", Exclude:=False)>
    Note

    Change XXXXXX.dll with the file name of the assembly you want to merge with.

    Tip

    Eazfuscator.NET automatically finds the assembly path when only the file name is supplied.
    If you prefer to specify the exact file path to assembly, then you can use script variables:

    [assembly: Obfuscation(Feature = @"merge with $(InputDir)\Lib\AssemblyToMerge.dll", Exclude = false)]
    Tip

    If you want to merge with several assemblies, then just add several attributes:

    [assembly: Obfuscation(Feature = "merge with Assembly1.dll", Exclude = false)]
    [assembly: Obfuscation(Feature = "merge with AnotherAssembly2.dll", Exclude = false)]

    Tip

    You can use assembly mask syntax to bulk select the assemblies you want to merge with:

    [assembly: Obfuscation(Feature = "merge with Contoso.Dal.*.dll", Exclude = false)]
Note

Usage of assemblies merging may lead to some side effects, which may make obfuscation fail. If such is the case, then use the least common denominator principle – merge just those assemblies that do not cause obfuscation failure.
Assemblies embedding can be used in conjunction or as an alternative to assemblies merging.

4.8.3. Tuning

The full notation of a custom attribute for assembly merging has the following form:

[assembly: Obfuscation(Feature = "merge with [flags] XXXXXX.dll", Exclude = false)]

Flags

The [flags] is an optional sequence of flags separated by spaces and enclosed in [] brackets. The available flags are grouped by purpose and described in the tables below.

Table 4.6. The list of general flags for assembly merging directive

Flag

Description

satellites

Enables automatic merging of satellite assemblies

xml-documentation

Enables merging of XML documentation

log

In addition to merging, logs all the assemblies targeted by the directive

Table 4.7. The list of type internalization flags for assembly merging directive

Flag

Description

internalization=auto

Instructs Eazfuscator.NET to automatically decide which public merged types should be internalized. This is the default setting. The typical decision is to internalize a given type. At the same time, the type internalization can be inhibited, for example, by the fact that some kinds of WPF controls cannot have internal visibility

internalization=none

Disables the internalization of public merged types

internalization=full

Instructs Eazfuscator.NET to internalize all public merged types

Table 4.8. The list of assembly inclusion flags for assembly merging directive

Flag

Description

include=auto

Instructs Eazfuscator.NET to automatically decide whether to merge the specified assembly or not. A typical behavior is to always merge the explicitly specified assemblies. The assemblies specified by a mask are only merged if they are referenced by code. This is the default setting

include=all

Always merge the assembly even if it is not referenced by code. This is a useful setting if the assembly specified by a mask is not directly used by the code but instead engaged in a reflection scenario

include=referenced

Merge the assembly only if it is referenced by code

Examples

Example 4.29. Merge with assembly and its satellite assemblies

using System;
using System.Reflection;

[assembly: Obfuscation(Feature = "merge with [satellites] XXXXXX.dll", Exclude = false)]

Example 4.30. Merge with assembly and its satellite assemblies; do not internalize public merged types

using System;
using System.Reflection;

[assembly: Obfuscation(Feature = "merge with [satellites internalization=none] XXXXXX.dll", Exclude = false)]

4.8.4. Internalization

Internalization changes the visibility of merged classes from public to internal. By default, classes from merged assemblies are automatically internalized to improve obfuscation coverage.

That's fine for most scenarios, but sometimes you may want to change that for some specific classes. Please follow the instructions below to achieve it.

Instructions on disabling internalization for a specific class

  1. Open the source code of a class

  2. Add a custom attribute as shown below (C#):

    using System;
    using System.Reflection;

    [Obfuscation(Feature = "internalization", Exclude = true)]
    public class YourClass
    {
    ...
    }

    For Visual Basic .NET:

    Imports System
    Imports System.Reflection

    <Obfuscation(Feature:="internalization", Exclude:=True)>
    Class YourClass
    ...
    End Class
    Important

    Conditional obfuscation is not available for this feature.

4.8.5. Distribution Considerations

Assembly merging changes the set of assemblies that should be distributed with the obfuscated app. This change requires excluding the merged assemblies from the distribution. Eazfuscator.NET does most of this work automatically. However, in some cases, you may need to put extra effort into excluding the specific assemblies from being distributed.

4.8.6. Custom Parameters for Merging

Sometimes you may need to pass custom parameters for assembly merging. For example, you may prefer to control class internalization yourself or use some tricky merging feature.

Historically Eazfuscator.NET relied on ILMerge utility in the past. Now it is equipped with its own compatible merger since version 4.1. The new merger understands most of ILMerge configuration parameters and can be configured in the very same way. Please refer to ILMerge documentation for the list of available parameters.

Instructions on passing custom parameters to the merger

  1. Open obfuscatable project inside the IDE

  2. Add new source file to the project and call it ObfuscationSettings.cs (for C#) or ObfuscationSettings.vb (for Visual Basic .NET). You may prefer to use another name instead of ObfuscationSettings.cs or ObfuscationSettings.vb

  3. Fill ObfuscationSettings.cs with the following content (C#):

    using System;
    using System.Reflection;

    [assembly: Obfuscation(Feature = "ilmerge custom parameters: <parameters>", Exclude = false)]

    For Visual Basic .NET, fill ObfuscationSettings.vb with the following content:

    Imports System
    Imports System.Reflection

    <Assembly: Obfuscation(Feature:="ilmerge custom parameters: <parameters>", Exclude:=False)>
    Note

    Change <parameters> with the parameters you want to pass to the merger. Eazfuscator.NET passes /internalize /ndebug parameters by default when no attribute is defined. If you do not want to pass any parameters to the merger, then change <parameters> with none string.