Introduction

Les debuggers sont des outils indispensables pour analyser JavaScript, particulièrement lorsqu’il s’agit de code obfusqué et de protections côté client. Les développeurs et les chercheurs en sécurité s’appuient sur eux pour comprendre le fonctionnement d’une application web, découvrir des vulnérabilités ou contourner des restrictions.

Problématique

Cependant, de nombreuses entreprises et développeurs mettent en place des techniques d’anti-debugging pour rendre plus difficile l’analyse de leur code. Ils injectent des scripts qui détectent quand le navigateur est en mode debug, utilisent des astuces d’obfuscation, ou désactivent même de force les breakpoints. Cela rend le processus d’analyse JavaScript incroyablement frustrant, particulièrement lorsqu’il s’agit de protections propriétaires ou de mécanismes de sécurité conçus pour empêcher la rétro-ingénierie.

Message de détection d’anti-debugging
Exemple d'un message typique de détection de debugger

Désactiver les breakpoints : Une solution simple mais limitée

Une façon simple de contourner certains mécanismes de détection du debugger est de désactiver complètement les breakpoints. Cela empêche JavaScript de mettre en pause l’exécution, rendant inopérants les scripts d’anti-debugging.

Désactivation des breakpoints
Désactivation des breakpoints dans les outils de développement Firefox

Cependant, cette méthode présente un compromis important : elle désactive également la capacité d’analyser efficacement l’exécution JavaScript. Bien que cela puisse fonctionner dans certains cas, ce n’est pas une solution idéale pour une analyse plus approfondie, car perdre la capacité de définir des breakpoints limite sévèrement notre capacité à inspecter les variables, modifier le flux d’exécution ou analyser comment le code se comporte en temps réel.

Renommer le debugger dans le code source de Firefox

⚠️ Note importante : Cette technique ne doit être utilisée que pour la recherche légitime en sécurité, le développement logiciel et les tests autorisés. La rétro-ingénierie non autorisée peut violer les conditions d’utilisation ou les exigences légales.

Le problème principal avec les restrictions de débogage est que les sites web s’appuient sur des méthodes spécifiques pour détecter la présence du debugger. En changeant le nom interne du debugger Firefox dans le code source, nous pouvons contourner ces mécanismes de détection sans perdre la fonctionnalité de débogage.

Obtenir le code source de Firefox et le compiler (Instructions pour macOS)

Pour une documentation détaillée, référez-vous à : 🔗 Documentation source Firefox

1. Installer Xcode

Téléchargez et installez Xcode depuis l’App Store. Puis finalisez l’installation dans votre terminal :

$ sudo xcode-select --switch /Applications/Xcode.app
$ sudo xcodebuild -license

2. Installer Mercurial

Mercurial est nécessaire pour récupérer le code source de Firefox :

$ python3 -m pip install --user mercurial

3. “Bootstrapper” une copie du code source de Firefox

Exécutez les commandes suivantes pour obtenir une copie locale du code source :

$ curl https://hg.mozilla.org/mozilla-central/raw-file/default/python/mozboot/bin/bootstrap.py -O
$ python3 bootstrap.py

⚠️ Attention : Le téléchargement du code source de Firefox nécessite environ 15 Go d’espace disque et peut prendre du temps selon votre connexion internet.

Lors de l’exécution du script bootstrap, vous serez invité à choisir diverses options de configuration, suivez ensuite les instructions et confirmez l’installation des outils ou dépendances requis.

4. Compiler et exécuter Firefox

Une fois la configuration terminée on peut compiler le code source :

$ cd mozilla-unified
$ hg up -C central
$ ./mach build

Pour référence, la compilation de Firefox a pris environ 30 minutes sur un système avec 10 cœurs CPU et 32 Go de RAM.

Après la compilation réussie, vous pouvez exécuter le Firefox modifié avec :

$ ./mach run

Après une compilation réussie, vous trouverez votre Firefox compilé à :

obj-aarch64-apple-darwin*/dist/Nightly.app

*Note : Le chemin exact peut varier selon votre architecture système et version.

Modification du code source

Vient maintenant la partie la plus intéressante et étonnamment simple : modifier le code source de Firefox pour renommer le mot-clé “debugger”. Pour y parvenir, j’ai recherché dans le code source toutes les occurrences de “debugger”, compilé le navigateur plusieurs fois, et identifié les emplacements exacts qui devaient être modifiés. L’objectif était de renommer le debugger en interne en “debuggy” pour que les scripts d’anti-debugging ne le détectent plus.

Les modifications ont été effectuées dans les deux fichiers suivants :

  • mozilla-unified/js/src/frontend/ReservedWords.h
  • mozilla-unified/js/src/vm/CommonPropertyNames.h

Voici les 2 modifications à effectuer :

diff --git a/js/src/frontend/ReservedWords.h b/js/src/frontend/ReservedWords.h
--- a/js/src/frontend/ReservedWords.h
+++ b/js/src/frontend/ReservedWords.h
@@ -20,7 +20,7 @@
   MACRO(catch, catch_, TokenKind::Catch)                                  \
   MACRO(const, const_, TokenKind::Const)                                  \
   MACRO(continue, continue_, TokenKind::Continue)                         \
-  MACRO(debugger, debugger, TokenKind::Debugger)                          \
+  MACRO(debuggy, debugger, TokenKind::Debugger)                          \
   MACRO(default, default_, TokenKind::Default)                            \
   MACRO(delete, delete_, TokenKind::Delete)                               \
   MACRO(do, do_, TokenKind::Do)                                           \
diff --git a/js/src/vm/CommonPropertyNames.h b/js/src/vm/CommonPropertyNames.h
--- a/js/src/vm/CommonPropertyNames.h
+++ b/js/src/vm/CommonPropertyNames.h
@@ -129,7 +129,7 @@
   MACRO_(daysInMonth, "daysInMonth")                                           \
   MACRO_(daysInWeek, "daysInWeek")                                             \
   MACRO_(daysInYear, "daysInYear")                                             \
-  MACRO_(debugger, "debugger")                                                 \
+  MACRO_(debugger, "debuggy")                                                 \
   MACRO_(decimal, "decimal")                                                   \
   MACRO_(decodeURI, "decodeURI")                                               \
   MACRO_(decodeURIComponent, "decodeURIComponent")                             \

Une fois les modifications en place, j’ai recompilé le navigateur en utilisant la même commande de compilation (cela prend 15 secondes cette fois :D).

Résultats : Détection du debugger contournée !

Comme montré ci-dessous, un script d’anti-debugging ne parvient pas à détecter notre mot-clé debugger modifié :

Mot-clé debugger non reconnu
Le mot-clé 'debugger' original n'est plus reconnu

La protection du site ne détecte plus le débogage :

Protection contournée
Protection anti-debugging contournée avec succès

Et notre debugger fonctionne toujours parfaitement, juste sous un nom différent :

debugger modifié
Notre debugger fonctionnant avec le nouveau mot-clé 'debuggy'

Conclusion

En renommant le debugger en interne dans le code source de Firefox, nous avons réussi à contourner les techniques d’anti-debugging JavaScript tout en conservant une fonctionnalité complète de débogage. Contrairement à la simple désactivation des breakpoints — une approche qui limite l’analyse ultérieure — cette méthode permet un débogage ininterrompu sans déclencher de protections.

Modification : 10/02/25

Un ami avait besoin d’une version compilée pour Mac Intel, alors je l’ai compilée en cross-compilation.

Pour une documentation détaillée, référez-vous à : 🔗 Guide de cross-compilation Firefox

J’ai modifié le fichier .mozconfig et ajouté les lignes suivantes :

ac_add_options --target=x86_64-apple-darwin
ac_add_options --enable-bootstrap

Après recompilation, j’ai réussi à construire une version Mac Intel !

Télécharger les versions pré-compilées

Voici des versions modifiées de Firefox Nightly pour macOS :

🔹 Version Apple Silicon (ARM64) : 📥 Télécharger Nightly_aarch64.tar.xz

🔹 Version Mac Intel (x86_64) : 📥 Télécharger Nightly_x86_64.tar.xz