Reglas de ejemplo
Para adaptar el proceso de ofuscación de Babel Obfuscator, el usuario puede escribir sus propias reglas XML. Estas reglas determinan cómo trata el ofuscador clases, métodos y propiedades concretos, entre otros elementos. Como ofrecen un control detallado, permiten afinar el resultado del ofuscador. En esta sección se presentan varios ejemplos de reglas XML para Babel Obfuscator.
Desactivar el renombrado de una clase
Para desactivar el renombrado de una clase determinada con las reglas XML de Babel Obfuscator, puede usar la regla XML siguiente:
<Rule name="disable-myclass-renaming" feature="renaming" exclude="true"
applyToMembers="true">
<Target>Classes</Target>
<Pattern>MyNamespace.MyClass</Pattern>
<Description>Disable renaming for MyClass.</Description>
</Rule>Nota:
Sustituya MyNamespace.MyClass por el nombre completo de la clase que desea excluir del renombrado.
- El atributo
featuretiene el valor «renaming» para dirigirse a la función de renombrado. - El atributo
excludetiene el valor «true» para impedir el renombrado de la clase indicada. - El atributo
applyToMemberstiene el valor «true» para impedir el renombrado de los miembros de la clase. - El elemento
Targetespecifica que la regla se aplica a las clases. - El elemento
Patternespecifica el nombre completo de la clase.
Código generado por el compilador
La regla siguiente impide que algunas funciones avanzadas de ofuscación se apliquen al código generado por el compilador.
<Rule name="no-compiler-generated"
feature="control flow, value encryption, string encryption"
exclude="true" applyToMembers="false">
<Target>Classes</Target>
<Pattern>*</Pattern>
<HasAttribute onEnclosingType="false">
System.Runtime.CompilerServices.CompilerGeneratedAttribute,
System.Diagnostics.DebuggerHiddenAttribute
</HasAttribute>
<Description>Do not obfuscate compiler-generated methods.</Description>
</Rule>Tipos anónimos
En C#, un tipo anónimo es un tipo que se define sin nombre mediante el operador new junto con un inicializador de objeto.
var query =
from prod in products
select new { prod.Name, prod.Price };
foreach (var v in query)
{
Console.WriteLine("Name={0}, Price={1}", v.Name, v.Price);
}Esto permite crear objetos sobre la marcha sin tener que definir antes un tipo específico. El compilador genera un nombre para el tipo anónimo, que normalmente empieza por los caracteres <>f__Anonymous. El nombre generado es único y no está pensado para que lo use el desarrollador.
Los tipos anónimos se usan mucho en las consultas LINQ y en otros escenarios, como las aplicaciones web ASP.NET, en los que hay que crear objetos sobre la marcha.
En el contexto de la ofuscación, los tipos anónimos pueden plantear dificultades, ya que sus nombres generados podrían ofuscarse. Renombrarlos puede causar problemas en el código que los usa, por lo que a menudo se recomienda excluirlos de la ofuscación.
Una forma de conseguirlo es añadir una regla dirigida a cualquier símbolo que tenga el atributo
System.Runtime.CompilerServices.CompilerGeneratedAttribute
para excluir todo el código generado por el compilador, incluidos los tipos anónimos.
<Rule name="rule1" feature="renaming, dead code" exclude="true" applyToMembers="true">
<Pattern>*</Pattern>
<HasAttribute>System.Runtime.CompilerServices.CompilerGeneratedAttribute</HasAttribute>
</Rule>Otra opción es usar un patrón de expresión regular que coincida con el nombre de cualquier tipo en línea, ya que estos tipos suelen tener el prefijo <>f__Anonymous.
<Pattern isRegEx="true">
<![CDATA[<>f__Anonymous.*]]>
</Pattern>Puede comprobar si el tipo anónimo sigue esta regla consultando su nombre en cualquier inspector de ensamblados .NET, como ILSpy o dotPeek.
Usar los filtros de llamadas del proxy dinámico
Los filtros de llamadas del proxy dinámico son una herramienta útil de Babel Obfuscator para ajustar con precisión la generación del proxy dinámico y obtener el nivel de ofuscación deseado sin perjudicar el rendimiento (consulte Proxy dinámico).
<Rule name="rule1" feature="dynamic proxy" exclude="false" applyToMembers="true">
<Pattern>*</Pattern>
<Description>Set Dynamic Proxy Call Filters</Description>
<Properties>
<DynamicProxyCallFilters>IEnumerator.*;ICollection.*</DynamicProxyCallFilters>
</Properties>
</Rule>Esta regla XML es una configuración de Babel que establece los filtros de llamadas del proxy dinámico.
Con los filtros de llamadas del proxy dinámico puede definir con precisión qué llamadas a métodos se interceptan y se sustituyen por proxies dinámicos. Así puede proteger las secciones críticas del código y dejar intactas las demás. Como los filtros admiten expresiones regulares, puede adaptar la regla para que coincida con los patrones de nombres de métodos o con los comportamientos que requieren un proxy dinámico. De este modo, las estrategias de ofuscación y protección se ajustan a los requisitos propios de su aplicación.
Controlar el agente de ofuscación
El agente de ofuscación de Babel Obfuscator se encarga de ejecutar, durante el proceso de ofuscación, una serie de tareas basadas en reglas predefinidas. Su finalidad principal es evitar los problemas que la ofuscación podría introducir y que podrían dejar inservible el ensamblado resultante. Por ejemplo, el agente se asegura de que los símbolos que se usan mediante reflexión no se ofusquen, porque hacerlo podría provocar errores en tiempo de ejecución. Las tareas del agente van desde comprobaciones sencillas, como examinar los campos de los tipos serializables, hasta operaciones más complejas que requieren el análisis estático del código MSIL.
Aunque el agente de ofuscación es fundamental para que el código ofuscado funcione correctamente, puede haber escenarios en los que el desarrollador quiera obtener un resultado de ofuscación concreto que exija desactivar determinadas tareas del agente.
Para omitir tareas concretas del agente mediante reglas XML, se puede definir una regla de exclusión dirigida a la función agent. Por ejemplo, para desactivar tareas como «Serializable types» y «Reflected strings», la regla XML sería así:
<Rule name="rule1" feature="agent" exclude="true">
<Pattern>ACME.Data.*</Pattern>
<Properties>
<TaskNameList>Serializable types;Reflected strings</TaskNameList>
</Properties>
</Rule>En conclusión, aunque el agente de ofuscación desempeña un papel decisivo para que el código ofuscado funcione sin contratiempos, hay situaciones en las que el desarrollador puede necesitar desactivar tareas concretas para obtener el resultado de ofuscación que busca. Es esencial hacerlo con prudencia y entender las consecuencias que cada tarea desactivada tiene en la aplicación final.