Skip to Content
New release 12 available 🎉
ObfuscatorNuGet PackageSingle-File Merge

One Obfuscated File: Merging Dependencies

Shipping an application together with its dependency DLLs gives an attacker more surface, and those libraries are usually not obfuscated at all. This example uses the Babel Obfuscator NuGet package to merge a referenced assembly into the host, internalize its public types and obfuscate the result, so you deliver a single self-contained file with no loose, readable libraries.

To use this example you need a site license for Babel Obfuscator (Ultimate, Server or Data Center editions). The source code is available on GitHub:

git clone https://github.com/babelfornet/single-file-merge-nuget-example.git

PaymentCore is an ordinary class library with a public API (src/PaymentCore/PaymentProcessor.cs) that Checkout uses like any dependency:

// PaymentCore (the dependency) public sealed class PaymentProcessor { public PaymentProcessor(decimal feeRate) => _feeRate = feeRate; public decimal Charge(decimal amount) => amount + Math.Round(amount * _feeRate, 2); } // Checkout (the host) var processor = new PaymentProcessor(feeRate: 0.029m); Console.WriteLine(processor.Charge(100.00m)); // 102.90

After the build, PaymentProcessor is an internal, renamed type inside Checkout.dll — there is no PaymentCore.dll to ship. The Checkout console project references the library and folds it in with two MSBuild properties in Release:

<ItemGroup> <ProjectReference Include="..\PaymentCore\PaymentCore.csproj" /> </ItemGroup> <ItemGroup Condition="'$(Configuration)' == 'Release'"> <PackageReference Include="Babel.Obfuscator" Version="12.0.0"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> </ItemGroup> <PropertyGroup Condition="'$(Configuration)' == 'Release'"> <MergeAssemblies>true</MergeAssemblies> <Internalize>true</Internalize> <StringEncryption>hash</StringEncryption> <BabelWarningsAsErrors>W00000</BabelWarningsAsErrors> </PropertyGroup>

MergeAssemblies folds the referenced assemblies into the output, and Internalize changes the merged public types to internal so they can be renamed and are no longer part of any public surface. The Babel package runs the merge before the SDK’s later steps (dependency resolution, trimming, single-file bundling) and keeps dotnet publish consistent by updating the .deps.json file and the set of published files.

Building the sample in Release produces a single Checkout.dll — PaymentCore.dll is no longer present because it was merged in — and the application runs from that one file with identical output. If you would rather keep a dependency as an opaque encrypted blob than merge its types, use EmbedAssemblies instead.

Last updated on