labreux.fr Veille techno
Rétro-ingénierie · Sécurité logicielle

L'obfuscation de code

Rendre un programme illisible pour un humain tout en le gardant parfaitement exécutable par la machine. Comment ça marche, comment on obfusque, et comment on tente de revenir en arrière.

transformationéquivalence sémantiquecoût / bénéfice
Définition

Ce que c'est, et ce que ce n'est pas

L'obfuscation transforme un code source ou un binaire en une version fonctionnellement identique mais volontairement difficile à comprendre. La machine exécute exactement le même comportement ; c'est seulement le lecteur humain, ou l'outil d'analyse, qu'on cherche à ralentir.

= même résultat

Équivalence

Le programme obfusqué produit les mêmes sorties que l'original pour les mêmes entrées. Sinon, ce n'est pas de l'obfuscation, c'est un bug.

≠ chiffrement

Pas du chiffrement

Un code chiffré doit être déchiffré pour tourner. Un code obfusqué tourne tel quel : tout ce qu'il faut pour le comprendre est déjà là, juste rendu pénible à lire.

⏱ gagne du temps

Un ralentisseur

L'obfuscation n'empêche jamais la compréhension : elle la rend plus coûteuse. On parle de sécurité par l'effort, pas de secret inviolable.

i

À quoi ça sert concrètement ? Protéger de la propriété intellectuelle (algorithmes, clés, logique métier) dans du code livré au client, compliquer le piratage et le cheat dans les jeux, cacher une charge malveillante aux antivirus. Les mêmes techniques servent donc à la défense et à l'attaque.

Mécanisme

Comment on obfusque

Toujours le même principe : appliquer une suite de transformations qui préservent le comportement mais détruisent les repères dont dépend un lecteur — les noms parlants, la structure logique, le flux linéaire, les constantes visibles.

Avant · lisible
// Prix TTC avec remise fidélité
function prixFinal(prix, estFidele) {
  const tva = 1.20;
  let total = prix * tva;
  if (estFidele) {
    total = total * 0.9;
  }
  return total;
}
Après · obfusqué
function _0xa3(_0x1,_0x2){var _0x3=
[0x1e,0x5,0xa][0x0]/0x19+0x1,
_0x4=_0x1*_0x3;return _0x2?(function(_0x5)
{return _0x5-_0x5*(0x1/0xa)})(_0x4)
:_0x4}

Le code de droite calcule exactement la même chose. Mais les noms ne disent plus rien, 1.20 est devenu une expression arithmétique, et la logique est enfouie dans une fonction imbriquée. Voici les transformations courantes, de la plus simple à la plus agressive :

Renommage niveau 1
prixFinal devient _0xa3. On remplace tout identifiant parlant par un symbole opaque. C'est la base, et c'est aussi ce que fait tout « minifieur » pour réduire la taille.
Encodage des chaînes niveau 1
Les textes lisibles ("mot de passe") sont transformés en séquences d'échappement \x6d\x6f\x74, en base64, ou rangés dans un tableau décodé à l'exécution. On ne peut plus faire une simple recherche de texte.
Masquage des constantes niveau 2
Un nombre comme 100 devient 0x1e + 0x46 ou le résultat d'un calcul. La valeur n'apparaît jamais en clair dans le fichier.
Aplatissement du flux niveau 3
La suite naturelle des instructions est éclatée dans une grande boucle pilotée par un switch et une variable d'état. L'ordre réel d'exécution n'est plus visible dans l'ordre du texte.
Code mort & prédicats opaques niveau 3
On insère des branches qui ne s'exécutent jamais, gardées par des conditions toujours vraies ou toujours fausses mais difficiles à prouver (if ((x*x) >= 0)). L'analyste perd du temps sur du code inutile.
Virtualisation niveau 4
Le code est converti en instructions d'une machine virtuelle maison, embarquée dans le programme. Pour comprendre, il faut d'abord comprendre l'interpréteur. C'est la protection la plus lourde — et la plus coûteuse en performance.
Atelier

Essayez vous-même

Tapez du texte ou un identifiant, choisissez une technique, et observez la transformation. Chaque opération est réversible ici : le bouton de déchiffrement montre qu'avec la bonne méthode, on revient toujours à l'original.

Rétro-ingénierie

Comment on déchiffre

Désobfusquer, c'est inverser la démarche : reconstruire les repères qu'on a détruits. On n'a presque jamais besoin de la « clé » de l'obfuscateur, parce qu'il n'y en a pas vraiment — tout est dans le code.

01

Exécuter, pas seulement lire

L'analyse dynamique est l'arme la plus efficace : un débogueur, des points d'arrêt, et on observe les vraies valeurs au moment où elles sont calculées. Les chaînes encodées se décodent toutes seules en mémoire.

02

Rembellir le code

Un « beautifier » ré-indente et réespace un code minifié. Ça ne restaure pas les noms, mais ça rend la structure à nouveau lisible. Première étape sur presque tout JavaScript obfusqué.

03

Évaluer partiellement

Les expressions comme 0x1e + 0x46 peuvent être calculées à froid et remplacées par leur résultat. Des outils d'analyse statique (AST) font ça automatiquement.

04

Renommer par le sens

On observe ce que fait chaque variable et on lui redonne un nom parlant. Travail manuel, mais c'est là que la logique métier réapparaît vraiment.

05

Dérouler le flux

Face à un aplatissement par switch, on reconstitue l'ordre réel des blocs en suivant la variable d'état, souvent avec un script d'analyse dédié.

06

Supprimer le bruit

On identifie les prédicats opaques et le code mort pour les éliminer, ce qui dégonfle le programme à sa logique utile.

!

La règle d'or. Puisque la machine doit toujours pouvoir exécuter le code, toute l'information nécessaire est présente dans le binaire. L'obfuscation ne peut donc pas rendre un programme impossible à comprendre — seulement très long à comprendre. Face à un analyste déterminé, elle n'achète que du temps.

Mise en perspective

Quand est-ce pertinent ?

  • Oui, comme couche parmi d'autres. Pour relever le coût d'une attaque, protéger une astuce commerciale dans un logiciel distribué, ou gagner du temps face au cheat. Jamais comme protection unique.
  • Non, pour cacher un secret durable. Une clé d'API ou un mot de passe dans un code livré finira par être trouvé. Un secret qui doit rester secret ne doit pas se trouver dans le code côté client, obfusqué ou non.
  • Le prix à payer. Code plus lent, plus lourd, plus dur à déboguer pour soi-même, et parfois signalé comme suspect par les antivirus — précisément parce que les logiciels malveillants en abusent.
  • Le bon réflexe sécurité. Chiffrer ce qui doit l'être, garder les secrets côté serveur, et réserver l'obfuscation au rôle qui est le sien : ralentir, pas verrouiller.