Skip to Content
Nueva versión 12 disponible 🎉
ObfuscatorRenombrado de símbolosRenombrado entre ensamblados

Renombrado entre ensamblados

Durante el proceso de ofuscación, Babel Obfuscator renombra todos los símbolos que no son visibles desde el exterior del ensamblado, es decir, los símbolos privados e internos. Esto significa que Babel cambia los nombres de los campos, métodos, clases y demás elementos de código que no están pensados para que se acceda a ellos desde fuera del ensamblado.

Babel no renombra los símbolos visibles desde el exterior del ensamblado, como los símbolos públicos. El motivo es que los símbolos públicos están pensados para que otros ensamblados accedan a ellos, y renombrarlos rompería el funcionamiento de la aplicación. Por eso Babel solo renombra los símbolos a los que otros ensamblados no deben acceder, de modo que la aplicación sigue funcionando como se espera.

No obstante, Babel permite ofuscar tanto los miembros públicos como los internos en varios ensamblados. Para ello corrige, mediante archivos map XML, los nombres de los símbolos ofuscados a los que hace referencia cada ensamblado.

Esto es necesario porque, cuando se ofusca un ensamblado, los nombres de sus símbolos cambian. Por tanto, cualquier referencia a esos símbolos desde otro ensamblado debe actualizarse para reflejar los nombres nuevos. Al indicar los archivos map XML de entrada y de salida, Babel Obfuscator puede usarlos para corregir las referencias de nombres cruzadas entre todos los ensamblados que participan. Así el código ofuscado funciona correctamente y no falla por nombres de símbolos incorrectos.

Es importante mantener privados los archivos map y no distribuirlos en ningún caso con la aplicación ofuscada, ya que pueden usarse para revertir la ofuscación y comprometer la seguridad de la aplicación.

Configurar el renombrado entre ensamblados

Para configurar el renombrado entre ensamblados hay que tener en cuenta todos los ensamblados que participan en el proceso de renombrado. Considere el ensamblado principal de la aplicación, MainAssembly.dll, que usa la interfaz pública de dos componentes externos: Library1.dll y Library2.dll. A su vez, Library1.dll también necesita acceder a la interfaz pública de Library2.dll, según el esquema siguiente:

  • MainAssembly.dll
    1. Library1.dll
    2. Library2.dll
  • Library1.dll
    1. Library2.dll

Esta configuración muestra las relaciones entre los ensamblados que intervienen en el proceso de ofuscación. El primer paso es configurar Babel para que ofusque los símbolos públicos de Library1.dll y Library2.dll. Para ello, añada el siguiente atributo personalizado de nivel de ensamblado al código fuente de ambas bibliotecas:

[assembly: System.Reflection.ObfuscateAssembly(true)]

Este atributo indica a Babel que ofusque los símbolos públicos del ensamblado especificado sin necesidad de archivos de reglas XML externos. Al establecer el parámetro Boolean en true, la interfaz pública del ensamblado se trata como privada, lo que permite ofuscar con seguridad los nombres de los miembros públicos.

Como alternativa, puede configurar Babel para que renombre la interfaz pública de un ensamblado mediante un archivo de reglas XML. Este método ofrece más flexibilidad y control, y permite ofuscar de forma selectiva partes de la interfaz pública. A continuación se muestra un ejemplo de archivo de reglas XML llamado public.xml que fuerza la ofuscación de todos los nombres de miembros públicos:

<Rules> <Rule name="obfuscate public" exclude="false"> <Access>Public</Access> <Pattern isRegEx="false">*</Pattern> <Description>Obfuscate all public symbols.</Description> </Rule> </Rules>

En comparación con el atributo ObfuscateAssembly, las reglas XML ofrecen un control más detallado sobre los símbolos públicos que se ofuscan. Con la expresión Pattern puede indicar qué partes de la interfaz pública deben ofuscarse, lo que permite estrategias de ofuscación a medida.

En este punto, Library1.dll y Library2.dll están configuradas para usar el atributo ObfuscateAssembly o el archivo de reglas XML (en este caso, public.xml)

  • MainAssembly.dll
  • Library1.dll (configurada con public.xml)
  • Library2.dll (configurada con public.xml)

Para cada ensamblado configurado para renombrar su interfaz pública hay que activar la generación de un archivo map XML.

Este archivo contiene la correspondencia entre los nombres originales de los símbolos y sus nombres ofuscados. Usan el archivo map XML todos los ensamblados que participan en el proceso de ofuscación y hacen referencia al menos a un ensamblado con la interfaz pública renombrada. Así se garantiza una resolución de nombres correcta entre los ensamblados ofuscados.

Para ofuscar Library1.dll y Library2.dll, se usa la siguiente sintaxis de la CLI:

babel Library2.dll --rules public.xml --mapout

Este primer comando ofusca Library2.dll y genera un archivo map XML llamado Library2.map.xml, que contiene la correspondencia entre los nombres originales de los símbolos y los nombres ofuscados.

Como Library1.dll hace referencia a Library2.dll y usa su interfaz pública, al ofuscar Library1.dll hay que proporcionar el archivo Library2.map.xml como entrada, para que los símbolos ofuscados de Library2.dll se resuelvan correctamente. Además, como se quiere ofuscar la interfaz pública de Library1.dll, se configura Babel para que cargue el archivo de reglas public.xml y genere el archivo map XML correspondiente a Library1.dll.

El comando de la CLI para este paso es el siguiente:

babel Library1.dll --rules public.xml --mapout --mapin Library2.map.xml

De este modo, Library1.dll hace referencia correctamente a los símbolos ofuscados de Library2.dll y, además, genera su propio archivo map para usarlo más adelante en el proceso de ofuscación.

Por último, para ofuscar MainAssembly.dll hay que configurar Babel para que cargue los archivos map XML de Library1.dll y de Library2.dll, ya que MainAssembly hace referencia a estos ensamblados. Así MainAssembly puede resolver correctamente, durante el proceso de ofuscación, los símbolos ofuscados de las bibliotecas de las que depende.

El comando de la CLI para este paso es:

babel MainAssembly.dll --mapin Library1.map.xml --mapin Library2.map.xml

Este comando recibe los archivos map generados antes (Library1.map.xml y Library2.map.xml) para que las referencias a los símbolos ofuscados de estas bibliotecas se traten correctamente en MainAssembly.

Es fundamental seguir el orden correcto al ofuscar los ensamblados. Las bibliotecas a las que hacen referencia otros ensamblados, como Library2.dll y Library1.dll, deben ofuscarse primero para generar los archivos map necesarios. Después pueden ofuscarse, con esos archivos map, los ensamblados que dependen de ellas, como Library1.dll y MainAssembly.dll.

Configuración desde la tarea de MSBuild

Para configurar el renombrado entre ensamblados con MSBuild es necesario indicar los archivos map XML de entrada y de salida de cada ensamblado que interviene en el proyecto de ofuscación, además del archivo de reglas XML. Cada ensamblado ofuscado debe generar un archivo map XML, que después se proporciona como entrada a todos los demás ensamblados ofuscados que hacen referencia a ese ensamblado de destino.

A continuación se muestra un ejemplo de cómo configurar el renombrado entre ensamblados con un ensamblado principal y dos ensamblados a los que este hace referencia, dispuestos según el esquema siguiente.

  • MainAssembly.dll
    1. Library1.dll
    2. Library2.dll
  • Library1.dll
    1. Library2.dll

Se empieza por el proyecto Library2, que no tiene dependencias. Como no depende de ningún otro ensamblado, puede ofuscarse de forma independiente, sin ningún archivo map XML de entrada.

Proyecto del ensamblado Library2

<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <GenerateMapOutFile>true</GenerateMapOutFile> </PropertyGroup> <Target Name="Obfuscate" AfterTargets="CoreCompile"> <ItemGroup> <RulesFile Include="path\to\referenced\public.xml" /> </ItemGroup> <Babel Input="$(TargetPath)" RulesFiles="@(RulesFile)" GenerateMapOutFile="$(GenerateMapOutFile)" /> </Target> </Project>

Conviene observar que, como Library1 hace referencia a Library2, el proyecto de ofuscación, además de generar el archivo map XML con GenerateMapOutFile=true, debe hacer referencia también al archivo map generado para Library2.

Proyecto del ensamblado Library1

<Project Sdk="Microsoft.NET.Sdk"> <ItemGroup> <Reference Include="path\to\referenced\Library2.dll" /> </ItemGroup> <PropertyGroup> <GenerateMapOutFile>true</GenerateMapOutFile> </PropertyGroup> <Target Name="Obfuscate" AfterTargets="CoreCompile"> <ItemGroup> <MapInFile Include="path\to\referenced\Library2.dll.map.xml" /> </ItemGroup> <ItemGroup> <RulesFile Include="path\to\referenced\public.xml" /> </ItemGroup> <Babel Input="$(TargetPath)" MapInFiles="@(MapInFile)" RulesFiles="@(RulesFile)" GenerateMapOutFile="$(GenerateMapOutFile)" /> </Target> </Project>

Como el proyecto MainAssembly hace referencia a las dos bibliotecas, Library1 y Library2, cuya interfaz pública se ha ofuscado, hay que configurar la tarea Babel para que cargue los dos archivos map XML generados para cada biblioteca.

Proyecto del ensamblado principal

<Project Sdk="Microsoft.NET.Sdk"> <ItemGroup> <Reference Include="path\to\referenced\Library1.dll" /> <Reference Include="path\to\referenced\Library2.dll" /> </ItemGroup> <Target Name="Obfuscate" AfterTargets="CoreCompile"> <ItemGroup> <MapInFile Include="path\to\referenced\Library1.dll.map.xml" /> <MapInFile Include="path\to\referenced\Library2.dll.map.xml" /> </ItemGroup> <Babel Input="$(TargetPath)" MapInFiles="@(MapInFile)" /> </Target> </Project>

De este modo, las referencias cruzadas entre Library1 y Library2 se tratan correctamente durante el proceso de ofuscación. Si no se hace referencia al archivo map XML generado para Library2, el proceso de ofuscación de Library1 puede no tratar bien las referencias cruzadas entre las dos bibliotecas, lo que puede causar problemas en tiempo de ejecución. Por eso, al configurar el renombrado entre ensamblados es imprescindible asegurarse de que se generan todos los archivos map XML necesarios y de que se hace referencia a ellos correctamente.

Configuración desde Babel Desktop

Un proyecto de Babel Desktop puede contener todos los ensamblados implicados. En el diagrama del proyecto, conecte cada biblioteca con el ensamblado que la usa y elija Pasar el archivo de map: la biblioteca escribe entonces su archivo map, el ensamblado que la usa lo lee y la biblioteca se ofusca primero. En el ejemplo anterior, conecte Library2 con Library1 y con MainAssembly, y Library1 con MainAssembly. Una conexión con Solo orden de ejecución establece el orden, pero no pasa ningún archivo map.

Las reglas de renombrado público siguen añadiéndose a cada biblioteca, con reglas XML o con RulesFiles. El grupo Archivos map de las propiedades del destino muestra los archivos map que cada destino escribe y lee, y permite añadir archivos map de compilaciones anteriores. Consulte Orden de ejecución y archivos map.

Last updated on