Décoder les traces de pile
Obfusquer une application protège la propriété intellectuelle et procure un avantage concurrentiel en rendant la rétro-ingénierie plus difficile. Cette sécurité supplémentaire complique toutefois le signalement des erreurs. L’obfuscation peut rendre l’analyse des plantages plus difficile, car la trace de pile se réduit souvent à une suite de symboles illisibles, ce qui complique le débogage.
Décoder les traces de pile dans .NET
Les développeurs .NET s’appuient généralement sur les traces de pile pour localiser la cause des erreurs d’une application. L’obfuscation rend cependant ces traces inintelligibles. Avec Babel Obfuscator, décoder ces traces de pile obfusquées est simple. L’outil a besoin d’un fichier de mappage, généré pendant l’obfuscation.
Générer le fichier de mappage
Lorsque vous activez la génération du fichier de mappage XML dans Babel Obfuscator, ce fichier est généré par défaut dans le même répertoire que l’assembly obfusqué. Il porte le nom de l’assembly d’origine, suivi de .map.xml (par exemple MyApp.exe.map.xml).
Le fichier de mappage généré contient la correspondance entre les noms de symboles obfusqués et les noms d’origine.
Notez qu’il est préférable de désactiver le renommage avec surcharge (--nooverloaded), car il attribue le même nom à des méthodes différentes, ce qui peut rendre le décodage de la trace de pile ambigu. Si le renommage avec surcharge est activé, Babel indique lors du décodage toutes les méthodes qui peuvent correspondre.
Vous pouvez choisir l’emplacement de sortie du fichier de mappage de différentes manières, selon la façon dont vous utilisez Babel.
Ligne de commande
babel MyApp.exe --mapout CustomPath/MyMapping.xmlSi vous omettez le chemin du fichier, Babel applique la convention de nommage par défaut dans le répertoire cible.
Tâche MSBuild
<Babel GenerateMapOutFile="true" MapOutFile="CustomPath/MyMapping.xml" />Package NuGet Babel Obfuscator
<PropertyGroup>
<GenerateMapOutFile>true</GenerateMapOutFile>
<BabelMapOutFile>CustomPath/MyMapping.xml</BabelMapOutFile>
</PropertyGroup>Babel Desktop
Dans Babel Desktop, sélectionnez l’assembly et activez GenerateMapOutFile dans le groupe Output & diagnostics du panneau des propriétés. Définissez MapOutFile pour écrire le fichier de mappage à un emplacement personnalisé. Voir Projets d’obfuscation.
Décoder la trace de pile obfusquée
Lorsqu’une application obfusquée plante et produit une trace de pile obfusquée, utilisez Babel pour la décoder. Babel Obfuscator fournit des outils intégrés qui décodent les traces de pile obfusquées à l’aide des fichiers de mappage.
Babel Desktop
Les étapes ci-dessous sont un résumé ; voir Décodeur de pile pour le guide complet.
Ouvrir le décodeur de pile
Ouvrez la palette de commandes et exécutez Outils : décodeur de pile.
Ajouter les fichiers de mappage
Ajoutez les fichiers de mappage XML avec Ajouter des fichiers map…, ou déposez-les sur le décodeur. Vous pouvez ajouter plusieurs fichiers de mappage lorsque la trace couvre plusieurs assemblies.
Coller la trace de pile
Collez la trace de pile obfusquée, ou chargez-la depuis un fichier avec Ouvrir une trace….
Décoder
Cliquez sur Décoder pour afficher la trace de pile décodée.
Ligne de commande
Vous pouvez aussi utiliser l’outil en ligne de commande babel :
babel --stacktrace StackTrace.txt --mapin MyApp.exe.map.xml --mapin Library.dll.map.xmlVous pouvez indiquer plusieurs fichiers de mappage si la trace de pile concerne plusieurs assemblies.
Frames du proxy dynamique
Lorsque le proxy dynamique est activé, Babel fait passer les appels éligibles par des méthodes de pont générées. Chaque pont apparaît comme une frame supplémentaire, si bien qu’une trace décodée entremêle vos propres méthodes et la mécanique interne de Babel. Babel enregistre dans le fichier de mappage la méthode que chaque pont remplace, et le décodeur l’affiche :
at Acme.Backup.ZipReader.OpenZip(System.String filename)
at (System.String ) -> proxy for System.IO.Compression.ZipFile::OpenRead
at Acme.Backup.BackupReader.IsBackupFile(System.String path)L’annotation -> proxy for <DeclaringType>::<Method> indique exactement quelle méthode le pont appelait. La signature figure déjà sur la frame et n’est donc pas répétée dans l’annotation. Les fichiers de mappage produits par des versions antérieures de Babel, qui n’enregistrent pas la cible du proxy, sont décodés comme auparavant et affichent à la place la mention générique -> babel generated code.
Masquer les frames générées par Babel
Si seule votre propre chaîne d’appels vous intéresse, Babel peut retirer toutes les frames qu’il a générées (les ponts de proxy et les frames anonymes créées à l’exécution par lesquelles ils passent), ce qui laisse une trace identique à celle que produirait l’application non obfusquée.
Depuis la ligne de commande, ajoutez la clé frames=user à l’option --stacktrace :
babel --stacktrace StackTrace.txt --stacktrace frames=user --mapin MyApp.exe.map.xmlframes=all est la valeur par défaut et conserve toutes les frames. Dans Babel Desktop, le décodeur de pile masque ces frames par défaut : la case Masquer les frames ajoutées par Babel est cochée. Décochez-la pour conserver toutes les frames.
Une fois les frames générées masquées, la trace ci-dessus devient :
at System.IO.Compression.ZipFile.Open(System.String archiveFileName)
at Acme.Backup.ZipReader.OpenZip(System.String filename)
at Acme.Backup.BackupReader.IsBackupFile(System.String path)Automatiser la désobfuscation des traces de pile
Babel Obfuscator fournit une interface pour automatiser le décodage des traces de pile. Ajoutez à votre assembly .NET une référence à babel.dll (ou à babel.exe pour les anciennes applications .NET Framework) et utilisez l’API fournie pour décoder les traces de pile par programmation.
L’extrait de code ci-dessous montre comment configurer une application console pour désobfusquer une trace de pile chargée depuis un fichier externe :
// Example of setting up the console application
static int Main(string[] args)
{
if (args.Length < 2)
{
Console.WriteLine("Usage: stackdecode.exe <filename> <xmlmapfile1> [xmlmapfile2 ...]");
return 1;
}
StackTraceDeobfuscator stk = new StackTraceDeobfuscator();
foreach (var xmlMapFile in args.Skip(1))
{
try
{
stk.AddMapFile(xmlMapFile);
}
catch (Exception ex)
{
Console.WriteLine(String.Format("Error reading XML map file '{0}':n{1}", xmlMapFile, ex.Message));
return 1;
}
}
try
{
StreamReader sr = new StreamReader(args[0]);
Console.WriteLine("Deobfuscated Stack Trace:");
Console.WriteLine(stk.DeobfuscateStack(sr));
}
catch (Exception ex)
{
Console.WriteLine(String.Format("Could not decode stack trace file '{0}':n{1}", args[0], ex.Message));
return 1;
}
return 0;
}Pour retirer les frames générées par Babel (voir Masquer les frames générées par Babel) lors d’un décodage par programmation, définissez HideGeneratedFrames sur le désobfuscateur avant d’appeler DeobfuscateStack :
StackTraceDeobfuscator stk = new StackTraceDeobfuscator();
stk.HideGeneratedFrames = true;L’interface de programmation de désobfuscation des traces de pile donne aux développeurs un outil pour améliorer leurs pratiques de débogage. En intégrant ce mécanisme à leurs applications, ils peuvent automatiser le décodage, traiter efficacement les traces de pile obfusquées et préserver l’intégrité et la sécurité de leur code.
Utiliser les fichiers PDB avec les traces de pile obfusquées
Vous pouvez aussi utiliser des fichiers PDB en production pour obtenir le fichier source et les numéros de ligne dans la trace de pile décodée. Plus précisément, Babel peut chiffrer les noms de fichiers et les noms de symboles dans les PDB : ils apparaissent alors chiffrés dans les traces de pile, ce qui évite de révéler des informations sensibles sur les chemins de fichiers.
Pour activer cette fonctionnalité, définissez un mot de passe PDB. Choisissez un mot de passe sûr : il chiffre les noms de fichiers dans le PDB et sera nécessaire plus tard pour désobfusquer les traces de pile.
- Ligne de commande : utilisez l’option
--pdbpwd, par exemplebabel MyApp.exe --debug --pdbpwd <password>. - MSBuild : définissez la propriété
PdbPwdde la tâche Babel. - Babel Desktop : sélectionnez l’assembly et définissez
PdbPwddans le groupe Advanced du panneau des propriétés. Le mot de passe n’est conservé que pour la session en cours : il n’est pas enregistré dans le projet et doit être saisi de nouveau après le redémarrage de Babel Desktop.
Une fois cette fonctionnalité activée et le mot de passe PDB défini, Babel chiffre les noms de fichiers et les autres informations concernées pendant l’obfuscation. Dans vos traces de pile, les noms de fichiers apparaissent donc sous forme de chaînes chiffrées et non plus sous forme de chemins d’origine.
System.Exception: (0x80131904): A network-related or instance-specific error occurred while establishing a connection to the server.
at System.Data.SqlClient.SqlConnection.Open()
at b.a(String g)
at c.b() in <GFpQHv9iwQzX1Zmh+… >:line 21
at c.a(String h)
at Acme.ViewModel.MainViewModel.get_Message() in <GFpQHv9iwQzX1Zmh+… >:line 28 Toutes les données nécessaires au déchiffrement sont stockées dans le fichier de mappage XML : le fichier PDB n’est donc pas nécessaire au décodage. La trace de pile décodée contient le nom de fichier déchiffré.
System.Exception: (0x80131904): A network-related or instance-specific error occurred while establishing a connection to the server.
at System.Data.SqlClient.SqlConnection.Open()
at Acme.Entities.DatabaseContext.ConnectToDatabase(System.String connectionString)
at Acme.ViewModel.RS.CheckResourceLoaded() in C:AcmeAcme.ViewModelRS.cs:line 21
at Acme.ViewModel.RS.GetString(System.String name)
at Acme.ViewModel.MainViewModel.get_Message() in C:AcmeAcme.ViewModelViewModelMainViewModel.cs:line 28Cette méthode concilie sécurité et maintenabilité. Elle protège la propriété intellectuelle que révèle l’organisation de vos fichiers, tout en vous laissant tirer des traces de pile des informations utiles au débogage et à l’analyse des erreurs.
Avec le chiffrement des PDB, la structure interne de votre application et l’organisation de ses fichiers restent protégées et confidentielles, même lorsque vous partagez des PDB à des fins de dépannage ou d’assistance.