Maison > interface Web > js tutoriel > Voici comment créer de l'obscurcissement en JavaScript sans brûler le laboratoire : AST, Babel, plugins.

Voici comment créer de l'obscurcissement en JavaScript sans brûler le laboratoire : AST, Babel, plugins.

DDD
Libérer: 2025-01-10 12:34:44
original
146 Les gens l'ont consulté

Introduction

Hé, avez-vous déjà pensé à quel point vos algorithmes sont cool et uniques ? ? De nombreux programmeurs et entreprises le font, c'est pourquoi ils pourraient hésiter à partager leur travail avec tout le monde. Ce problème s'améliore un peu si une partie du code est déplacée vers le serveur (pour les applications client-serveur), mais cette approche n'est pas toujours possible. Parfois, nous devons laisser des sections de code sensibles à l'air libre.

Dans cet article, nous allons examiner l'obscurcissement dans JavaScript, en créant des moyens de masquer les algorithmes et de rendre plus difficile l'étude du code. Nous explorerons également ce qu'est l'AST et fournirons des outils qui peuvent être utilisés pour interagir avec lui afin de mettre en œuvre l'obscurcissement.

Quel est le problème ?

Voici un exemple idiot. Imaginons cette situation :

  1. Bob se rend sur un site qui offre des écrans d'ordinateur (le voici -> ?). Le moniteur de Bob est meilleur, mais les trucs gratuits sont toujours sympas !
  2. Lorsque Bob visite le site, JavaScript s'exécute dans le navigateur, collectant des données sur l'appareil de l'utilisateur et les envoyant au serveur. Disons que ça y est :
let w = screen.width, h = screen.height;
// Let's say there's a logic with some check. 
console.info(w, h);
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
  1. Malheureusement, Bob ne peut pas accéder à la page des cadeaux, et il en est assez contrarié. Il ne comprend pas pourquoi. Puis il apprend dans les règles du concours que les utilisateurs équipés de grands et bons moniteurs ne sont pas autorisés.

  2. Heureusement, Bob avait suivi des cours d'informatique au lycée. Il ouvre la console développeur de manière décisive en appuyant sur F12, étudie le script et se rend compte que les organisateurs vérifient la résolution de l'écran. Il décide alors de participer depuis son téléphone et réussit le test.

Une histoire fictive avec une fin heureuse - mais cela n'aurait pas pu être aussi bon si le personnage principal avait vu ceci au lieu du code précédent :

l=~[];l={___:++l,$$$$:(![]+"")[l],__$:++l,$_$_:(![]+"")[l],_$_:++l,$_$$:({}+"")[l],$$_$:(l[l]+"")[l],_$$:++l,$$$_:(!""+"")[l],$__:++l,$_$:++l,$$__:({}+"")[l],$$_:++l,$$$:++l,$___:++l,$__$:++l};l.$_=(l.$_=l+"")[l.$_$]+(l._$=l.$_[l.__$])+(l.$$=(l.$+"")[l.__$])+((!l)+"")[l._$$]+(l.__=l.$_[l.$$_])+(l.$=(!""+"")[l.__$])+(l._=(!""+"")[l._$_])+l.$_[l.$_$]+l.__+l._$+l.$;l.$$=l.$+(!""+"")[l._$$]+l.__+l._+l.$+l.$$;l.$=(l.___)[l.$_][l.$_];l.$(l.$(l.$$+"\""+(![]+"")[l._$_]+l.$$$_+l.__+"\"+l.$__+l.___+"\"+l.__$+l.$$_+l.$$$+"\"+l.$__+l.___+"=\"+l.$__+l.___+"\"+l.__$+l.$$_+l._$$+l.$$__+"\"+l.__$+l.$$_+l._$_+l.$$$_+l.$$$_+"\"+l.__$+l.$_$+l.$$_+".\"+l.__$+l.$$_+l.$$$+"\"+l.__$+l.$_$+l.__$+l.$$_$+l.__+"\"+l.__$+l.$_$+l.___+",\"+l.$__+l.___+"\"+l.__$+l.$_$+l.___+"\"+l.$__+l.___+"=\"+l.$__+l.___+"\"+l.__$+l.$$_+l._$$+l.$$__+"\"+l.__$+l.$$_+l._$_+l.$$$_+l.$$$_+"\"+l.__$+l.$_$+l.$$_+".\"+l.__$+l.$_$+l.___+l.$$$_+"\"+l.__$+l.$_$+l.__$+"\"+l.__$+l.$__+l.$$$+"\"+l.__$+l.$_$+l.___+l.__+";\"+l.__$+l._$_+l.$$__+l._$+"\"+l.__$+l.$_$+l.$$_+"\"+l.__$+l.$$_+l._$$+l._$+(![]+"")[l._$_]+l.$$$_+".\"+l.__$+l.$_$+l.__$+"\"+l.__$+l.$_$+l.$$_+l.$$$$+l._$+"(\"+l.__$+l.$$_+l.$$$+",\"+l.$__+l.___+"\"+l.__$+l.$_$+l.___+");"+"\"")())();
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Here
Je vous rassure, ce n'est pas du charabia, c'est du JavaScript ! Et il effectue les mêmes actions. Vous pouvez essayer d'exécuter le code dans la console ici.

Je suppose que dans ce cas, notre héros aurait simplement accepté son sort en ne participant pas au concours, et les organisateurs auraient tenu leur plan.

Alors, à quoi ça sert ici ? Félicitations : vous avez découvert l'outil jjencode, ce qu'est l'obscurcissement et quel rôle il peut jouer.

En résumé, l'obscurcissement est le processus de conversion du code ou des données d'un programme en une forme difficile à comprendre pour les humains mais qui fonctionne toujours pour une machine ou un programme.

Cacher des secrets. Voie rapide

Assez de théories, passons à des exemples plus pratiques ?‍?. Essayons maintenant de convertir le code à l'aide d'obscurcissements que vous êtes plus susceptible de trouver sur Internet. Prenons un code plus intéressant qui contient nos opérations de « savoir-faire ». Et il n'est fortement pas souhaitable que tous ceux qui ne sont pas trop paresseux pour atteindre la F12 puissent les découvrir :

let w = screen.width, h = screen.height;
// Let's say there's a logic with some check. 
console.info(w, h);
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Ce code collecte les données de l'appareil et du navigateur et affiche le résultat sur la console, par exemple (nous utiliserons la sortie comme mesure des performances du code) :

l=~[];l={___:++l,$$$$:(![]+"")[l],__$:++l,$_$_:(![]+"")[l],_$_:++l,$_$$:({}+"")[l],$$_$:(l[l]+"")[l],_$$:++l,$$$_:(!""+"")[l],$__:++l,$_$:++l,$$__:({}+"")[l],$$_:++l,$$$:++l,$___:++l,$__$:++l};l.$_=(l.$_=l+"")[l.$_$]+(l._$=l.$_[l.__$])+(l.$$=(l.$+"")[l.__$])+((!l)+"")[l._$$]+(l.__=l.$_[l.$$_])+(l.$=(!""+"")[l.__$])+(l._=(!""+"")[l._$_])+l.$_[l.$_$]+l.__+l._$+l.$;l.$$=l.$+(!""+"")[l._$$]+l.__+l._+l.$+l.$$;l.$=(l.___)[l.$_][l.$_];l.$(l.$(l.$$+"\""+(![]+"")[l._$_]+l.$$$_+l.__+"\"+l.$__+l.___+"\"+l.__$+l.$$_+l.$$$+"\"+l.$__+l.___+"=\"+l.$__+l.___+"\"+l.__$+l.$$_+l._$$+l.$$__+"\"+l.__$+l.$$_+l._$_+l.$$$_+l.$$$_+"\"+l.__$+l.$_$+l.$$_+".\"+l.__$+l.$$_+l.$$$+"\"+l.__$+l.$_$+l.__$+l.$$_$+l.__+"\"+l.__$+l.$_$+l.___+",\"+l.$__+l.___+"\"+l.__$+l.$_$+l.___+"\"+l.$__+l.___+"=\"+l.$__+l.___+"\"+l.__$+l.$$_+l._$$+l.$$__+"\"+l.__$+l.$$_+l._$_+l.$$$_+l.$$$_+"\"+l.__$+l.$_$+l.$$_+".\"+l.__$+l.$_$+l.___+l.$$$_+"\"+l.__$+l.$_$+l.__$+"\"+l.__$+l.$__+l.$$$+"\"+l.__$+l.$_$+l.___+l.__+";\"+l.__$+l._$_+l.$$__+l._$+"\"+l.__$+l.$_$+l.$$_+"\"+l.__$+l.$$_+l._$$+l._$+(![]+"")[l._$_]+l.$$$_+".\"+l.__$+l.$_$+l.__$+"\"+l.__$+l.$_$+l.$$_+l.$$$$+l._$+"(\"+l.__$+l.$$_+l.$$$+",\"+l.$__+l.___+"\"+l.__$+l.$_$+l.___+");"+"\"")())();
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Prenons maintenant le code ci-dessus et modifions-le avec un obfuscateur populaire pour JS - obfuscator.io. En conséquence, nous obtiendrons un code comme celui-ci :

function getGpuData(){
  let cnv = document.createElement("canvas");
  let ctx = cnv.getContext("webgl");
  const rendererInfo = ctx.getParameter(ctx.RENDERER);
  const vendorInfo = ctx.getParameter(ctx.VENDOR);

  return [rendererInfo, vendorInfo]
}

function getLanguages(){
  return window.navigator.languages;
}

let data = {};
data.gpu = getGpuData();
data.langs = getLanguages();
console.log(JSON.stringify(data))
Copier après la connexion
Copier après la connexion

Voila ! Désormais, seule une machine se fera un plaisir d'analyser ce code (vous et moi n'en faisons probablement pas partie ?). Néanmoins, cela fonctionne toujours et produit le même résultat. Notez les changements :

  1. Les sauts de ligne et les espaces supplémentaires ont disparu.
  2. Les noms de variables ont été remplacés par des noms non informatifs comme _0x587f42.
  3. Les chaînes et les propriétés des objets ont été converties en appels de fonction qui renvoient leurs valeurs à partir d'un tableau par index. Par exemple, document.createElement("canvas") transformé en document[_0x12260c(0x197)](_0x12260c(0x191)). Cela a été rendu possible grâce à l'utilisation de propriétés calculées.

La dernière technique est peut-être la plus désagréable dans ce cas, en termes de surcharge de l'analyse de code statique.

Très bien, on dirait que tous les secrets sont cachés. Devons-nous déployer le code en production ?

Attendez... S'il existe des services pour l'obscurcissement du code, peut-être y en a-t-il qui peuvent retirer ce genre de choses ? Absolument ?, et plus d'un ! Essayons d'en utiliser un - webcrack. Et voyons si nous pouvons obtenir le code original et lisible. Vous trouverez ci-dessous le résultat de l'utilisation de ce désobfuscateur :

{"gpu":["ANGLE (NVIDIA, NVIDIA GeForce GTX 980 Direct3D11 vs_5_0 ps_5_0), or similar","Mozilla"],"langs":["en-US","en"]}
Copier après la connexion
Copier après la connexion

Oups ?. Bien sûr, il n'a pas renvoyé les noms des variables, mais merci pour cela.

Il s'avère donc que le seul obstacle pour étudier sereinement notre code dans ce cas est la volonté du chercheur d'utiliser le désobfuscateur. Sans aucun doute, il est également possible d'utiliser d'autres solutions et personnalisations, mais pour toute obfuscation populaire, il faut très probablement s'attendre à une désobfuscation populaire.

Devrions-nous désespérer et abandonner nos secrets sans combattre ? Bien sûr que non! Voyons ce que nous pouvons faire de plus....

Here

Comment devenir un obfuscateur

Un obfuscateur - cela ressemble à une sorte de mage d'un univers fantastique, n'est-ce pas ? ??‍♂️
Décidément, quelqu'un peut obscurcir le code en l'écrivant et est un magicien né. Il se peut même que vous ayez involontairement pu lancer de tels sorts vous-même pendant un certain temps. Mais que faire maintenant si les compétences ont disparu à cause des critiques des « programmeurs seniors » et que vous avez une idée qui vous permet potentiellement de rendre le programme difficile à étudier ? Dans ce cas, il est logique de se tourner vers des outils qui interagissent avec la structure du code elle-même et permettent de la modifier. Jetons un coup d'œil à eux.

ASTools

Il est également possible d'essayer de modifier le code en interagissant avec lui simplement comme avec du texte, en remplaçant certaines constructions par des expressions régulières etc. Mais je dirais qu'en suivant cette méthode, vous avez plus de chances de ruiner votre code et votre temps que de l'obscurcir.

Pour une modification plus fiable et contrôlée, il est logique de l'amener à une structure abstraite, un arbre (AST - arbre de syntaxe abstraite), en passant par lequel on peut changer les éléments et les constructions qui nous intéressent .

Il existe différentes solutions pour travailler avec du code JS, avec des différences dans l'AST final. Dans cet article, nous utiliserons babel à cet effet. Vous n'avez rien besoin d'installer, vous pouvez tout expérimenter sur une ressource telle qu'astexplorer.

(Si vous ne voulez pas jouer avec Babel, consultez shift-refactor. Il vous permet d'interagir avec AST à l'aide de **sélecteurs CSS. Approche assez minimaliste et pratique pour l'apprentissage et modifier le code. Mais il utilise une version spécifique d'AST, différente de babel. Vous pouvez tester vos requêtes CSS pour cet outil sur la démo interactive shift-query).

.

0. Travailler avec AST

Voyons maintenant comment ces outils peuvent être facilement utilisés sans quitter le navigateur, sur la base d'un exemple simple. Supposons que nous devions changer le nom de la variable de test dans la fonction du même nom en modifié :

let w = screen.width, h = screen.height;
// Let's say there's a logic with some check. 
console.info(w, h);
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Collez ce code dans astexplorer (sélectionnez JavaScript et @babel/parser ci-dessus), il devrait y apparaître comme un AST. Vous pouvez cliquer sur la variable de test pour voir la syntaxe de cette section de code dans la fenêtre de droite :
Here

Pour résoudre notre problème, nous pouvons écrire le plugin babel suivant, qui analysera notre code et y recherchera tous les noms et identifiants et les renommera si certaines conditions sont remplies. Collons-le dans la fenêtre en bas à gauche d'astexplorer (activez le curseur transform et sélectionnez babelv7 pour le faire apparaître) :

let w = screen.width, h = screen.height;
// Let's say there's a logic with some check. 
console.info(w, h);
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

La sortie console est incluse dans ce plugin pour une raison. Cela nous permet de déboguer notre plugin en examinant la sortie dans la console du navigateur. Dans ce cas, nous générons des informations sur tous les nœuds de type Identifiant. Ces informations contiennent des données sur le nœud lui-même (nœud), le nœud parent (parent) et l'environnement (portée - contient des variables créées dans le contexte actuel et des références à celles-ci) :
Here

Ainsi, dans la fenêtre en bas à droite, nous pouvons remarquer que la variable dans notre code source a été modifiée avec succès sans affecter les autres identifiants :

l=~[];l={___:++l,$$$$:(![]+"")[l],__$:++l,$_$_:(![]+"")[l],_$_:++l,$_$$:({}+"")[l],$$_$:(l[l]+"")[l],_$$:++l,$$$_:(!""+"")[l],$__:++l,$_$:++l,$$__:({}+"")[l],$$_:++l,$$$:++l,$___:++l,$__$:++l};l.$_=(l.$_=l+"")[l.$_$]+(l._$=l.$_[l.__$])+(l.$$=(l.$+"")[l.__$])+((!l)+"")[l._$$]+(l.__=l.$_[l.$$_])+(l.$=(!""+"")[l.__$])+(l._=(!""+"")[l._$_])+l.$_[l.$_$]+l.__+l._$+l.$;l.$$=l.$+(!""+"")[l._$$]+l.__+l._+l.$+l.$$;l.$=(l.___)[l.$_][l.$_];l.$(l.$(l.$$+"\""+(![]+"")[l._$_]+l.$$$_+l.__+"\"+l.$__+l.___+"\"+l.__$+l.$$_+l.$$$+"\"+l.$__+l.___+"=\"+l.$__+l.___+"\"+l.__$+l.$$_+l._$$+l.$$__+"\"+l.__$+l.$$_+l._$_+l.$$$_+l.$$$_+"\"+l.__$+l.$_$+l.$$_+".\"+l.__$+l.$$_+l.$$$+"\"+l.__$+l.$_$+l.__$+l.$$_$+l.__+"\"+l.__$+l.$_$+l.___+",\"+l.$__+l.___+"\"+l.__$+l.$_$+l.___+"\"+l.$__+l.___+"=\"+l.$__+l.___+"\"+l.__$+l.$$_+l._$$+l.$$__+"\"+l.__$+l.$$_+l._$_+l.$$$_+l.$$$_+"\"+l.__$+l.$_$+l.$$_+".\"+l.__$+l.$_$+l.___+l.$$$_+"\"+l.__$+l.$_$+l.__$+"\"+l.__$+l.$__+l.$$$+"\"+l.__$+l.$_$+l.___+l.__+";\"+l.__$+l._$_+l.$$__+l._$+"\"+l.__$+l.$_$+l.$$_+"\"+l.__$+l.$$_+l._$$+l._$+(![]+"")[l._$_]+l.$$$_+".\"+l.__$+l.$_$+l.__$+"\"+l.__$+l.$_$+l.$$_+l.$$$$+l._$+"(\"+l.__$+l.$$_+l.$$$+",\"+l.$__+l.___+"\"+l.__$+l.$_$+l.___+");"+"\"")())();
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

J'espère que, sur la base de cet exemple, il est devenu un peu plus clair comment nous pouvons analyser et modifier le code. Quoi qu'il en soit, permettez-moi de résumer le travail effectué :

  1. Nous avons converti le code en AST en utilisant babel via astexplorer.
  2. En examinant l'AST, nous avons vu que la variable de test est étiquetée avec le type Identifier dont le nom peut être défini à l'aide de la propriété name.
  3. Ensuite, à l'aide de notre plugin babel, nous avons contourné tous les identifiants et changé le nom de ceux de la fonction avec le nom test en modifié.

1. Masquage des noms de fonctions et de variables

Il est désormais clair comment modifier le code. Essayons quelque chose de plus utile, que nous pourrons appeler l'obscurcissement :) Nous prendrons un code plus complexe que nous avons essayé d'obscurcir dans la section précédente. Nous allons maintenant remplacer tous les noms de variables et de fonctions par des noms aléatoires. Ainsi, un potentiel ingénieur inverse aurait moins d’informations sur le but de certains éléments de code.

N'hésitez pas non plus à utiliser n'importe quel code JS pour déboguer les problèmes. Comme on dit, il n'y a pas de meilleur professeur que la douleur ?.

Le plugin suivant nous aidera à faire le travail :

function getGpuData(){
  let cnv = document.createElement("canvas");
  let ctx = cnv.getContext("webgl");
  const rendererInfo = ctx.getParameter(ctx.RENDERER);
  const vendorInfo = ctx.getParameter(ctx.VENDOR);

  return [rendererInfo, vendorInfo]
}

function getLanguages(){
  return window.navigator.languages;
}

let data = {};
data.gpu = getGpuData();
data.langs = getLanguages();
console.log(JSON.stringify(data))
Copier après la connexion
Copier après la connexion

À quoi sert ce code ? À peu près la même chose que dans l'exemple précédent :

  1. On passe par tous les nœuds AST de type Identifiant ;
  2. Cette fois, nous utilisons la fonction generateRndName pour générer aléatoirement des noms d'identifiants sans aucune condition ;
  3. La génération de noms uniques garantit que nous n'obtiendrons pas au hasard un nom en double qui pourrait briser la logique du programme.

À la suite de l'exécution de notre plugin, nous obtenons le code suivant avec des noms de variables aléatoires et des fonctions :

{"gpu":["ANGLE (NVIDIA, NVIDIA GeForce GTX 980 Direct3D11 vs_5_0 ps_5_0), or similar","Mozilla"],"langs":["en-US","en"]}
Copier après la connexion
Copier après la connexion

Vous pouvez le vérifier en exécutant le code en console - après nos manipulations, cela fonctionne toujours ! Et c'est la principale qualité d'un bon obfuscateur ✨.

Mais qu’en est-il de la qualité de notre obscurcissement ? Quant à moi, le mal n'est pas encore trop fort : même en remplaçant les noms, il sera facile pour un programmeur expérimenté de comprendre le but de ce code. Et à quoi ça sert si n'importe quel minificateur JS peut gérer cette tâche. Est-il possible maintenant de faire quelque chose de plus pratique et plus gênant pour un inverseur ? Il y a encore un sort...

Here

2. Cacher ? tout!

J'étais peut-être un peu confiant lorsque j'ai écrit « tout », mais ce que nous allons faire maintenant cachera les actions de notre code dans la mesure du possible. Dans cette section, nous allons dissimuler les chaînes et diverses propriétés d'objets afin de compliquer l'analyse statique et potentiellement empêcher le « client » de fouiller dans notre code !

Reprenons le code aux noms cachés obtenu à l'étape précédente et appliquons-lui le plugin suivant :

let w = screen.width, h = screen.height;
// Let's say there's a logic with some check. 
console.info(w, h);
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

J'ai déjà décrit un peu le travail de ce plugin dans les commentaires du code, mais décrivons brièvement étape par étape ce qu'il fait :

  1. Nous créons un tableau data dans lequel stockera toutes les propriétés et chaînes à remplacer dans le code. Ce tableau sera utilisé dans la fonction getData qui renvoie nos données ;
  2. Ensuite, nous parcourons l'AST et trouvons le programme du nœud racine, à l'aide duquel la fonction getData (renvoie les propriétés et les chaînes à un index donné) sera insérée au début de notre code ;
  3. Ensuite, nous contournons les nœuds de type MemberExpression. Nous remplaçons les propriétés par des appels à la fonction getData. Dans ce cas, les constructions comme document.createElement seront transformées en document[getData(0)], grâce aux propriétés calculées. En cours de route, nous mettons les noms des propriétés dans le tableau de données ;
  4. Enfin, nous contournons les nœuds de type StringLiteral, où nous remplaçons également les chaînes par un appel à getData avec l'index souhaité.

Il convient de mentionner que les opérations d'analyse ne sont pas effectuées séquentiellement, mais au fur et à mesure que le nœud nécessaire est trouvé lors du traitement AST.

À la suite de l'exécution de ce plugin, nous obtiendrons le code suivant :

l=~[];l={___:++l,$$$$:(![]+"")[l],__$:++l,$_$_:(![]+"")[l],_$_:++l,$_$$:({}+"")[l],$$_$:(l[l]+"")[l],_$$:++l,$$$_:(!""+"")[l],$__:++l,$_$:++l,$$__:({}+"")[l],$$_:++l,$$$:++l,$___:++l,$__$:++l};l.$_=(l.$_=l+"")[l.$_$]+(l._$=l.$_[l.__$])+(l.$$=(l.$+"")[l.__$])+((!l)+"")[l._$$]+(l.__=l.$_[l.$$_])+(l.$=(!""+"")[l.__$])+(l._=(!""+"")[l._$_])+l.$_[l.$_$]+l.__+l._$+l.$;l.$$=l.$+(!""+"")[l._$$]+l.__+l._+l.$+l.$$;l.$=(l.___)[l.$_][l.$_];l.$(l.$(l.$$+"\""+(![]+"")[l._$_]+l.$$$_+l.__+"\"+l.$__+l.___+"\"+l.__$+l.$$_+l.$$$+"\"+l.$__+l.___+"=\"+l.$__+l.___+"\"+l.__$+l.$$_+l._$$+l.$$__+"\"+l.__$+l.$$_+l._$_+l.$$$_+l.$$$_+"\"+l.__$+l.$_$+l.$$_+".\"+l.__$+l.$$_+l.$$$+"\"+l.__$+l.$_$+l.__$+l.$$_$+l.__+"\"+l.__$+l.$_$+l.___+",\"+l.$__+l.___+"\"+l.__$+l.$_$+l.___+"\"+l.$__+l.___+"=\"+l.$__+l.___+"\"+l.__$+l.$$_+l._$$+l.$$__+"\"+l.__$+l.$$_+l._$_+l.$$$_+l.$$$_+"\"+l.__$+l.$_$+l.$$_+".\"+l.__$+l.$_$+l.___+l.$$$_+"\"+l.__$+l.$_$+l.__$+"\"+l.__$+l.$__+l.$$$+"\"+l.__$+l.$_$+l.___+l.__+";\"+l.__$+l._$_+l.$$__+l._$+"\"+l.__$+l.$_$+l.$$_+"\"+l.__$+l.$$_+l._$$+l._$+(![]+"")[l._$_]+l.$$$_+".\"+l.__$+l.$_$+l.__$+"\"+l.__$+l.$_$+l.$$_+l.$$$$+l._$+"(\"+l.__$+l.$$_+l.$$$+",\"+l.$__+l.___+"\"+l.__$+l.$_$+l.___+");"+"\"")())();
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Comme vous pouvez le voir sur le code résultant, toutes les propriétés ont été remplacées par des appels de fonction getData avec un index donné. Nous avons fait la même chose avec les chaînes et avons commencé à les obtenir via des appels de fonction. Les noms de propriétés et les chaînes elles-mêmes ont été codées en base64 pour les rendre plus difficiles à remarquer...

Here

Je suppose que vous l'avez déjà remarqué - ce plugin, et le code en général, présente des défauts à ce stade. Par exemple, les éléments suivants pourraient être corrigés :

  • Les fonctions renvoyant nos propriétés et nos chaînes crient sur leur objectif : getData. Mais ce qui est bien, c'est que ce point peut être corrigé en appliquant notre premier plugin, qui renomme les identifiants.
  • Les chaînes elles-mêmes à l'intérieur de la fonction getData ne sont pas protégées de manière fiable, il est assez facile de retrouver leurs valeurs initiales, car il s'agit uniquement de base64. Il est plus difficile de résoudre ce problème, par exemple, vous pouvez recréer la fonction getData et appliquer le cryptage au lieu du codage bien connu.
  • La fonction getData est la seule, et il n'est pas difficile d'écrire un script qui remplacera tous ses appels par la valeur d'origine en extrayant et en exécutant la fonction elle-même.

Malgré toute cette simplicité et ces inconvénients, je pense que cela peut déjà être qualifié d'obscurcissement. Mais là encore, en quoi différons-nous des obfuscateurs open source, puisqu’ils font des choses similaires ?

Nous devons nous rappeler le problème initial : ces obscurcissements étaient un jeu d'enfant pour les désobfuscateurs publics. Maintenant, prenons ce code que nous avons obtenu et désobstruons-le dans webcrack ! (j'espère qu'il ne pourra toujours pas résoudre notre sort ?). Je suppose que l'on pourrait dire que l'importance pratique a été atteinte : notre code « protégé » ne peut plus être récupéré en un clic via un désobfuscateur public

Prime. Désobscurcissement

Apprenons maintenant un tout nouveau sort. Bien que les désobfuscateurs publics ne soient pas capables de gérer nos plugins, après avoir étudié le concept même de notre obfuscation, nous pouvons remarquer certains modèles qui peuvent être utilisés pour restaurer le code source.

Entrons dans le vif du sujet, et profitons spécifiquement de :

  • Avoir une seule fonction invoquée qui stocke nos propriétés et nos chaînes ;
  • Les appels à cette fonction ne sont pas masqués ;

Compte tenu de ces inconvénients, nous pouvons implémenter le plugin suivant :

let w = screen.width, h = screen.height;
// Let's say there's a logic with some check. 
console.info(w, h);
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Décrivons les fonctionnalités de ce plugin de désobscurcissement :

  1. Nous avons copié la fonction getData à partir du code obscurci, en l'exécutant avec l'argument requis (index), nous pouvons obtenir la chaîne requise ;
  2. Nous avons parcouru tous les appels de la fonction getData et les avons remplacés par le résultat de son exécution ;
  3. Enfin, nous avons trouvé la fonction getData dans AST et l'avons supprimée du code, car elle n'y est plus nécessaire.

En conséquence, nous obtenons le code suivant :

l=~[];l={___:++l,$$$$:(![]+"")[l],__$:++l,$_$_:(![]+"")[l],_$_:++l,$_$$:({}+"")[l],$$_$:(l[l]+"")[l],_$$:++l,$$$_:(!""+"")[l],$__:++l,$_$:++l,$$__:({}+"")[l],$$_:++l,$$$:++l,$___:++l,$__$:++l};l.$_=(l.$_=l+"")[l.$_$]+(l._$=l.$_[l.__$])+(l.$$=(l.$+"")[l.__$])+((!l)+"")[l._$$]+(l.__=l.$_[l.$$_])+(l.$=(!""+"")[l.__$])+(l._=(!""+"")[l._$_])+l.$_[l.$_$]+l.__+l._$+l.$;l.$$=l.$+(!""+"")[l._$$]+l.__+l._+l.$+l.$$;l.$=(l.___)[l.$_][l.$_];l.$(l.$(l.$$+"\""+(![]+"")[l._$_]+l.$$$_+l.__+"\"+l.$__+l.___+"\"+l.__$+l.$$_+l.$$$+"\"+l.$__+l.___+"=\"+l.$__+l.___+"\"+l.__$+l.$$_+l._$$+l.$$__+"\"+l.__$+l.$$_+l._$_+l.$$$_+l.$$$_+"\"+l.__$+l.$_$+l.$$_+".\"+l.__$+l.$$_+l.$$$+"\"+l.__$+l.$_$+l.__$+l.$$_$+l.__+"\"+l.__$+l.$_$+l.___+",\"+l.$__+l.___+"\"+l.__$+l.$_$+l.___+"\"+l.$__+l.___+"=\"+l.$__+l.___+"\"+l.__$+l.$$_+l._$$+l.$$__+"\"+l.__$+l.$$_+l._$_+l.$$$_+l.$$$_+"\"+l.__$+l.$_$+l.$$_+".\"+l.__$+l.$_$+l.___+l.$$$_+"\"+l.__$+l.$_$+l.__$+"\"+l.__$+l.$__+l.$$$+"\"+l.__$+l.$_$+l.___+l.__+";\"+l.__$+l._$_+l.$$__+l._$+"\"+l.__$+l.$_$+l.$$_+"\"+l.__$+l.$$_+l._$$+l._$+(![]+"")[l._$_]+l.$$$_+".\"+l.__$+l.$_$+l.__$+"\"+l.__$+l.$_$+l.$$_+l.$$$$+l._$+"(\"+l.__$+l.$$_+l.$$$+",\"+l.$__+l.___+"\"+l.__$+l.$_$+l.___+");"+"\"")())();
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Here

Ainsi, nous avons pu nous débarrasser de l'obscurcissement qui cache les propriétés et les chaînes en écrivant un simple plugin pour babel en utilisant les inconvénients indiqués.

J'espère que ce petit exemple vous a expliqué comment lutter contre de telles nuisances avec l'aide de babel. En utilisant ces approches, vous pouvez également résoudre des obscurcissements plus complexes - l'essentiel est de trouver des modèles dans le code et d'opérer habilement avec AST.

Conclusion

Nous avons découvert l'obscurcissement, une technique qui complique l'ingénierie inverse du code, et les outils pour la mettre en œuvre. Bien qu'il existe des solutions publiques qui obscurcissent le code JavaScript, il existe tout autant de solutions publiques qui peuvent supprimer cette protection en un instant.

Par conséquent, vous devez écrire vos propres solutions pour protéger le code qui ne peut pas être supprimé par les désobfuscateurs publics. Un moyen fiable d'implémenter l'obscurcissement dans JS consiste à écrire des plugins Babel personnalisés qui interagissent avec l'AST du code souhaité, le transformant en une forme moins lisible.

Bien sûr, ce domaine connaît des techniques et des approches d'obscurcissement, mais reste néanmoins ouvert à la créativité et aux nouvelles « astuces » qui peuvent potentiellement rendre l'apprentissage du code plus difficile. Malgré le grand nombre de ces techniques, elles ne garantissent pas du tout le secret des algorithmes, car le code est toujours « entre les mains » du client. De plus, il existe une possibilité de débogage, ce qui peut faciliter l'étude du code. L’obscurcissement permet plutôt de refuser des chercheurs peu motivés, augmentant ainsi le coût de l’ingénierie inverse.

Il existe des approches avancées, par exemple, l'une d'elles parmi l'obscurcissement est la virtualisation du code, ou tout simplement, la création d'une machine virtuelle en JS qui exécutera du bytecode personnalisé. Cette approche supprime presque complètement les risques d'analyse statique et rend le débogage aussi difficile que possible. Cependant, il s'agit d'un sujet de discussion distinct ?....

J'espère qu'il vous a été utile d'obtenir des informations sur ce sujet, et que vous ne vous blâmerez plus, ni à vos programmeurs, pour un code initialement obscurci. Appréciez ces sorciers ??‍♀️ ! Je serai heureux de discuter avec vous des dernières tendances en matière de magie ici ?

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal