Codeverschlüsselung
Mit der Codeverschlüsselung von Babel Obfuscator können Benutzer ihren gesamten Code verschlüsseln, um ihn vor Reverse Engineering zu schützen.
Babel Obfuscator wandelt die ursprünglichen IL-Anweisungen einer Methode in einen neuen Satz eigener Anweisungen um. Dabei können verschiedene Verschleierungstechniken einfließen, die es erschweren, den Code zurückzuentwickeln oder zu verändern. Sobald die neue Darstellung des Codes aufgebaut ist, wird sie mit dem gewählten Verschlüsselungsalgorithmus (zum Beispiel AES) verschlüsselt, damit sie noch schwerer zu verstehen oder zu verändern ist.
Zur Laufzeit, wenn die geschützte Assembly in den Speicher geladen wird, entschlüsselt die Babel Virtual Machine (BVM) den geschützten Code und führt ihn aus. Die BVM ist eine schlanke Laufzeit-Engine, die mit der verschleierten Assembly ausgeliefert wird. Sie stellt die Funktionen bereit, die nötig sind, um den Code zu entschlüsseln, auszuführen und seinen korrekten Ablauf sicherzustellen.
Bereitstellung auf Hosts im FIPS-Modus? Die Codeverschlüsselung entschlüsselt Methodenrümpfe zur Laufzeit über den Kryptografieanbieter der Plattform. Ein Container auf einem Host im FIPS-Modus ohne zertifizierten OpenSSL-FIPS-Anbieter kann deshalb beim Start fehlschlagen. Ursache und Lösung beschreibt die Seite FIPS-Konformität.
Die Codeverschlüsselung bietet starken Schutz vor Reverse Engineering und dem Diebstahl geistigen Eigentums, geht aber zulasten der Leistung und erhöht die Komplexität der Anwendung. Es wird daher nicht empfohlen, sie auf die gesamte Codebasis anzuwenden. Besser ist es, diese Verschleierungstechnik gezielt auf die sensibelsten Teile des Codes anzuwenden, die Schutz benötigen, und für den übrigen Code andere Verschleierungstechniken zu verwenden. So finden Sie ein ausgewogenes Verhältnis zwischen Sicherheit und Leistung.
Vor der Codeverschlüsselung
Nach der Codeverschlüsselung
Die Codeverschlüsselung von Babel ist eine vollständig verwaltete Lösung. Das heißt, die verschlüsselten Methoden werden nicht durch nativen Code für eine bestimmte Plattform ersetzt. Diese verwaltete Lösung lässt die plattformübergreifende Natur von .NET Framework unangetastet und erlaubt dem JIT-Compiler (Just-In-Time), den Code für die Ziel-CPU zu optimieren.
Grenzen der Codeverschlüsselung
Die Codeverschlüsselung von Babel wird für Assemblys von .NET MAUI und Blazor nicht unterstützt. Die wichtigsten Gründe:
Plattformbedingte Einschränkungen
• AOT-Kompilierung (Ahead-of-Time): Plattformen wie iOS, die für .NET MAUI zentral sind, setzen auf AOT-Kompilierung. Dabei wird der Code vorab in native Binärdateien kompiliert. Code lässt sich dann zur Laufzeit weder dynamisch generieren noch verändern, was für die Ver- und Entschlüsselung von Code unerlässlich ist.
Eingeschränkte Unterstützung des Namespace System.Reflection.Emit
• Eingeschränkte IL-Generierung: Der Namespace System.Reflection.Emit, mit dem IL-Code dynamisch generiert wird, wird auf wichtigen Plattformen wie iOS und WebAssembly (von Blazor verwendet) nur eingeschränkt oder gar nicht unterstützt. Da die Codeverschlüsselung häufig auf der dynamischen Veränderung von IL-Code beruht, erschwert diese Einschränkung die Umsetzung von Verschlüsselungsfunktionen in MAUI und Blazor zusätzlich.
Sicherheitsbeschränkungen
• Sandbox-Umgebungen: Sowohl MAUI als auch Blazor laufen in Umgebungen, in denen Apps aus Sicherheitsgründen in einer Sandbox ausgeführt werden. Plattformen wie iOS setzen strenge Sicherheitsmaßnahmen durch, die jede Form der Codeänderung zur Laufzeit verhindern, um vor der Ausführung von Schadcode zu schützen. Eine dynamische Verschlüsselung ist damit nicht praktikabel.
• Risiko der Codeinjektion: Die dynamische Codegenerierung, die für die Ver- und Entschlüsselung erforderlich ist, birgt erhebliche Sicherheitsrisiken, darunter mögliche Schwachstellen für Codeinjektion. Die Frameworks MAUI und Blazor stellen die Sicherheit in den Vordergrund und vermeiden solche Risiken.
Wegen dieser Einschränkungen unterstützen .NET MAUI und Blazor die Codeverschlüsselung nicht und setzen stattdessen auf sichere, portable und plattformeinheitliche Entwicklungsverfahren.
Methoden, die nicht verschlüsselt werden können
Innerhalb eines unterstützten Ziels wird die Codeverschlüsselung Methode für Methode angewendet, und einige Methoden bleiben automatisch unverschlüsselt:
• Instanzkonstruktoren (.ctor) werden nie verschlüsselt. Das ist so gewollt: Eine Instanz muss über die Kette ihrer Basiskonstruktoren vollständig initialisiert sein, bevor sie verwendet wird, und diese Garantie lässt sich nicht aufrechterhalten, wenn die Codeverschlüsselung den Rumpf des Konstruktors verlagert. Das gilt nur für Instanzkonstruktoren: Statische Konstruktoren (.cctor) sind nicht betroffen und werden wie jede andere Methode verschlüsselt.
• Methoden mit nicht unterstützter Signatur werden automatisch übersprungen. Die Codeverschlüsselung verlagert den Methodenrumpf in die Babel Virtual Machine (BVM) und ruft ihn über einen einheitlichen Argument-Marshaller wieder auf. Einige Signaturformen lassen sich so nicht abbilden und bleiben unverschlüsselt:
- Generische Methoden, gemeldet als
EM0003. - Nicht unterstützte Rückgabetypen: eine
ref-Rückgabe (als Verweis), eine Zeigerrückgabe, eine Funktionszeigerrückgabe oder die Rückgabe einerref struct(verweisähnlicher Typ) wieSpan<T>/ReadOnlySpan<T>. Gemeldet alsEM0001. - Zeiger- oder Funktionszeigerparameter, gemeldet als
EM0002. ref struct-Parameter (verweisähnliche Typen) wieSpan<T>/ReadOnlySpan<T>, gemeldet alsEM0013.
Diese Grenzen liegen in der .NET-Laufzeit selbst: Ein Zeiger oder eine ref struct kann nicht geboxt werden, sodass der Argument-Marshaller der BVM sie nicht transportieren kann. Alles andere wird unterstützt, darunter ref/out/in-Parameter (jedes Elementtyps, einschließlich Strukturen, Enumerationen und als Verweis übergebener Verweistypen), Rückgaben von Werttypen und generischen Instanzen, Ausnahmebehandlung, Iteratoren und async-Methoden. Die vollständige EM-Liste finden Sie im Anhang unter Warncodes.
Methoden, die aus diesen Gründen ausgeschlossen werden, werden beim Build gemeldet und lassen die Verschleierung nicht fehlschlagen. Sie werden einfach unverschlüsselt ausgegeben.
Hinweise zur Leistung
Der Rumpf einer verschlüsselten Methode läuft weiterhin als JIT-kompilierter Code, seine eigentliche Arbeit erledigt er also nahezu mit nativer Geschwindigkeit. Die Codeverschlüsselung fügt bei jedem Eintritt in eine verschlüsselte Methode geringe Dispatch-Kosten pro Aufruf hinzu (die Argumente werden an die BVM übergeben, das Ergebnis wird zurückgegeben). Dieser Mehraufwand ist bei Methoden, die echte Arbeit leisten, vernachlässigbar, kann aber bei sehr kleinen Methoden überwiegen, die in extrem häufig durchlaufenen Schleifen aufgerufen werden (Millionen von Aufrufen). Wenden Sie die Codeverschlüsselung aus diesem Grund, und um die Assembly klein und schnell zu halten, gezielt auf die sensiblen Methoden an, die Schutz benötigen, statt auf die gesamte Codebasis, und verschlüsseln Sie keine winzigen, häufig aufgerufenen Hilfsmethoden auf einem kritischen Pfad.
Codeverschlüsselung einschalten
Mit Babel Obfuscator kann der Benutzer die Codeverschlüsselung gezielt auf bestimmte Methoden der Codebasis anwenden, statt die gesamte Codebasis zu verschlüsseln. So lassen sich die Leistungsprobleme vermeiden, die bei der Verschlüsselung großer Codemengen entstehen können.
Welche Methoden verschlüsselt werden sollen, gibt der Benutzer entweder mit einer XML-Regel oder mit dem Attribut Obfuscation an. In einer XML-Regel legt er die Namen der Methoden fest, die verschlüsselt werden sollen.
<Rule name="encrypt code" feature="msil encryption" exclude="false">
<Target>Methods</Target>
<Pattern>ACME.Algorithms::*</Pattern>
<Description>Encrypt all methods of Algorithm class.</Description>
</Rule>Alternativ lassen sich einzelne Methoden mit dem Attribut Obfuscation für die Verschlüsselung kennzeichnen, indem der Parameter „Feature“ auf „msil encryption“ gesetzt wird.
[Obfuscation(Feature = "msil encryption", Exclude = false)]
public void ProcessData()
{
// Encrypted code
}Ist die Codeverschlüsselung eingeschaltet, werden die ausgewählten Methoden bei der Verschleierung verschlüsselt.
Befehlszeile
babel myapp.exe --msilencryptionAnstelle von XML-Regeln oder Attributen kann der Schalter --msilencryption optional reguläre Ausdrücke annehmen, die die Methoden oder Typen auswählen, für die die Codeverschlüsselung eingeschaltet wird. Ein Beispiel ist der folgende Befehl:
babel myapp.exe --msilencryption ACME.LicenseManager::.*Er weist Babel an, alle Methoden der Klasse LicenseManager im Namespace ACME zu verschlüsseln.
MSBuild-Aufgabe Babel
<PropertyGroup>
<MsilEncryption>true</MsilEncryption>
</PropertyGroup>
<Babel MsilEncryption="$(MsilEncryption)" />Babel Desktop
Wählen Sie die Assembly auf der Zeichenfläche des Projekts aus und schalten Sie im Eigenschaftenbereich in der Gruppe „Codeverschlüsselung“ die Einstellung MsilEncryption ein. Optional fügen Sie eine Liste regulärer Ausdrücke hinzu, um die Namespaces oder Klassen zu filtern, auf die die Codeverschlüsselung angewendet wird. Lassen Sie die Liste leer, wenn Sie die zu verschlüsselnden Methoden mit XML-Regeln oder dem Attribut Obfuscation ausgewählt haben. Wie Sie in Babel Desktop mit Projekten arbeiten, erfahren Sie unter Verschleierungsprojekte.
Nach dem Lauf führt die Ansicht „Ergebnisse“ die verschlüsselten Methoden auf, sodass Sie prüfen können, ob die Codeverschlüsselung angewendet wurde.
Die Statistiken der Codeverschlüsselung erscheinen auch im Ausgabeprotokoll (in Babel Desktop im Bereich „Aktivität“), das jede Phase der Verschleierung festhält, auch die Codeverschlüsselung.
Encrypt Msil phase, elapsed time 00.579s
Embedded resource: omJYi
size : 13170 bytes
Method statistics:
194/[ 252] resources: 76.98 %
194/[ 252] overall: 76.98 %
Number of encrypted methods: 194Anhand der Statistiken der Codeverschlüsselung im Ausgabeprotokoll prüfen Sie leicht, ob die Codeverschlüsselung auf Ihren Code angewendet wurde, und erhalten einen Eindruck vom erreichten Schutzniveau. So können Sie bestätigen, dass Ihr sensibler Code erfolgreich verschlüsselt wurde und damit sicher und vor unbefugtem Zugriff geschützt bleibt.