Un unico file offuscato: unire le dipendenze
Distribuire un’applicazione insieme alle DLL delle sue dipendenze offre a un attaccante una superficie più ampia, e di solito quelle librerie non sono affatto offuscate. Questo esempio usa il pacchetto NuGet di Babel Obfuscator per unire un assembly referenziato all’host, internalizzare i suoi tipi pubblici e offuscare il risultato, così distribuisci un unico file autosufficiente, senza librerie sparse e leggibili.
Per usare questo esempio ti serve una licenza per sede di Babel Obfuscator (edizioni Ultimate, Server o Data Center). Il codice sorgente è disponibile su GitHub:
git clone https://github.com/babelfornet/single-file-merge-nuget-example.gitPaymentCore è una normale libreria di classi con un’API pubblica (src/PaymentCore/PaymentProcessor.cs)
che Checkout usa come qualsiasi dipendenza:
// 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.90Dopo la build, PaymentProcessor è un tipo interno e rinominato dentro Checkout.dll: non c’è alcun
PaymentCore.dll da distribuire. Il progetto console Checkout fa riferimento alla libreria e la
unisce a sé con due proprietà MSBuild 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 unisce all’output gli assembly referenziati, e Internalize rende internal i
tipi pubblici uniti, così possono essere rinominati e non fanno più parte di alcuna superficie
pubblica. Il pacchetto Babel esegue l’unione prima dei passi
successivi dell’SDK (risoluzione delle dipendenze, trimming, creazione del bundle a file singolo) e
mantiene coerente dotnet publish aggiornando il file .deps.json e l’insieme dei file pubblicati.
La build dell’esempio in Release produce un solo Checkout.dll (PaymentCore.dll non è più presente
perché è stato unito) e l’applicazione viene eseguita da quell’unico file con un output identico.
Se preferisci mantenere una dipendenza come blob cifrato opaco anziché unirne i tipi, usa
EmbedAssemblies.