Skip to Content
Neue Version 12 verfügbar 🎉

XAML-Umbenennung

Anwendungen für Windows Presentation Foundation (WPF) und seit Kurzem auch MAUI-Anwendungen verwenden die deklarative Markupsprache XAML und BAML (kompiliertes XAML), damit visuelle Designer Elemente der Benutzeroberfläche direkt erstellen können.

Babel Obfuscator kann XAML- und BAML-Ressourcen analysieren und alle darin referenzierten Member umbenennen. Das erhöht den Anteil der verschleierten Symbole und macht den XAML-Code schwerer lesbar. Außerdem kann Babel mehrere Assembly-Dateien, die XAML- oder BAML-Ressourcen enthalten, zu einer einzigen Assembly-Datei zusammenführen, was die Organisation verbessert und die Bereitstellung der Anwendung vereinfacht.

Die Umbenennung von XAML- und BAML-Symbolen schalten Sie mit dem Flag --xaml auf der Befehlszeile ein. Dieser Schalter hat zusätzliche optionale Parameter, mit denen sich die Verschleierung von XAML (BAML) erweitern lässt.

Befehlszeile

babel.exe myapp.exe --xaml

MSBuild-Aufgabe Babel

<PropertyGroup> <ObfuscateXaml>true</ObfuscateXaml> </PropertyGroup> <Babel ObfuscateXaml="$(ObfuscateXaml)" />

Babel Obfuscator bietet einige erweiterte XAML-Einstellungen, mit denen sich die XAML-Verschleierung zusätzlich konfigurieren lässt. Sie werden als Schlüssel-Wert-Paare nach dem Schalter --xaml übergeben.

Verfügbar sind die folgenden Schlüssel-Wert-Paare:

keys

In XAML ist eine statische Ressource eine Ressource, die zur Entwurfszeit definiert wird und von anderen Teilen der Anwendung referenziert werden kann, etwa von Steuerelementen oder Stilen. Die Ressource wird durch einen Schlüsselnamen identifiziert, über den der XAML-Code sie referenziert.

Ist die Option eingeschaltet, benennt Babel Obfuscator die Schlüsselnamen statischer Ressourcen im XAML/BAML-Code um. Das erhöht den Grad der Verschleierung des Codes und erschwert es Angreifern, den ursprünglichen Zweck einer Ressource zu erkennen.

res

Ist die Option eingeschaltet, verschleiert Babel die Namen der XAML/BAML-Ressourcen. Die Namen aller im XAML/BAML-Code verwendeten Ressourcen, etwa Bilder oder Zeichenfolgen, werden also umbenannt, um ihren ursprünglichen Zweck zu verbergen. Das erschwert es Angreifern, Aufbau und Funktion des XAML/BAML-Codes zu verstehen, und kann die Sicherheit Ihrer Anwendung insgesamt erhöhen.

strip

Diese Option entfernt Zeileninformationen und Leerraum aus dem verschleierten XAML/BAML-Code. Das erschwert Angreifern das Reverse Engineering des ursprünglichen Codes, weil Debuginformationen entfallen, mit denen sich der ursprüngliche Quellcode rekonstruieren ließe. Ohne Zeileninformationen und Leerraum wird außerdem die verschleierte XAML/BAML-Datei kleiner, sodass sie effizienter ist und schneller geladen wird.

manual

Standardmäßig verschleiert Babel Obfuscator automatisch alle öffentlichen Member, die im XAML- oder BAML-Code referenziert werden. Wenn eine feinere Abstimmung nötig ist, kann die Option manual eingeschaltet werden. Der Benutzer gibt dann von Hand an, welche öffentlichen Member verschleiert werden sollen, entweder mit Schnellregeln oder mit XML-Regeldateien. Das gibt mehr Kontrolle über die Verschleierung, verlangt vom Benutzer aber mehr Konfiguration.

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)" />

Zeichenfolgenliterale an umbenannte, an XAML gebundene Member angleichen

Beim Erstellen einer WPF-Assembly bettet der Compiler in der Regel jede XAML-Seite als BAML, die binäre Form von XAML, in die Ressourcen der Assembly ein. In der Lesephase untersucht Babel dieses BAML und versucht, für jede Deklaration mit x:Name den Namen an das entsprechende zugrunde liegende Feld im Code-Behind des Typs des Stammelements zu binden. Ein Feld, für das die Bindung gelingt, gilt für den Rest des Verschleierungslaufs als an XAML gebunden.

Wird ein solcher an XAML gebundener Member umbenannt, führt Babel für den deklarierenden Typ einen zusätzlichen Angleichungsschritt aus. Es durchläuft jeden Methodenrumpf des Typs und schreibt jedes Zeichenfolgenliteral um, dessen Wert dem ursprünglichen Namen des Members entspricht, indem es ihn durch den neuen Namen des Members ersetzt. Der Abgleich ist ein einfacher Zeichenfolgenvergleich mit dem Text des Literals, und umgeschrieben werden alle derartigen Literale des Typs, unabhängig davon, wie sie anschließend verwendet werden. Ausgenommen sind nur Literale, die an System.Resources.ResourceManager übergeben werden, und Aufrufstellen, die durch Umbenennungsregeln des Benutzers ausdrücklich ausgeschlossen sind.

Damit sollen namensbasierte WPF-Suchen zur Laufzeit im Code-Behind auch nach der Umbenennung funktionieren. Muster wie this.FindName("tabPreise"), eigene Hilfsmethoden wie GetControlByName<T>(string name) oder jeder andere Code, der einen Member oder ein benanntes Element über seinen Zeichenfolgennamen aus dem Quellcode auflöst, funktionieren weiter, weil die Literale mit dem umbenannten Feld synchron gehalten wurden. Weil der Abgleich strukturell und nicht attributbasiert arbeitet, erfasst diese Angleichung benutzerdefinierte Hilfsmethoden automatisch, ohne dass die Hilfsmethode ein Opt-in-Attribut braucht.

Ein Beispiel mit dem folgenden Code-Behind:

private TabItem tabPreise { get; set; } void Wire() { var tab = GetControlByName<TabItem>("tabPreise"); // ... }

Nachdem Babel die Assembly verschleiert hat, ist das Feld umbenannt und das Literal, das es benennt, an den neuen Namen angeglichen:

private TabItem cm { get; set; } void Wire() { var tab = GetControlByName<TabItem>("cm"); // ... }

Die Angleichung greift nur, wenn die oben beschriebene BAML-Bindung gelingt. Lässt sich der Typ des BAML-Elements nicht auflösen, schlägt die Bindung stillschweigend fehl, und der Member wird nicht als an XAML gebunden markiert. In der Regel liegt das daran, dass die Assembly, die den Typ definiert, nicht im Suchpfad von Babel liegt und der Resolver für diese Assembly die Warnung W00013 ausgibt. Die Umbenennung des Felds selbst hängt nicht vom XAML-Flag ab, das Feld erhält also trotzdem seinen neuen Namen. Die Literale, die das ursprüngliche Feld benennen, bleiben jedoch unverändert, und die verschleierte Assembly enthält inkonsistenten IL-Code. Jede namensbasierte Suche zur Laufzeit, die sich auf diese Literale stützt, schlägt dann fehl.

Zwei Gegenmaßnahmen kommen infrage, in dieser Reihenfolge:

  1. Behandeln Sie W00013 bei Projekten mit eingebettetem BAML als Fehler, der den Build blockiert. Nehmen Sie mit der Option --addsearch die Verzeichnisse aller referenzierten Assemblys, die XAML-Elementtypen definieren, in den Suchpfad von Babel auf, damit der BAML-Resolver jeden Elementtyp binden kann. Sind alle Elementtypen aufgelöst, läuft der Angleichungsschritt wie vorgesehen.

  2. Wenn der ursprüngliche Name erhalten bleiben soll, zum Beispiel weil eigenständige .xaml-Dateien zusammen mit der Assembly ausgeliefert werden und das Feld über seinen ursprünglichen Namen referenzieren, schließen Sie das Feld mit einer gesperrten XML-Regel von der Umbenennung aus:

<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>

Bleibt der Feldname unverändert, hat der Angleichungsschritt nichts umzuschreiben, und die Assembly bleibt sowohl mit dem BAML als auch mit allen losen XAML-Dateien konsistent, die tabPreise referenzieren.

Wann W00013 rein informativ ist und wann die Warnung mit einer tatsächlichen Änderung der verschleierten Ausgabe zusammenhängt, beschreibt der Abschnitt W00013 bei der BAML-Bindung in der Befehlszeilenreferenz.

Last updated on