Skip to content
← Tous les articles
· Delta1 Labs Obfuscation.NETGuide

Obfusquer une application déployée via ClickOnce : pourquoi l'ordre des opérations décide si elle démarre

Les manifestes ClickOnce stockent un hachage de chaque fichier. Obfusquez après les avoir générés et l'application refuse de démarrer avec une erreur de validation. Voici l'ordre de build exact qui fait cohabiter obfuscation et ClickOnce.

Il existe une manière particulière pour une application ClickOnce d’échouer après l’ajout de l’obfuscation, qui mène les gens sur une tout autre fausse piste : l’application s’installe bien, puis refuse de démarrer avec une erreur de validation de fichier ou de hachage, et rien dans votre code n’a changé. L’instinct est de soupçonner que l’obfuscateur a cassé l’assembly. Ce n’est pas le cas. ClickOnce fait exactement ce pour quoi il est conçu — refuser d’exécuter un fichier dont les octets ne correspondent pas au hachage enregistré — et le vrai bug est l’ordre dans lequel vos étapes de build se sont exécutées. Mettez le bon ordre et obfuscation et ClickOnce cohabitent sans drame.

Pourquoi ClickOnce est inhabituellement sensible

La plupart des mécanismes de déploiement copient des fichiers et les exécutent. ClickOnce fait plus : son manifeste d’application enregistre, pour chaque fichier du déploiement, un hachage cryptographique et une taille, et le runtime ClickOnce vérifie chaque fichier par rapport à cet enregistrement avant le démarrage. C’est une fonction de détection d’altération et de corruption : elle garantit que l’utilisateur exécute exactement ce que vous avez publié.

Cette garantie est précisément ce avec quoi l’obfuscation entre en collision. L’obfuscation réécrit les octets de vos assemblies — renommage, aplatissement du flux de contrôle et chiffrement des chaînes changent tous le fichier. Si le hachage du manifeste pour MyApp.dll a été calculé sur la DLL d’avant obfuscation, la DLL d’après obfuscation que vous livrez réellement ne correspond plus, et ClickOnce s’arrête sur une erreur de validation avant qu’une ligne de votre code ne s’exécute.

Obfuscate before manifests are hashed, not after Ordre correct : compiler obfusquer signernom fort/Authenticode mage : manifesteshache les fichiers finaux Mauvais ordre (l'app ne démarre pas) : compiler mage : manifesteshache les fichiers pré-obf. obfusquer → hachage non concordant au démarrage

Le bon ordre de build

La règle tient en une phrase : toute transformation des assemblies doit avoir lieu avant la génération des manifestes, et la génération des manifestes doit être la dernière. Concrètement :

  1. Compilez le projet.
  2. Obfusquez les assemblies de sortie.
  3. Réappliquez le nom fort si vous avez delay-signé (une obfuscation qui réémet l’assembly doit préserver ou rétablir le nom fort — voir resigner des assemblies obfusquées).
  4. Signez en Authenticode les binaires, si vous les signez.
  5. Générez les manifestes d’application et de déploiement avec mage/mageUI ou les cibles ClickOnce de MSBuild — c’est là que les hachages sont calculés, sur les fichiers désormais finaux.
  6. Signez les manifestes.

Si vous utilisez la Publication en un clic de Visual Studio, le piège est que la publication fait l’étape 5 pour vous juste après la compilation, avant qu’un éventuel hook d’obfuscation post-build ne se soit exécuté. Le correctif est de sortir la génération des manifestes de l’étape de Publication et d’exécuter mage vous-même après l’obfuscation (un petit script de CI), ou d’exécuter l’obfuscation dans le cadre de la build de sorte qu’elle se termine avant l’exécution des cibles ClickOnce.

Un squelette de CI minimal

# 1-2: build then obfuscate the output
dotnet build -c Release -o publish
nebula protect publish/MyApp.dll   # (plus other assemblies)

# 3-4: re-sign as needed
sn -R publish/MyApp.dll keypair.snk           # if delay-signed
signtool sign /f cert.pfx publish/MyApp.dll    # Authenticode (optional)

# 5: generate manifests over the FINAL files (hashes computed now)
mage -New Application -Processor msil -ToFile publish/MyApp.exe.manifest \
     -Name "MyApp" -Version 1.2.0.0 -FromDirectory publish
mage -New Deployment -Processor msil -Install true \
     -ToFile MyApp.application -AppManifest publish/MyApp.exe.manifest \
     -providerUrl "https://downloads.example.com/MyApp/"

# 6: sign the manifests
mage -Sign MyApp.application -CertFile cert.pfx

Comme les hachages de l’étape 5 sont pris sur les assemblies obfusquées et signées, la vérification du runtime ClickOnce passe et l’application démarre.

Le faire avec Nebula

Nebula s’insère dans l’étape d’obfuscation ci-dessus et, comme il s’exécute en étape de build/CI (voir obfusquer uniquement sur le serveur de build et les guides Azure DevOps / GitHub Actions), il est simple de le placer avant la génération des manifestes ClickOnce. Il préserve la signature par nom fort pour que l’étape de resignature soit propre, et ses règles de conservation gèrent toute réflexion WinForms/WPF de votre application. La seule règle propre à ClickOnce est l’ordre — respectez-le et rien d’autre ne change.

Commencez avec l’édition gratuite, ou consultez les offres.

Essayez Nebula.NET

Renforcez votre code .NET en quelques minutes — commencez avec l'édition gratuite.