Exemples de règles
Pour adapter l’obfuscation effectuée par Babel Obfuscator, vous pouvez écrire vos propres règles XML. Ces règles déterminent la manière dont l’obfuscateur traite certaines classes, méthodes et propriétés, entre autres. Elles offrent un contrôle détaillé et permettent d’affiner le résultat de l’obfuscateur. Cette section présente plusieurs exemples de règles XML pour Babel Obfuscator.
Désactiver le renommage d’une classe
Pour désactiver le renommage d’une classe donnée avec les règles XML de Babel Obfuscator, utilisez la règle XML suivante :
<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>Remarque :
Remplacez MyNamespace.MyClass par le nom complet de la classe à exclure du renommage.
- L’attribut
featureest défini sur « renaming » pour viser la fonctionnalité de renommage. - L’attribut
excludeest défini sur « true » pour empêcher le renommage de la classe indiquée. - L’attribut
applyToMembersest défini sur « true » pour empêcher le renommage des membres de la classe. - L’élément
Targetindique que la règle s’applique aux classes. - L’élément
Patternindique le nom complet de la classe.
Code généré par le compilateur
La règle suivante désactive certaines fonctionnalités d’obfuscation avancées pour le code généré par le compilateur.
<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>Types anonymes
En C#, un type anonyme est un type défini sans nom, à l’aide de l’opérateur new associé à un initialiseur d’objet.
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);
}Cela permet de créer des objets à la volée sans avoir à définir un type au préalable. Le compilateur génère pour le type anonyme un nom de type qui commence généralement par les caractères <>f__Anonymous. Ce nom généré est unique et n’est pas destiné à être utilisé par le développeur.
Les types anonymes sont très utilisés dans les requêtes LINQ et dans d’autres scénarios, comme les applications web ASP.NET, où des objets doivent être créés à la volée.
Lors de l’obfuscation, les types anonymes peuvent poser problème, car leurs noms générés pourraient être obfusqués. Les renommer peut perturber le code qui les utilise ; il est donc souvent recommandé de les exclure de l’obfuscation.
Une solution consiste à ajouter une règle qui vise tout symbole portant l’attribut
System.Runtime.CompilerServices.CompilerGeneratedAttribute
afin d’exclure tout le code généré par le compilateur, types anonymes compris.
<Rule name="rule1" feature="renaming, dead code" exclude="true" applyToMembers="true">
<Pattern>*</Pattern>
<HasAttribute>System.Runtime.CompilerServices.CompilerGeneratedAttribute</HasAttribute>
</Rule>Une autre solution consiste à utiliser un motif d’expression régulière qui correspond au nom de tout type défini en ligne, puisque ces types portent généralement le préfixe <>f__Anonymous.
<Pattern isRegEx="true">
<![CDATA[<>f__Anonymous.*]]>
</Pattern>Vous pouvez vérifier que le nom du type anonyme suit cette règle en l’examinant dans un inspecteur d’assemblies .NET tel que ILSpy ou dotPeek.
Utiliser les filtres de proxy dynamique
Dans Babel Obfuscator, les filtres de proxy dynamique permettent d’ajuster finement la génération des proxys dynamiques et d’atteindre le niveau d’obfuscation voulu tout en préservant les performances (voir Proxy dynamique).
<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>Cette règle XML est une configuration Babel qui définit des filtres de proxy dynamique.
Les filtres de proxy dynamique vous permettent de définir précisément quels appels de méthode doivent être interceptés et remplacés par des proxys dynamiques. Vous protégez ainsi les parties critiques de votre code sans toucher aux autres. Comme les filtres acceptent des expressions régulières, vous pouvez ajuster la règle à des conventions de nommage de méthodes ou à des comportements particuliers qui nécessitent un proxy dynamique. Vous adaptez ainsi l’obfuscation et la protection aux besoins propres à votre application.
Contrôler l’agent d’obfuscation
Dans Babel Obfuscator, l’agent d’obfuscation exécute pendant l’obfuscation une série de tâches fondées sur des règles prédéfinies. Son rôle principal est de prévenir les problèmes que l’obfuscation pourrait introduire et qui risqueraient de rendre l’assembly obtenu inutilisable. L’agent veille par exemple à ce que les symboles utilisés par réflexion ne soient pas obfusqués, car cela pourrait provoquer des erreurs à l’exécution. Ses tâches vont de simples vérifications, comme l’examen des champs des types sérialisables, à des opérations plus complexes qui reposent sur l’analyse statique du code MSIL.
L’agent d’obfuscation est indispensable au bon fonctionnement du code obfusqué, mais il arrive qu’un résultat d’obfuscation précis exige de désactiver certaines de ses tâches.
Pour ignorer certaines tâches de l’agent à l’aide des règles XML, définissez une règle d’exclusion visant la fonctionnalité agent. Par exemple, pour désactiver les tâches « Serializable types » et « Reflected strings », la règle XML se présente ainsi :
<Rule name="rule1" feature="agent" exclude="true">
<Pattern>ACME.Data.*</Pattern>
<Properties>
<TaskNameList>Serializable types;Reflected strings</TaskNameList>
</Properties>
</Rule>En conclusion, l’agent d’obfuscation joue un rôle central dans le bon fonctionnement du code obfusqué, mais certaines situations exigent de désactiver des tâches précises pour obtenir le résultat d’obfuscation voulu. Procédez avec prudence, en mesurant les conséquences de chaque tâche désactivée sur l’application finale.
Garder publics les types fusionnés (avertissement MG0004)
Lorsque vous fusionnez des assemblys avec l’option Internalize activée, Babel rend internes les types publics fusionnés afin qu’ils puissent être renommés. Les types sérialisables font exception : modifier leur visibilité peut casser la sérialisation, c’est pourquoi Babel les laisse publics et le signale avec l’avertissement MG0004 :
Warning [MG0004]: The serializable type 'Newtonsoft.Json.JsonException' will not be internalized.L’avertissement est informatif. Le type reste public et l’assembly continue de fonctionner. Pour rendre ce choix explicite sur les types concernés et supprimer l’avertissement, définissez la propriété Internalize dans une règle merge. Une règle qui définit Internalize l’emporte sur l’option globale pour les types qu’elle cible, de sorte que Babel applique votre valeur au lieu d’examiner le type :
<Rule name="keep-serializable-public" feature="merge" exclude="false">
<Target>Types</Target>
<Pattern>Newtonsoft.Json.*Exception</Pattern>
<Properties>
<Internalize>false</Internalize>
</Properties>
</Rule>Avec Internalize défini sur false, les types concernés sont fusionnés et restent publics, et MG0004 n’est plus signalé pour eux. Utilisez un motif qui couvre les types nommés dans les avertissements. Définir la propriété sur true les rendrait internes, ce qui est déconseillé pour les types sérialisables.
Chiffrement du code et méthodes génériques (avertissement EM0003)
Le chiffrement du code (fonctionnalité msil encryption) ne peut pas chiffrer les méthodes génériques. Lorsqu’une règle en sélectionne une, Babel l’ignore et signale l’avertissement EM0003 :
Warning [EM0003]: Generic methods are not supported at Engine::LargestÉcrivez le motif de sorte qu’il ne sélectionne que les méthodes à chiffrer et laisse de côté les méthodes génériques. Lorsqu’un motif large atteint inévitablement une méthode générique, celle-ci est ignorée sans risque. Pour masquer l’avertissement, passez le code en ligne de commande avec --nowarn EM0003, définissez NoWarnings dans la tâche MSBuild de Babel, ou ajoutez le code à la liste des avertissements à ignorer dans Babel Desktop.