Configuración de la ofuscación
Con el paquete instalado, todas las funciones de Babel Obfuscator se configuran con propiedades y elementos de MSBuild en el archivo de proyecto. Esta página muestra los ajustes que más va a usar, función por función.
Cómo llegan los ajustes a Babel
El paquete define una propiedad o un elemento de MSBuild por cada atributo de la tarea Babel y los pasa a la tarea cuando se ejecuta el destino CoreObfuscate. La mayoría de las propiedades tienen el mismo nombre que el atributo de la tarea y aceptan los mismos valores que la opción correspondiente de la línea de comandos. Las que difieren, como BabelLicense, MergeInternalize o BabelRules, figuran en la tabla Asignación de propiedades.
Los ajustes se escriben en un PropertyGroup, normalmente condicionado a la configuración de compilación para que las compilaciones Debug sigan siendo legibles:
<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>Las listas de archivos se expresan como elementos de un ItemGroup: BabelRules, MergeAssembly, EmbedAssembly, MapInFile y BabelPlugin.
Las propiedades se evalúan antes de que se ejecute ningún destino, de modo que un valor establecido en el cuerpo del proyecto se aplica a toda la compilación. Para calcular un ajuste a partir de algo que solo se conoce durante la compilación, como la ruta resuelta de una referencia de paquete, establézcalo dentro del destino BeforeObfuscate. Consulte Reemplazar la configuración de la tarea.
Valores predeterminados que aplica el paquete
Sin ningún ajuste, un proyecto que hace referencia al paquete se ofusca de la manera siguiente:
- El renombrado de símbolos está activado para tipos, métodos, propiedades, campos, eventos y parámetros, incluidos los miembros virtuales, y los espacios de nombres se aplanan. La propiedad
SymbolsRenamingactiva o desactiva todo esto a la vez; las propiedades individualesObfuscateTypes,ObfuscateMethods,ObfuscateProperties,ObfuscateFields,ObfuscateEvents,ObfuscateParameters,VirtualFunctionsyFlattenNamespacesla reemplazan una por una. - Todas las demás funciones están desactivadas hasta que las active.
- Los símbolos de depuración se regeneran cuando el compilador ha generado un PDB junto al ensamblado (
GenerateDebugse establece automáticamente), de modo que las compilaciones ofuscadas siguen siendo depurables y las trazas de pila pueden descodificarse. - Los directorios de búsqueda de ensamblados se construyen a partir de las referencias del proyecto, de modo que Babel resuelve todas las dependencias que vio el compilador.
- El archivo de configuración de Babel se ignora (
NoConfigurationestrue), de modo que la compilación depende solo de lo que declara el proyecto. - Un archivo
babelRules.xmlen la carpeta del proyecto se detecta automáticamente. - La clave de nombre seguro que MSBuild resuelve para el proyecto (
KeyOriginatorFile, oKeyContainerName) se pasa a Babel, de modo que el ensamblado ofuscado se firma igual que el original.
Para desactivar el renombrado, en un proyecto de pruebas o en una pasada que solo cifra las cadenas:
<PropertyGroup>
<SymbolsRenaming>false</SymbolsRenaming>
</PropertyGroup>Reglas de ofuscación
Las reglas excluyen símbolos de una función o aplican una función a un conjunto de símbolos. Hay tres formas de proporcionarlas:
- Añada un archivo
babelRules.xmla la carpeta del proyecto: se usa automáticamente. - Haga referencia a cualquier número de archivos de reglas con elementos
BabelRules:
<ItemGroup>
<BabelRules Include="rules\renaming.xml" />
<BabelRules Include="rules\encryption.xml" />
</ItemGroup>- Escriba las reglas en línea en la propiedad
XmlRules, lo que resulta cómodo para un conjunto pequeño de reglas propio del proyecto:
<PropertyGroup>
<XmlRules>
<Rules>
<Rule name="rename public types" feature="renaming" exclude="false">
<Access>Public</Access>
<Pattern>*</Pattern>
</Rule>
</Rules>
</XmlRules>
</PropertyGroup>El ejemplo Aplicación Android usa una regla en línea para renombrar los tipos públicos, y el ejemplo Blazor Web App usa un archivo de reglas para ofuscar las clases que hay detrás de las páginas Razor. Las reglas también pueden asociarse al código con atributos personalizados.
Cifrado de cadenas
StringEncryption activa el cifrado de cadenas y selecciona el algoritmo, exactamente igual que la opción --stringencryption: true usa el algoritmo predeterminado, mientras que xor, hash, stream o custom seleccionan uno concreto. Consulte Algoritmos estándar para ver una comparación.
<PropertyGroup>
<StringEncryption>stream</StringEncryption>
</PropertyGroup>STREAM Ultimate es el algoritmo preferible para las plataformas de destino modernas: es totalmente administrado, por lo que funciona con el recorte, con NativeAOT y en hosts en modo FIPS, y está verificado desde .NET Framework hasta .NET 10, incluidos Android, iOS y .NET MAUI. En los proyectos Android, iOS y MAUI el paquete ya ejecuta Babel después de la compilación y antes del empaquetado, que es donde debe producirse el cifrado de cadenas para que la aplicación empaquetada lleve las cadenas cifradas. Las cadenas declaradas const no pueden cifrarse; consulte Cifrado de cadenas const.
Ofuscación del flujo de control
ControlFlowObfuscation acepta la misma lista de pares clave-valor que --controlflow, y ControlFlowIterations el número de pasadas (ILIterations se acepta como alias):
<PropertyGroup>
<ControlFlowObfuscation>goto=on;if=on;switch=on;case=on;call=on</ControlFlowObfuscation>
<ControlFlowIterations>3</ControlFlowIterations>
</PropertyGroup>La versión 12 añade el algoritmo Chained State Ultimate, una transformación de aplanamiento reforzada frente a los desofuscadores automáticos. Actívelo con chain=on, solo o junto con los demás algoritmos:
<PropertyGroup>
<ControlFlowObfuscation>switch=on;case=on;chain=on</ControlFlowObfuscation>
</PropertyGroup>El aplanamiento tiene un coste en tiempo de ejecución. Use reglas para no aplicarlo a los métodos de uso intensivo, como se explica en Rendimiento y ajuste fino.
Cifrado de código
MsilEncryption cifra los cuerpos de los métodos. true cifra todos los métodos elegibles, mientras que una expresión regular limita el cifrado a los métodos cuyo nombre completo coincide con ella:
<PropertyGroup>
<MsilEncryption>MyApp\.Licensing\..*</MsilEncryption>
</PropertyGroup>Consulte Cifrado de código para conocer el comportamiento en tiempo de ejecución, el código protegido por contraseña y los métodos que no pueden cifrarse.
Protección de valores, recursos y llamadas
<PropertyGroup>
<ValueEncryption>array=true;true</ValueEncryption>
<ResourceEncryption>true</ResourceEncryption>
<DynamicProxy>all</DynamicProxy>
<SuppressIldasm>true</SuppressIldasm>
<SuppressReflection>true</SuppressReflection>
</PropertyGroup>Cada propiedad acepta los valores de la opción correspondiente: consulte Cifrado de valores y matrices, Cifrado de recursos y Proxy dinámico.
Detección de manipulación y protección contra depuración
<PropertyGroup>
<TamperingDetection>true</TamperingDetection>
<DebuggingProtection>true</DebuggingProtection>
</PropertyGroup>En los destinos de escritorio, la comprobación de manipulación calcula el hash de la imagen cargada en memoria, por lo que es inerte en las aplicaciones de archivo único, recortadas o publicadas con AOT. El paquete pasa a Babel el ajuste PublishSingleFile del proyecto, y Babel emite una advertencia cuando se solicita la detección de manipulación para una publicación de ese tipo. Consulte Detección de manipulación y Protección contra depuración.
Integridad del paquete en Android e iOS Ultimate
A partir de la versión 12, en los destinos de .NET para Android e iOS (incluido .NET MAUI) la detección de manipulación verifica la integridad del paquete en lugar de la de la imagen: el certificado de firma del APK en Android, y el identificador del bundle y el identificador de equipo de Apple (Team ID) en iOS. Fije los valores esperados con las propiedades añadidas en esta versión:
<!-- 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 acepta varias huellas digitales separadas por punto y coma, por ejemplo la de una clave de subida y la de la clave de firma de aplicaciones de Google Play. Cómo obtener cada valor, y qué ocurre cuando falta un valor fijado, se explica en Integridad del paquete en Android (MAUI) e Integridad del paquete en iOS (MAUI). El ejemplo Aplicación Android muestra un archivo de proyecto Android completo.
AES administrado para hosts FIPS
Los descifradores en tiempo de ejecución que se inyectan para el cifrado de código, de cadenas (XOR y HASH), de valores y de recursos usan el proveedor criptográfico de la plataforma, y un host con una configuración FIPS de OpenSSL defectuosa no puede iniciar un ensamblado así. Desde la versión 11.8, encryption=aesmanaged selecciona en su lugar un descifrador administrado autónomo:
<PropertyGroup>
<MsilEncryption>true</MsilEncryption>
<Use>encryption=aesmanaged</Use>
</PropertyGroup>Use acepta cualquier par clave-valor que acepte la opción --use, separados por punto y coma, por ejemplo tagassembly=on. Consulte Conformidad con FIPS para conocer las contrapartidas del descifrador administrado.
Combinación e incrustación de ensamblados
Los elementos MergeAssembly y EmbedAssembly enumeran los ensamblados que se combinan con el ensamblado de destino o se incrustan en él. MergeInternalize convierte en internos los tipos públicos combinados, y MergeCopyAttributes controla si se copian sus atributos de nivel de ensamblado:
<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>Babel se ejecuta justo después de la compilación, antes de que el proceso de compilación copie las dependencias en la carpeta de salida, de modo que en una compilación limpia puede que una ruta bajo $(TargetDir) todavía no exista. El origen fiable es la lista de referencias resueltas para el compilador, que puede filtrar dentro del destino BeforeObfuscate:
<Target Name="BeforeObfuscate">
<ItemGroup>
<MergeAssembly Include="@(ReferencePathWithRefAssemblies)"
Condition="'%(Filename)' == 'Acme.View' Or '%(Filename)' == 'Acme.ViewModel'" />
</ItemGroup>
</Target>El paquete también quita los ensamblados combinados e incrustados del archivo .deps.json y del conjunto de publicación, de modo que dotnet publish no los distribuye dos veces. Consulte Combinar e incrustar para conocer la función y Publicación para los detalles relativos a la compilación.
Archivos map y renombrado entre ensamblados
GenerateMapOutFile escribe el archivo map XML del ensamblado ofuscado, que se usa para descodificar trazas de pila y para renombrar de forma coherente entre ensamblados la interfaz pública de una biblioteca. Los elementos MapInFile proporcionan a Babel los archivos map de los ensamblados ya ofuscados:
<PropertyGroup>
<GenerateMapOutFile>true</GenerateMapOutFile>
<BabelMapOutFile>$(SolutionDir)MapOut\$(TargetFileName).map.xml</BabelMapOutFile>
</PropertyGroup>
<ItemGroup>
<MapInFile Include="$(SolutionDir)MapOut\Acme.Core.dll.map.xml" />
</ItemGroup>Consulte Archivos map XML y Renombrado entre ensamblados. El ejemplo Pruebas unitarias usa un archivo map para ejecutar pruebas sobre una biblioteca ofuscada, y el ejemplo Publicar una aplicación .NET ofusca la interfaz pública de una dependencia NuGet y pasa su archivo map a la aplicación.
Optimizaciones
<PropertyGroup>
<DeadCodeElimination>true</DeadCodeElimination>
<SealClasses>true</SealClasses>
<EnumRemoval>true</EnumRemoval>
<ConstRemoval>true</ConstRemoval>
<DisgregateRemoval>true</DisgregateRemoval>
<InlineExpansion>true</InlineExpansion>
<CleanAttributes>true</CleanAttributes>
</PropertyGroup>Cada optimización se describe en Optimizaciones.
Complementos
Los elementos BabelPlugin hacen referencia a los ensamblados de complementos que se cargan, y PluginsArguments les pasa argumentos clave-valor. El complemento BabelEncrypt se incluye en el paquete, en la misma carpeta que las herramientas de compilación:
<ItemGroup>
<BabelPlugin Include="$(BabelTaskDir)BabelEncrypt.dll" />
</ItemGroup>
<PropertyGroup>
<PluginsArguments>dictionary=exclusionlist.txt</PluginsArguments>
</PropertyGroup>Consulte Complementos de Babel Obfuscator y el Encrypt Plugin.
Registro y diagnóstico
<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>VerboseLevelcontrola qué parte del registro de Babel llega a la salida de la compilación;GenerateLogFileyBabelLogFileguardan el registro completo en un archivo.BabelProvideCommandLineArgsmuestra la línea de comandos que el paquete pasa a Babel y la guarda en el elemento@(BabelCommandLineArgs).Traceacepta una expresión regular y explica, símbolo por símbolo, por qué una coincidencia se ha ofuscado o no: es la forma más rápida de depurar las reglas.BabelWarningsToIgnore,BabelWarningsAsErrorsyBabelWarningsAsInfosaceptan listas de códigos de advertencia y cambian la forma en que se notifican.MakeBabelProjectFileescribe un proyecto de MSBuild equivalente a la configuración actual, lo que resulta útil para reproducir una compilación con la tarea Babel o con la herramienta de línea de comandos.
Todas las propiedades que acepta el paquete figuran en la Referencia del paquete.