Defensa en profundidad: todas las capas en una sola compilación
Una protección sólida no se consigue con un único truco: se consigue con capas. Este ejemplo activa todas las protecciones del paquete NuGet de Babel Obfuscator en un ensamblado pequeño, de modo que puede ver la configuración completa de Ultimate en un único archivo de proyecto y adaptarla a su propia aplicación.
Para usar este ejemplo necesita una licencia de sitio de Babel Obfuscator (ediciones Ultimate, Server o Data Center). El código fuente está disponible en GitHub:
git clone https://github.com/babelfornet/defense-in-depth-nuget-example.gitLa aplicación es un pequeño control de acceso a funciones (src/LicenseGate/FeatureGate.cs) que
contiene justo el tipo de elementos que protege cada capa: cadenas, pesos numéricos, una matriz y
lógica con bifurcaciones:
internal static class FeatureGate
{
private static readonly int[] Weights = { 3, 7, 11, 13, 17, 19, 23, 29, 31, 37 };
private static readonly string Pepper = "d3f3ns3-1n-d3pth-pepper";
public static GateReport Evaluate(string edition, int tokens, double budget)
{
bool allowed = edition is "PRO" or "ENTERPRISE" && tokens > 0 && budget >= 100.0;
double score = 0.0;
for (int i = 0; i < Weights.Length; i++)
score += Weights[i] * (tokens + 1) * 0.5;
return new GateReport(edition, allowed, Math.Round(score / budget, 4), Digest(edition, tokens));
}
// Digest …
}El proyecto de consola LicenseGate apila las capas en Release:
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<!-- Rename & restructure -->
<FlattenNamespaces>true</FlattenNamespaces>
<OverloadedRenaming>true</OverloadedRenaming>
<VirtualFunctions>true</VirtualFunctions>
<!-- Hide data -->
<StringEncryption>stream</StringEncryption>
<ValueEncryption>int32=true;int64=true;single=true;double=true;array=true;true</ValueEncryption>
<ResourceEncryption>true</ResourceEncryption>
<!-- Obscure logic -->
<ControlFlowObfuscation>if=true;switch=true;case=true;chain=true;true</ControlFlowObfuscation>
<ControlFlowIterations>3</ControlFlowIterations>
<DynamicProxy>external=true;true</DynamicProxy>
<!-- Detect & deter runtime attacks -->
<TamperingDetection>true</TamperingDetection>
<DebuggingProtection>true</DebuggingProtection>
<SuppressIldasm>true</SuppressIldasm>
<!-- Strip metadata -->
<CleanAttributes>true</CleanAttributes>
<SealClasses>true</SealClasses>
<BabelWarningsAsErrors>W00000</BabelWarningsAsErrors>
</PropertyGroup>Cada propiedad añade una capa: el renombrado y el aplanamiento de espacios de nombres ocultan la
intención; el cifrado de cadenas, de valores y de recursos oculta los datos; el flujo de control y el
proxy dinámico ocultan la lógica; la detección de manipulación y la protección contra depuración
disuaden de los ataques en tiempo de ejecución; y la limpieza de metadatos elimina lo que la aplicación
en ejecución no necesita. Como el paquete es una dependencia solo de compilación (PrivateAssets=all),
nada de esto se filtra al grafo de dependencias de la aplicación, y los pasos posteriores del SDK
trabajan sobre el ensamblado ya protegido.
Al compilar el ejemplo en Release se aplica todo lo anterior sin que cambie la salida del programa; abra el resultado en un descompilador y compárelo con la compilación Debug para ver la diferencia. Esto refleja las indicaciones de Mejora de la seguridad del código: parta de esta configuración y quite las capas que no necesite.