147 votes

Quelles sont les chaînes intégrées de JavaScript ?

cette question est difficile à résumer dans un titre de question

UPDATE J'ai créé un JSFiddle qui construit une chaîne obfusquée à partir de votre entrée en se basant sur les lettres extraites de cette question : Vous pouvez y accéder ici ou est-ce qu'un Gist être plus facile ?

Je suis récemment tombé sur un amusant morceau de JavaScript obscurci dans ce profil qui ressemble à ça :

javascript:[[]+1/!1][1^1][1>>1]+({}+[])[1<<1^11>>1]+([]+!!-
[])[1<<1]+[/~/+{}][+!1][-~1<<1]+([]+/-/[(!!1+[])[1>>1]+(!!1
+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1]+([,][
~1]+[])[1-~1]+[[]+{}][!1.1%1][11111.1%11.1*111e11|!1]+(/1/+
1/[1<1][1%1])[1^11]+[[],[]+{}][1][+1]+(/<</[1]+[])[1/1.1&1]

Désolé de gâcher la surprise, mais quand on l'évalue, on obtient ceci :

"I love you" in Chrome
"I lone you" In Firefox
"I lo[e you" in IE10

La façon dont cela fonctionne est de générer une série de messages et d'en tirer des lettres comme suit (en utilisant le "I" comme exemple) :

[]+1/!1
returns
"Infinity"
then
[[]+1/!1]
creates this array:
["Infinity"]
then
[[]+1/!1][1^1]
Takes the first (1^1 == 0) element of that array
"Infinity"
finally
[[]+1/!1][1^1][1>>1]
Takes the first (1>>1 == 0) char of that string
"I"

D'autres chaînes de caractères sont générées :

({}+[])       -> "[object Object]" (where the space comes from)
([]+!!-[])    -> "false" (used for it's "l")
[/~/+{}][+!1] -> "/~/[object Object]" (this is used for an "o")
(/<</[1]+[])  -> "undefined"

J'ai essayé de trouver un remplacement pour le "n" et le "[" et j'ai trouvé ceci :

String.fromCharCode(('1'.charCodeAt(0)<<1)+(10<<1))

Ce qui, à mon avis, est dans l'esprit de l'utilisation des 1 et des 0, mais viole l'un des aspects les plus élégants du code original qui est l'apparence de n'avoir rien à faire avec les chaînes de caractères. Est-ce que quelqu'un d'autre a une idée de la façon de générer un "v" qui soit en accord avec le code obfusqué original ?

Voici quelques informations supplémentaires qui ont été trouvées après que de nombreux programmeurs JavaScript talentueux aient jeté un coup d'œil plus approfondi sur cette question.

Firefox renvoie "I lone you" à cause de cette ligne :

([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1]+

[1^11<<1] enlève un caractère spécifique de celui-ci :

([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])

Ce qui donne ceci :

"function test() {
    [native code]
}"

On dirait qu'on pourrait avoir notre "V" ! !!

Chrome renvoie "I love you", car le même code renvoie ceci :

"function test() { [native code] }"

Avant que la question ne soit fermée pour cause de lien douteux avec "un vrai problème de programmation", j'ai pensé ajouter une solution résumée qui s'appuie sur les principes suivants @Supr's , @Cory's y @alpha123's , regardez :

alert([[]+1/!1][1^1][1>>1]+({}+[])[1<<1^11>>1]+(
[]+!!-[])[1<<1]+[/~/+{}][+!1][-~1<<1]+[([]+/-/[(
!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(
!!1+[])[1^1]])[1+(1^(11+1+1)<<1)],([]+/-/[(!!1+[
])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[
])[1^1]])[1^11<<1],([]+/-/[(!!1+[])[1>>1]+(!!1+[
])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^(11
+1+1)<<1]][((([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<
1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1<<1<<1<<1
)+1<<1]==({}+[])[1^1])*1)+((([]+/-/[(!!1+[])[1>>
1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1
]])[(1^11<<1)-1]==({}+[])[1^1])<<1)]+([,][~1]+[]
)[1-~1]+[[]+{}][!1.1%1][11111.1%11.1*111e11|!1]+
(/1/+1/[1<1][1%1])[1^11]+[[],[]+{}][1][+1]+(/<</
[1]+[])[1/1.1&1])

Étant donné la complexité du code et le message qu'il produit, c'est presque comme si le moteur JavaScript disait à quel point vous le faites se sentir spécial :)

83voto

VisioN Points 62518

Tout d'abord, je tiens à remercier Jason et tous les contributeurs pour avoir joué avec ce petit bout d'humour. J'ai écrit ce bout de code juste pour le plaisir afin de l'envoyer à ma femme le 14 février :) N'ayant que Chrome installé sur l'ordinateur portable, je n'avais pas la possibilité de vérifier comment cela fonctionne dans Firefox et IE. De plus, je ne m'attendais pas vraiment à ce que toString() La représentation des méthodes intégrées peut être différente dans d'autres navigateurs.

Maintenant, passer au vrai problème Pour cela, regardons précisément le code. Oui, "v" était le vrai "problème" ici. Je n'ai pas trouvé d'autres moyens d'obtenir cette lettre que l'analyse syntaxique [native code] chaîne de caractères, qui peut être prise dans n'importe quelle méthode intégrée. Puisque je me suis limité à n'avoir aucune chaîne de caractères et aucun nombre, à l'exception de 1 utilisé, j'avais besoin d'exploiter une méthode qui n'a que des caractères disponibles dans son nom.

Les caractères disponibles peuvent être obtenus à partir de mots-clés existants et de représentations de chaînes de caractères, c'est-à-dire que dès le départ, nous avions NaN , null , undefined , Infinity , true , false et "[object Object]" . Certains d'entre eux peuvent être facilement convertis en chaînes de caractères, par ex. 1/!1+[] da "Infinity" .

J'ai analysé différentes méthodes intégrées pour les tableaux. [] , objets {} des expressions régulières /(?:)/ , numéros 1.1 , cordes "1" et a découvert une belle méthode de RegExp objet appelé test() . Son nom peut être assemblé à partir de tous les caractères disponibles, par ex. "t" y "e" de true et "s" de false . J'ai créé une chaîne de caractères "test" et abordé cette méthode en utilisant la notation entre crochets pour le littéral de la regex /-/ correctement identifié dans cette ligne :

/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]]

Comme nous l'avons déjà dit, ce morceau de code est évalué dans Chrome comme :

function test() { [native code] }

dans Firefox comme :

function test() {
    [native code]
}

et dans IE comme :

 function test() {     [native code] }  

(dans cette dernière paie spécial attention à l'espace qui précède function mot-clé)

Donc, comme vous le voyez clairement, mon code récupérait le 24ème caractère de la chaîne présentée, qui dans Chrome était "v" (comme prévu), mais malheureusement dans Firefox et IE -- "n" y "[" respectivement.

Afin d'obtenir le même résultat dans tous les navigateurs, j'ai utilisé la méthode suivante approche différente qu'illustré dans les autres réponses. Maintenant la version modifiée ressemble à ça :

javascript:[[]+1/!1][1^1][1>>1]+({}+[])[1<<1^11>>1]+([]+!!-
[])[1<<1]+[/~/+{}][+!1][-~1<<1]+/\[[^1]+\]/[([]+![])[1<<1<<
1]+(/|/[(1+{})[1+11>>>1]+[[]+{}][+!1][1]+([]+1/[])[1<<1>>1]
+([1<1]+[])[1+11>>>1+1]+[[!!1]+1][+[]][1-1]+([]+!!/!/)[1|1]
+(/1/[1]+[])[!1%1]+(-{}+{})[-1+1e1-1]+(1+[!!1])[1]+([]+1+{}
)[1<<1]+[!!/!!/+[]][+[]][1&1]]+/=/)[1e1+(1<<1|1)+(([]+/-/[(
!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1
]])[1^1]==+!1)]+(!![]+{})[1|1<<1]+[1+{}+1][!1+!1][(11>>1)+1
]](([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+
(!!1+[])[1^1]]))[1&.1][11>>>1]+([,][~1]+[])[1-~1]+[[]+{}][!
1.1%1][11111.1%11.1*111e11|!1]+(/1/+1/[1<1][1%1])[1^11]+[[]
,[]+{}][1<<1>>>1][1||1]+(/[<+>]/[1&1|1]+[1.1])[1/11.1&1.11]

Cependant, afin d'intriguer les lecteurs, je ne fournirai pas de solution à ce problème. Je pense sincèrement que vous comprendrez facilement comment cela fonctionne... et certains pourront même surprendre leur bien-aimé(e) en utilisant le cross-browser ;)

P.S. Encore un autre obfuscateur

Inspiré par l'idée de Jason de créer un outil d'obfuscation universel, j'en ai écrit un autre. Vous pouvez le trouver à JSBin : http://jsbin.com/amecoq/2 . Il peut obscurcir tout texte contenant des chiffres. [0-9] en petites lettres latines [a-z] et des espaces. La longueur de la chaîne de caractères est limitée principalement par votre RAM (au moins le corps de ma réponse a été obfusqué avec succès). La sortie est supportée par Chrome, Firefox, et IE.

Un conseil : l'outil utilise une approche d'obfuscation différente de celle présentée ci-dessus.

26voto

Supr Points 4738

Pourquoi le native code de la question utilisée ? Celle-ci donne un 'v' dans Chrome et Firefox :

([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1]>([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^(11+1+1)<<1]?([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1]:([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^(11+1+1)<<1]

Modifier pour supporter IE et le faire sans l'opérateur ternaire : Celui-ci fonctionne dans Chrome, IE et FF. Construit un tableau et utilise == pour déterminer le navigateur.

[([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1+(1^(11+1+1)<<1)],([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1],([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^(11+1+1)<<1]][((([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1<<1<<1<<1)+1<<1]==({}+[])[1^1])*1)+((([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1^11<<1)-1]==({}+[])[1^1])<<1)]

Lisible :

[
    //ie
    ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1+(1^(11+1+1)<<1)],
    //ch
    ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1],
    //ff
    ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^(11+1+1)<<1]
]
[
    //ch?
    ((([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1<<1<<1<<1)+1<<1]==({}+[])[1^1])*1)+
    //ff?
    ((([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1^11<<1)-1]==({}+[])[1^1])<<1)
]

8voto

Cory Points 37551

C'est à peu près ce que j'ai pu obtenir, malheureusement cela viole la convention de l'obfuscation originale en faisant un appel à unescape() :

unescape((/%/+[])[1]+(/1/[1]+[])[1%1]+(+!1)+(+!1)+(1e1+(11*(1-~1)<<1)))

Démontage :

(/%/+[])[1]          => "%"
(/1/[1]+[])[1%1]     => "u"
(+!1)                => "0"
(+!1)                => "0"
(1e1+(11*(1-~1)<<1)) => "76"
===========================
unescape("%u0076")   => "v"

D'autres idées :

  1. D'une manière ou d'une autre, arriver à unescape("\x76")
  2. En quelque sorte, convertir 118 sans appeler String.fromCharCode()
  3. Obtenez le texte d'une exception contenant le mot "Invalid".

Mises à jour :

J'ai commencé à jouer au golf codé et je l'ai raccourci, en remplaçant certaines parties par d'autres plus importantes. 1 s, etc.

4voto

alpha123 Points 3600

Voici la partie qui génère le n/v :

([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1]

Dans Firefox, ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]]) évalue à

"function test() {
    [native code]
}"

alors que dans Chrome, c'est

"function test() { [native code] }"

1^11<<1 est égal à 23. En raison de l'espacement supplémentaire de Firefox, ce chiffre n'est pas suffisant pour atteindre le "v", qui est remplacé par "n".

Et c'est pourquoi il ne faut pas compter sur le comportement de Function#toString ;)

EDIT : J'ai enfin trouvé une version cross-browser raisonnablement obfusquée :

[[]+1/!1][1^1][1>>1]+({}+[])[1<<1^11>>1]+([]+!!-[])[1<<1]+[/~/+{}][+!1][-~1<<1]+([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1^11<<1)+(parseInt("010")<10?(1+1+1+1):0)]+([,][~1]+[])[1-~1]+[[]+{}][!1.1%1][11111.1%11.1*111e11|!1]+(/1/+1/[1<1][1%1])[1^11]+[[],[]+{}][1][+1]+(/<</[1]+[])[1/1.1&1]

Cela remplace la section n/v par :

([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1^11<<1)+(parseInt("010")<10?(1+1+1+1):0)]

qui exploite les différences de parseInt (apparemment Firefox analyse les nombres commençant par 0 en octal, alors que Chrome ne le fait pas) pour ajouter 4 dans le cas de Firefox, obtenant ainsi 'v' à partir de 'native' dans les deux cas (je ne peux pas trouver un autre 'v' :P).
Le parseInt semble un peu déplacé, mais c'est le mieux que je puisse faire pour l'instant.

4voto

svidgen Points 4012

Pour le général si la casse des caractères n'est pas une préoccupation majeure, je pourrais être enclin à tricher un peu.

Créez la fonction "c" qui transforme un nombre 0 25 en un caractère.

c=function(v){for(var i in window){for(var ci in i){if(parseInt(i[ci],(10+11+11)+(1<<1)+(1<<1))==(v+10)){return i[ci]}}}};

Pour des raisons de performances, mettez les lettres en pré-cache, si vous le souhaitez.

l=[];for(var i=0; i<(11+11)+(1<<1)+(1<<1);i++){l[i]=c(i);}

Dans la console Chrome, le tableau résultant ressemble à ceci :

> l;
["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "K", "l", "m", "n", "o", "p", "q", "r", "S", "t", "u", "v", "w", "x", "y", "Z"]

Alors ... votre v pourrait être l[10+10+1] .

On peut aussi opter pour une solution générale comme celle-ci :

p=(function(){10%11}+[])[1+11+(1<<1)]; // "%"
u=(function(){club=1}+[])[1+11+(1<<1)]; // "u"
vc=p+u+(0+[])+(0+[])+((111>>1)+11+10+[]); // "%u0076"
unescape(vc);

Ou, pour cette spécifique problème, peut-être juste :

(function(){v=1}+[])[10+(1<<1)]; // "v"

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X