Renommage XAML
Les applications Windows Presentation Foundation (WPF) et, plus récemment, MAUI utilisent le langage de balisage déclaratif XAML et le BAML (XAML compilé), qui permettent aux concepteurs visuels de créer directement les éléments de l’interface utilisateur.
Babel Obfuscator peut analyser les ressources XAML et BAML et renommer tous les membres qui y sont référencés, ce qui augmente le pourcentage de symboles obfusqués et rend le code XAML plus difficile à lire. Babel peut aussi fusionner plusieurs assemblies contenant des ressources XAML ou BAML en un seul fichier d’assembly, ce qui améliore l’organisation de l’application et simplifie son déploiement.
Le renommage des symboles XAML et BAML s’active avec l’option --xaml de la ligne de commande. Cette option accepte des paramètres facultatifs supplémentaires, qui permettent de renforcer l’obfuscation XAML (BAML).
Ligne de commande
babel.exe myapp.exe --xamlTâche MSBuild Babel
<PropertyGroup>
<ObfuscateXaml>true</ObfuscateXaml>
</PropertyGroup>
<Babel ObfuscateXaml="$(ObfuscateXaml)" />Babel Obfuscator propose des paramètres XAML avancés pour configurer plus finement l’obfuscation XAML, sous forme de paires clé-valeur passées après l’option --xaml.
Les paires clé-valeur disponibles sont notamment :
keys
En XAML, une ressource statique est une ressource définie au moment de la conception, qui peut être référencée depuis d’autres parties de l’application, comme les contrôles ou les styles. La ressource est identifiée par un nom de clé, qui sert à la référencer depuis le code XAML.
Lorsque cette option est activée, Babel Obfuscator renomme les noms de clé des ressources statiques dans le code XAML/BAML. Le niveau d’obfuscation du code augmente, et il devient plus difficile pour un attaquant de comprendre à quoi sert une ressource.
res
Lorsque cette option est activée, Babel obfusque les noms des ressources XAML/BAML. Les noms de toutes les ressources utilisées dans le code XAML/BAML, comme les images ou les chaînes, sont renommés pour masquer leur rôle d’origine. Il devient ainsi plus difficile pour un attaquant de comprendre la structure et le fonctionnement du code XAML/BAML, ce qui peut améliorer la sécurité globale de votre application.
strip
Cette option supprime les informations de ligne et les espaces du code XAML/BAML obfusqué. La rétro-ingénierie du code d’origine devient plus difficile, car les informations de débogage qui pourraient aider un attaquant à reconstituer le code source d’origine sont supprimées. La suppression des informations de ligne et des espaces peut aussi réduire la taille du fichier XAML/BAML obfusqué, qui se charge alors plus efficacement et plus vite.
manual
Par défaut, Babel Obfuscator obfusque automatiquement tous les membres publics référencés dans le code XAML ou BAML. Lorsqu’une approche plus fine est nécessaire, vous pouvez activer l’option manual. Vous indiquez alors vous-même les membres publics à obfusquer, à l’aide de règles rapides ou de fichiers de règles XML. Vous gagnez en maîtrise sur l’obfuscation, au prix d’une configuration plus importante.
babel.exe myapp.exe --xaml keys=on --xaml res=on --xaml strip=on<PropertyGroup>
<ObfuscateXaml>keys=true;strip=true;manual=false;res=true;true</ObfuscateXaml>
</PropertyGroup>
<Babel ObfuscateXaml="$(ObfuscateXaml)" />Aligner les littéraux de chaîne sur les membres liés au XAML renommés
Lors de la génération d’un assembly WPF, le compilateur incorpore généralement chaque page XAML sous forme de BAML, la forme binaire du XAML, dans les ressources de l’assembly. Pendant la phase de lecture, Babel inspecte ce BAML et, pour chaque déclaration x:Name, tente de lier le nom au champ de stockage correspondant du code-behind, sur le type de l’élément racine. Un champ pour lequel la liaison réussit est considéré comme lié au XAML pendant tout le reste de l’obfuscation.
Lorsqu’un tel membre lié au XAML est renommé, Babel effectue une étape d’alignement supplémentaire sur le type déclarant. Il parcourt chaque corps de méthode du type et réécrit chaque littéral de chaîne dont la valeur est égale au nom d’origine du membre, en le remplaçant par le nouveau nom. La correspondance est une simple égalité de chaînes sur le texte du littéral, et la réécriture s’applique à tous ces littéraux du type, quelle que soit la façon dont ils sont utilisés ensuite. Les seuls littéraux exemptés de cette réécriture sont ceux qui sont passés à System.Resources.ResourceManager et les sites d’appel explicitement exclus par des règles de renommage fournies par l’utilisateur.
L’objectif est que les recherches par nom effectuées à l’exécution par WPF dans le code-behind continuent de fonctionner après le renommage. Les constructions comme this.FindName("tabPreise"), les méthodes auxiliaires personnalisées comme GetControlByName<T>(string name), ou tout autre code qui résout un membre ou un élément nommé à partir du nom qu’il porte dans le code source, continuent de fonctionner, car les littéraux ont été synchronisés avec le champ renommé. Comme la correspondance est structurelle et ne repose pas sur des attributs, cet alignement prend automatiquement en compte les méthodes auxiliaires définies par l’utilisateur, sans qu’il faille leur ajouter un attribut d’activation.
Par exemple, avec le code-behind suivant :
private TabItem tabPreise { get; set; }
void Wire()
{
var tab = GetControlByName<TabItem>("tabPreise");
// ...
}Une fois l’assembly obfusqué par Babel, le champ est renommé et le littéral qui le désigne est aligné sur le nouveau nom :
private TabItem cm { get; set; }
void Wire()
{
var tab = GetControlByName<TabItem>("cm");
// ...
}L’alignement n’a lieu que si la liaison BAML décrite ci-dessus réussit. Si le type de l’élément BAML ne peut pas être résolu, généralement parce que l’assembly qui le définit ne se trouve pas dans le chemin de recherche de Babel et que le résolveur émet l’avertissement W00013 pour cet assembly, la liaison échoue silencieusement et le membre n’est pas marqué comme lié au XAML. Le renommage du champ ne dépend pas de cet indicateur XAML : le champ reçoit donc tout de même son nouveau nom. Les littéraux qui désignent le champ d’origine restent en revanche inchangés, et l’assembly obfusqué contient alors un IL incohérent. Toute recherche par nom à l’exécution qui reposait sur ces littéraux échoue.
Deux mesures s’appliquent, dans cet ordre :
-
Considérez W00013 comme bloquant pour le build dans les projets qui contiennent du BAML incorporé. Ajoutez au chemin de recherche de Babel, avec l’option
--addsearch, les répertoires de tous les assemblies référencés qui définissent des types d’éléments XAML, afin que le résolveur BAML puisse lier chaque type d’élément. Une fois tous les types d’éléments résolus, l’étape d’alignement s’exécute comme prévu. -
Lorsque vous voulez conserver le nom d’origine, par exemple quand des fichiers
.xamlautonomes sont livrés avec l’assembly et référencent le champ par son nom d’origine, excluez le champ du renommage avec une règle XML verrouillée :
<Rule name="keep-xname-tabPreise"
feature="renaming" exclude="true" locked="true">
<Target>Fields,Properties,Methods</Target>
<Pattern>MyNamespace.MyForm::tabPreise</Pattern>
<Pattern>MyNamespace.MyForm::get_tabPreise</Pattern>
<Pattern>MyNamespace.MyForm::set_tabPreise</Pattern>
</Rule>Le nom du champ restant inchangé, l’étape d’alignement n’a rien à réécrire, et l’assembly reste cohérent à la fois avec le BAML et avec les éventuels fichiers XAML autonomes qui référencent tabPreise.
Pour savoir plus généralement quand W00013 est purement informatif et quand il correspond à une modification réelle de la sortie obfusquée, voir W00013 lors de la liaison BAML dans la référence de la ligne de commande.