Votre obfuscation a-t-elle vraiment marché ? Vérifiez-le dans Glass.NET
Une compilation réussie ne prouve pas que votre code est protégé. Ouvrez l'assembly obfusqué dans Glass.NET — le décompilateur .NET gratuit et purement statique — et lisez-le comme le fera un attaquant : vérifiez que le renommage, le chiffrement des chaînes, le flux de contrôle et la virtualisation ont tenu, et que vous n'avez pas sur-protégé votre API publique.
Vous avez passé votre obfuscateur. La compilation a réussi, les tests sont au vert, le paquet est signé. Donc votre code est protégé maintenant — n’est-ce pas ?
Peut-être. Une compilation réussie vous dit que l’obfuscateur n’a pas planté. Elle ne vous dit rien sur le fait que le résultat soit réellement difficile à lire. La seule façon de le savoir est de regarder l’assembly comme le fera un attaquant : le glisser dans un décompilateur et voir ce qui en ressort. Si le C# est encore lisible, vous avez livré un faux sentiment de sécurité.
Le bon outil pour cette vérification est un décompilateur de confiance qui n’exécute jamais le binaire. Glass.NET est gratuit, et il est strictement statique — il lit les métadonnées et l’IL et reconstruit le C#, et n’exécute jamais l’assembly qu’il inspecte. Cela en fait le compagnon naturel d’un obfuscateur comme Nebula.NET : vous protégez avec l’un, vous vérifiez avec l’autre, et vous n’avez jamais à exécuter une build dont vous n’êtes pas sûr.
Pourquoi « la compilation a réussi » n’est pas une vérification
L’obfuscation est un ensemble de transformations appliquées à l’IL. Chacune d’elles peut être mal configurée, avoir une portée trop étroite ou être silencieusement ignorée. Une règle de renommage qui exclut trop, une passe de chiffrement des chaînes qui ne s’est jamais exécutée, une option de flux de contrôle laissée désactivée, une méthode que vous vouliez virtualiser mais avez oublié de marquer — rien de tout cela ne produit d’erreur de compilation. Cela produit un binaire qui a l’air protégé dans votre dossier de sortie et qui se lit comme du source dans un décompilateur.
Traitez donc la vérification comme une étape obligatoire, pas comme une arrière-pensée. La procédure est simple : décompilez l’assembly avant et après protection, et comparez.
Préparez une comparaison avant-après
Gardez une copie de la build non obfusquée. Ouvrez-la d’abord dans Glass.NET et naviguez vers une classe qui compte pour vous — une vérification de licence, une routine de tarification, tout ce que vous ne voudriez pas voir copié. Vous serez presque certainement surpris de sa lisibilité ; pour un assembly non protégé, le C# reconstruit est souvent assez proche pour être recompilé.
Ouvrez maintenant la build protégée. Glass.NET propose une comparaison d’assemblys côte à côte avec un diff ligne à ligne, ce qui vous permet de mettre les deux versions l’une à côté de l’autre et de lire la différence directement, au lieu de passer d’une fenêtre à l’autre. Parcourez, méthode par méthode, le code que vous attendiez que l’obfuscateur touche, et posez-vous pour chacune les questions précises ci-dessous.
1. Le renommage a-t-il tenu ?
La protection la moins chère est le renommage des identifiants — transformer ValidateLicenseKey, _customerBalance et ComputeDiscount en symboles vides de sens. Dans la build non protégée, vous verrez vos vrais noms. Dans la build protégée, les types et membres internes devraient se lire comme a, b, c ou un bruit similaire :
// avant
internal sealed class LicenseValidator
{
public bool ValidateLicenseKey(string key) { ... }
}
// après
internal sealed class a
{
public bool b(string A_0) { ... }
}
Vérifiez deux choses. D’abord, que le renommage a bien eu lieu — si vos noms ont survécu, la passe ne s’est pas exécutée ou vos règles d’exclusion sont beaucoup trop larges. Ensuite, et c’est tout aussi important, qu’il n’est pas allé trop loin : votre API publique, vos cibles de réflexion et vos contrats de sérialisation doivent rester intacts, sinon votre bibliothèque casse pour ses appelants. Utilisez Aller à tout (Ctrl+T) et la vue d’informations de l’assembly pour confirmer que votre surface publique garde ses vrais noms tandis que tout l’interne a disparu. La sur-obfuscation est un bug aussi réel que la sous-obfuscation ; Glass vous laisse voir les deux.
2. Les chaînes ont-elles disparu ?
Le code décompilé fuit beaucoup à travers les littéraux de chaîne en clair — URL, SQL, messages d’erreur, chaînes de format, noms de feature flags. Le chiffrement des chaînes les stocke chiffrées et ne les déchiffre qu’à l’usage. Pour vérifier, cherchez dans la sortie décompilée un littéral dont vous savez qu’il était dans le source — une URL, un message d’erreur, une constante magique. Dans une build correctement chiffrée, vous ne le trouverez pas sous forme de texte ; vous trouverez à la place un appel qui renvoie la chaîne à l’exécution.
Soyez honnête sur ce que cela prouve. Le littéral est tout de même déchiffré en mémoire quand le code s’exécute, donc un attaquant déterminé muni d’un débogueur peut toujours le récupérer. Ce que vous avez confirmé, c’est que l’attaque triviale — grepper le binaire ou le source décompilé à la recherche d’un mot-clé — ne renvoie plus rien. Cela élimine déjà une grande part de l’exposition à faible effort.
3. Le flux de contrôle est-il un enchevêtrement ?
Le renommage cache comment les choses s’appellent ; l’obfuscation de flux de contrôle cache ce que fait le code. Une méthode protégée ne devrait plus se décompiler en C# propre et linéaire. Au lieu d’un if/else lisible, vous devriez voir une logique aplatie — un switch sur une variable d’état, des branches opaques, des goto — la forme qu’un décompilateur produit lorsqu’il ne peut plus récupérer la structure d’origine :
// après obfuscation de flux de contrôle, décompilé
int num = 0;
while (true)
{
switch (num)
{
case 0: num = (cond ? 2 : 1); continue;
case 1: result = a(); num = 3; continue;
case 2: result = b(); num = 3; continue;
case 3: return result;
}
}
Si le corps se lit encore comme le source que vous avez écrit, la protection de flux de contrôle n’atteint pas cette méthode. La barre à viser n’est pas seulement « embrouiller un humain » mais « survivre aux dé-obfuscateurs automatiques », il est donc raisonnable de passer aussi un dé-obfuscateur sur la build — mais la première vérification, gratuite, consiste simplement à le lire dans Glass.
4. Vos méthodes sensibles ont-elles vraiment été virtualisées ?
La virtualisation de code est la protection courante la plus forte, et dans Nebula.NET c’est une fonction Pro. Elle convertit l’IL d’une méthode en bytecode pour une petite machine virtuelle intégrée à l’assembly, si bien qu’il ne reste aucun IL ordinaire qu’un décompilateur puisse reconstruire. C’est la vérification où le résultat est sans équivoque. Basculez Glass.NET sur sa vue IL sur une méthode que vous avez virtualisée. Vous ne devriez pas voir votre algorithme. Vous devriez voir un appel à l’interpréteur de la VM avec un argument de données opaque — le bytecode qui ne signifie rien sans le runtime correspondant :
// vue IL d'une méthode virtualisée
IL_0000: ldarg.0
IL_0001: ldsfld uint8[] '<VM>'::'data_7f3a'
IL_0006: call object '<VM>'::Run(object, uint8[])
IL_000b: ret
La vue C# de la même méthode se réduit elle aussi à un unique appel opaque. Si, au contraire, vous pouvez encore lire votre logique dans l’une ou l’autre vue, cette méthode n’a jamais été virtualisée — vérifiez que vous avez marqué les bonnes méthodes, car la virtualisation s’applique de façon sélective (elle est plus lente à l’exécution, vous la réservez donc à votre code le plus sensible, pas à tout l’assembly).
Lisez le rapport d’exposition, puis décidez
Glass.NET produit aussi un rapport d’exposition qui résume quelle part d’un assembly est lisible — une jauge rapide et de haut niveau à passer sur les deux builds. C’est un signal de tri utile, mais il ne remplace pas la lecture des méthodes qui comptent le plus pour vous. Un rapport peut vous dire que le ratio s’est amélioré ; seuls vos propres yeux sur le ValidateLicenseKey décompilé peuvent vous dire que ce que vous cherchiez vraiment à protéger n’est plus à découvert.
Rien de tout cela ne rend votre code impossible à rétro-concevoir — rien ne le fait, et tout outil qui promet « incraquable » vous vend quelque chose. Ce que ce flux de travail vous donne, c’est la vérité : vous pouvez voir exactement de combien vous avez relevé la barre, attraper les passes qui n’ont silencieusement rien fait, et confirmer que vous n’avez pas par accident renommé votre API publique jusqu’à la faire disparaître. Protégez avec Nebula.NET, vérifiez avec Glass.NET — gratuit, purement statique, et le second avis honnête sur votre propre build. Nouveau du côté décompilateur ? Commencez par comment décompiler une DLL .NET en C#.
Essayez Nebula.NET
Renforcez votre code .NET en quelques minutes — commencez avec l'édition gratuite.