# Configuring Obfuscation

With the package installed, every Babel Obfuscator feature is configured with
MSBuild properties and items in the project file. This page shows the
settings you will use most, feature by feature.

## How Settings Reach Babel

The package defines one MSBuild property or item for each attribute of the [Babel task](https://docs.babelfor.net/obfuscator/msbuild-task/babel-task-reference), and passes them to the task when the `CoreObfuscate` target runs. Most properties have the same name as the task attribute and accept the same values as the corresponding [command line](https://docs.babelfor.net/obfuscator/command-line/reference) switch. The ones that differ, such as `BabelLicense`, `MergeInternalize` or `BabelRules`, are listed in the [Property Mapping](https://docs.babelfor.net/obfuscator/nuget-package/reference#property-mapping) table.

Settings go in a `PropertyGroup`, usually conditioned on the build configuration so that Debug builds stay readable:

```xml
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
  <StringEncryption>stream</StringEncryption>
  <ControlFlowObfuscation>if=on;switch=on;call=on</ControlFlowObfuscation>
  <ControlFlowIterations>3</ControlFlowIterations>
  <ValueEncryption>true</ValueEncryption>
  <ResourceEncryption>true</ResourceEncryption>
  <DebuggingProtection>true</DebuggingProtection>
  <VerboseLevel>2</VerboseLevel>
</PropertyGroup>
```

Lists of files are expressed as items in an `ItemGroup`: `BabelRules`, `MergeAssembly`, `EmbedAssembly`, `MapInFile` and `BabelPlugin`.

> **Info:** Properties are evaluated before any target runs, so a value set in the project body applies to the whole build. To compute a setting from something that is only known while building, such as the resolved path of a package reference, set it inside the `BeforeObfuscate` target instead. See [Overriding the Task Configuration](https://docs.babelfor.net/obfuscator/nuget-package/build-pipeline#overriding-the-task-configuration).

## Defaults Applied by the Package

Without any setting, a project that references the package is obfuscated as follows:

- **Symbol renaming is on** for types, methods, properties, fields, events and parameters, virtual members included, and namespaces are flattened. The `SymbolsRenaming` property switches all of these at once; the individual `ObfuscateTypes`, `ObfuscateMethods`, `ObfuscateProperties`, `ObfuscateFields`, `ObfuscateEvents`, `ObfuscateParameters`, `VirtualFunctions` and `FlattenNamespaces` properties override it one by one.
- **Every other feature is off** until you enable it.
- **Debug symbols are regenerated** when the compiler produced a PDB next to the assembly (`GenerateDebug` is set automatically), so obfuscated builds stay debuggable and stack traces can be [decoded](https://docs.babelfor.net/obfuscator/symbols-renaming/decoding-stack-traces).
- **Assembly search directories** are built from the project references, so Babel resolves every dependency the compiler saw.
- **The Babel configuration file is ignored** (`NoConfiguration` is `true`), so the build depends only on what the project declares.
- A **`babelRules.xml`** file in the project folder is picked up automatically.
- The **strong-name key** resolved by MSBuild for the project (`KeyOriginatorFile`, or `KeyContainerName`) is passed to Babel, so the obfuscated assembly is signed like the original.

To turn renaming off, for a test project or for a string-encryption-only pass:

```xml
<PropertyGroup>
  <SymbolsRenaming>false</SymbolsRenaming>
</PropertyGroup>
```

## Obfuscation Rules

[Rules](https://docs.babelfor.net/obfuscator/obfuscation-rules) exclude symbols from a feature or apply a feature to a set of symbols. There are three ways to provide them:

- Add a `babelRules.xml` file to the project folder: it is used automatically.
- Reference any number of rules files with `BabelRules` items:

```xml
<ItemGroup>
  <BabelRules Include="rules\renaming.xml" />
  <BabelRules Include="rules\encryption.xml" />
</ItemGroup>
```

- Write the rules inline in the `XmlRules` property, which is convenient for a small set of rules that belongs to the project:

```xml
<PropertyGroup>
  <XmlRules>
    <Rules>
      <Rule name="rename public types" feature="renaming" exclude="false">
        <Access>Public</Access>
        <Pattern>*</Pattern>
      </Rule>
    </Rules>
  </XmlRules>
</PropertyGroup>
```

The [Android Application](https://docs.babelfor.net/obfuscator/examples/nuget-package/android-application) example uses an inline rule to rename public types, and the [Blazor Web App](https://docs.babelfor.net/obfuscator/examples/general-samples/blazor-web-app) example uses a rules file to obfuscate the classes behind Razor pages. Rules can also be attached to the code with [custom attributes](https://docs.babelfor.net/obfuscator/obfuscation-rules/custom-attributes).

## String Encryption

`StringEncryption` enables string encryption and selects the algorithm, exactly like the `--stringencryption` switch: `true` uses the default algorithm, while `xor`, `hash`, `stream` or `custom` selects one. See [Standard Algorithms](https://docs.babelfor.net/obfuscator/string-encryption/standard-algorithms) for a comparison.

```xml
<PropertyGroup>
  <StringEncryption>stream</StringEncryption>
</PropertyGroup>
```

STREAM (Ultimate) is the algorithm to prefer for modern targets: it is fully managed, so it works with trimming, NativeAOT and on FIPS-constrained hosts, and it is verified from .NET Framework through .NET 10, Android, iOS and .NET MAUI included. On Android, iOS and MAUI projects the package already runs Babel after compilation and before packaging, which is where string encryption has to happen for the packaged app to carry the encrypted strings. Strings declared `const` cannot be encrypted; see [Encryption of Const Strings](https://docs.babelfor.net/obfuscator/string-encryption#encryption-of-const-strings).

## Control Flow Obfuscation

`ControlFlowObfuscation` takes the same key-value list as `--controlflow`, and `ControlFlowIterations` the number of passes (`ILIterations` is accepted as an alias):

```xml
<PropertyGroup>
  <ControlFlowObfuscation>goto=on;if=on;switch=on;case=on;call=on</ControlFlowObfuscation>
  <ControlFlowIterations>3</ControlFlowIterations>
</PropertyGroup>
```

Version 12 adds the [Chained State](https://docs.babelfor.net/obfuscator/control-flow-obfuscation/chained-state) algorithm (Ultimate) as a flattening transform hardened against automated deobfuscators. Enable it with `chain=on`, alone or together with the other algorithms:

```xml
<PropertyGroup>
  <ControlFlowObfuscation>switch=on;case=on;chain=on</ControlFlowObfuscation>
</PropertyGroup>
```

Flattening has a runtime cost. Use rules to keep it off hot methods, as explained in [Performance & Tuning](https://docs.babelfor.net/obfuscator/control-flow-obfuscation/performance).

## Code Encryption

`MsilEncryption` encrypts method bodies. `true` encrypts every eligible method, while a regular expression restricts encryption to the methods whose full name matches it:

```xml
<PropertyGroup>
  <MsilEncryption>MyApp\.Licensing\..*</MsilEncryption>
</PropertyGroup>
```

See [Code Encryption](https://docs.babelfor.net/obfuscator/code-encryption) for the runtime behaviour, password-protected code and the methods that cannot be encrypted.

## Value, Resource and Call Protection

```xml
<PropertyGroup>
  <ValueEncryption>array=true;true</ValueEncryption>
  <ResourceEncryption>true</ResourceEncryption>
  <DynamicProxy>all</DynamicProxy>
  <SuppressIldasm>true</SuppressIldasm>
  <SuppressReflection>true</SuppressReflection>
</PropertyGroup>
```

Each property accepts the values of the corresponding switch: see [Value and Array Encryption](https://docs.babelfor.net/obfuscator/value-and-array-encryption), [Resource Encryption](https://docs.babelfor.net/obfuscator/resource-encryption) and [Dynamic Proxy](https://docs.babelfor.net/obfuscator/dynamic-proxy).

## Tampering Detection and Anti-Debugging

```xml
<PropertyGroup>
  <TamperingDetection>true</TamperingDetection>
  <DebuggingProtection>true</DebuggingProtection>
</PropertyGroup>
```

On desktop targets the tampering check hashes the loaded image in memory, so it is inert in single-file, trimmed or AOT-published applications. The package forwards the project's `PublishSingleFile` setting to Babel, which warns when tampering detection is requested for such a publish. See [Tampering Detection](https://docs.babelfor.net/obfuscator/tampering-detection) and [Anti-Debugging](https://docs.babelfor.net/obfuscator/anti-debugging).

### Android and iOS package integrity (Ultimate)

Starting with version 12, on .NET for Android and iOS targets (.NET MAUI included) tampering detection verifies the integrity of the package instead of the image: the APK signing certificate on Android, the bundle identifier and the Apple Team ID on iOS. Pin the expected values with the properties added in this version:

```xml
<!-- Android: SHA-256 fingerprint of the release signing certificate -->
<PropertyGroup Condition="$(TargetFramework.Contains('-android'))">
  <TamperingDetection>true</TamperingDetection>
  <TrustedSigner>2924C53EE9C511E9F26E0720FD8151064F7621681667D7AB1899E551CDB25104</TrustedSigner>
</PropertyGroup>

<!-- iOS: bundle identifier and Apple Team ID -->
<PropertyGroup Condition="$(TargetFramework.Contains('-ios'))">
  <TamperingDetection>true</TamperingDetection>
  <TrustedBundle>com.mycompany.myapp</TrustedBundle>
  <TrustedTeam>ABCDE12345</TrustedTeam>
</PropertyGroup>
```

`TrustedSigner` accepts several fingerprints separated by semicolons, for example an upload key and the Google Play app-signing key. How to obtain each value, and what happens when a pin is missing, is explained in [Android (MAUI) Package Integrity](https://docs.babelfor.net/obfuscator/tampering-detection#android-maui-package-integrity) and [iOS (MAUI) Package Integrity](https://docs.babelfor.net/obfuscator/tampering-detection#ios-maui-package-integrity). The [Android Application](https://docs.babelfor.net/obfuscator/examples/nuget-package/android-application) example shows a complete Android project file.

## Managed AES for FIPS Hosts

The runtime decryptors injected for code, string (XOR and HASH), value and resource encryption use the platform cryptographic provider, and a host with a broken OpenSSL FIPS configuration cannot start such an assembly. Since version 11.8, `encryption=aesmanaged` selects a self-contained managed decryptor instead:

```xml
<PropertyGroup>
  <MsilEncryption>true</MsilEncryption>
  <Use>encryption=aesmanaged</Use>
</PropertyGroup>
```

`Use` accepts any key-value pair accepted by the `--use` switch, separated by semicolons, for example `tagassembly=on`. See [FIPS Compliance](https://docs.babelfor.net/obfuscator/fips-compliance) for the trade-offs of the managed decryptor.

## Merging and Embedding Assemblies

`MergeAssembly` and `EmbedAssembly` items list the assemblies to merge into, or embed in, the target assembly. `MergeInternalize` makes the merged public types internal, and `MergeCopyAttributes` controls whether their assembly-level attributes are copied:

```xml
<ItemGroup>
  <MergeAssembly Include="$(TargetDir)Acme.View.dll" />
  <MergeAssembly Include="$(TargetDir)Acme.ViewModel.dll" />
  <EmbedAssembly Include="$(TargetDir)Framework.Mvvm.dll" />
</ItemGroup>
<PropertyGroup>
  <MergeInternalize>true</MergeInternalize>
</PropertyGroup>
```

> **Info:** Babel runs right after compilation, before the build copies dependencies to the output folder, so on a clean build a path under `$(TargetDir)` may not exist yet. The reliable source is the list of references resolved for the compiler, which you can filter inside the `BeforeObfuscate` target:
>
> ```xml
> <Target Name="BeforeObfuscate">
>   <ItemGroup>
>     <MergeAssembly Include="@(ReferencePathWithRefAssemblies)"
>                    Condition="'%(Filename)' == 'Acme.View' Or '%(Filename)' == 'Acme.ViewModel'" />
>   </ItemGroup>
> </Target>
> ```

The package also removes merged and embedded assemblies from the `.deps.json` file and from the publish set, so `dotnet publish` does not ship them twice. See [Merge and Embed](https://docs.babelfor.net/obfuscator/merge-and-embed) for the feature and [Publishing](https://docs.babelfor.net/obfuscator/nuget-package/build-pipeline#publishing) for the build-side details.

## Map Files and Cross-Assembly Renaming

`GenerateMapOutFile` writes the XML map file of the obfuscated assembly, used to decode stack traces and to rename the public interface of a library consistently across assemblies. `MapInFile` items feed the map files of already obfuscated assemblies back to Babel:

```xml
<PropertyGroup>
  <GenerateMapOutFile>true</GenerateMapOutFile>
  <BabelMapOutFile>$(SolutionDir)MapOut\$(TargetFileName).map.xml</BabelMapOutFile>
</PropertyGroup>
<ItemGroup>
  <MapInFile Include="$(SolutionDir)MapOut\Acme.Core.dll.map.xml" />
</ItemGroup>
```

See [XML Map Files](https://docs.babelfor.net/obfuscator/symbols-renaming/xml-map-files) and [Cross Assembly Renaming](https://docs.babelfor.net/obfuscator/symbols-renaming/cross-assembly-renaming). The [Unit Tests](https://docs.babelfor.net/obfuscator/examples/build-servers/unit-tests) example uses a map file to run tests against an obfuscated library, and the [Publish .NET App](https://docs.babelfor.net/obfuscator/examples/cross-assembly-renaming/publish-.net-app) example obfuscates the public interface of a NuGet dependency and feeds its map file to the application.

## Optimizations

```xml
<PropertyGroup>
  <DeadCodeElimination>true</DeadCodeElimination>
  <SealClasses>true</SealClasses>
  <EnumRemoval>true</EnumRemoval>
  <ConstRemoval>true</ConstRemoval>
  <DisgregateRemoval>true</DisgregateRemoval>
  <InlineExpansion>true</InlineExpansion>
  <CleanAttributes>true</CleanAttributes>
</PropertyGroup>
```

Each optimization is described in [Optimizations](https://docs.babelfor.net/obfuscator/optimizations).

## Plugins

`BabelPlugin` items reference the plugin assemblies to load, and `PluginsArguments` passes key-value arguments to them. The `BabelEncrypt` plugin ships inside the package, in the same folder as the build tools:

```xml
<ItemGroup>
  <BabelPlugin Include="$(BabelTaskDir)BabelEncrypt.dll" />
</ItemGroup>
<PropertyGroup>
  <PluginsArguments>dictionary=exclusionlist.txt</PluginsArguments>
</PropertyGroup>
```

See [Babel Obfuscator Plugins](https://docs.babelfor.net/obfuscator/plugins/babel-obfuscator-plugins) and the [Encrypt Plugin](https://docs.babelfor.net/obfuscator/plugins/encrypt-plugin).

## Logging and Diagnostics

```xml
<PropertyGroup>
  <VerboseLevel>3</VerboseLevel>
  <GenerateLogFile>true</GenerateLogFile>
  <BabelLogFile>$(IntermediateOutputPath)babel.log</BabelLogFile>
  <BabelProvideCommandLineArgs>true</BabelProvideCommandLineArgs>
  <ShowStatistics>true</ShowStatistics>
  <Trace>MyApp\.Services\..*</Trace>
  <BabelWarningsToIgnore>W00008</BabelWarningsToIgnore>
  <BabelWarningsAsErrors>W00000</BabelWarningsAsErrors>
</PropertyGroup>
```

- `VerboseLevel` controls how much of the Babel log reaches the build output; `GenerateLogFile` and `BabelLogFile` save the complete log to a file.
- `BabelProvideCommandLineArgs` prints the command line the package passes to Babel and stores it in the `@(BabelCommandLineArgs)` item.
- `Trace` takes a regular expression and explains, symbol by symbol, why a match was or was not obfuscated: the fastest way to debug rules.
- `BabelWarningsToIgnore`, `BabelWarningsAsErrors` and `BabelWarningsAsInfos` take lists of warning codes and change how they are reported.
- `MakeBabelProjectFile` writes an MSBuild project equivalent to the current configuration, which is useful to reproduce a build with the [Babel task](https://docs.babelfor.net/obfuscator/msbuild-task) or the [command line tool](https://docs.babelfor.net/obfuscator/nuget-package/babel-tool).

Every property accepted by the package is listed in the [Package Reference](https://docs.babelfor.net/obfuscator/nuget-package/reference).
