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

147

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

MISE À JOUR J'ai créé un JSFiddle qui construit une chaîne masquée à partir de votre entrée en fonction des lettres extraites de cette question: vous pouvez y accéder ici , ou est-ce que l' essentiel serait plus facile?

Je suis récemment tombé sur un peu amusant de JavaScript obscurci dans ce profil qui ressemble à ceci:

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 lorsque cela est évalué, il renvoie ceci:

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

La façon dont cela fonctionne une fois éclaté, est de générer une série de messages et d'en extraire des lettres comme ceci (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"

Les autres chaînes générées incluent:

({}+[])       -> "[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'étais intéressé à trouver un remplaçant pour le "n" et "[" et j'ai trouvé ceci:

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

Ce que je ressens dans l'esprit d'utiliser des 1 et des 0, mais qui viole l'un des aspects les plus élégants du code original qui est l'apparence de n'avoir rien à voir avec les chaînes du tout. Quelqu'un d'autre a-t-il une idée de la façon de générer un "v" conforme au code obscurci d'origine?

Voici quelques informations supplémentaires qui ont été trouvées après que de nombreux programmeurs JavaScript talentueux se soient penchés plus en profondeur sur cette

Firefox renvoie "Je t'ai seul" à cause de cette ligne:

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

[1^11<<1] supprime un caractère spécifique de ceci:

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

Qui évalue à ceci:

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

On dirait que nous pourrions avoir notre "V" !!!

Chrome renvoie "Je t'aime", car le même code renvoie ceci:

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

Avant que la question ne soit close pour un lien douteux avec "un vrai problème de programmation", j'ai pensé ajouter une solution résumée qui s'appuie sur celles de @ Supr , @ Cory et @ alpha123 , voici:

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])

Compte tenu de la complexité du code et du message qu'il produit, c'est presque comme si le moteur JavaScript disait à quel point vous le faites sentir :)

Jason Sperske
la source
9
Il dit "amour" dans la console Chrome. i.imgur.com/rVyKMoP.png
bfavaretto
2
Que faire si vous supprimez les lettres non du function test() { [native code] }, alors vous pouvez la normaliser et extraire la lettre que vous voulez
Jason Sperske
4
Baser le code sur une sortie de chaîne non définie par les normes afin d'imprimer un message en utilisant du code obscurci ... J'appelle cela une manière trop localisée.
2
@Ian, c'est vrai. Si les gens de ma vie que j'aime vraiment se soucient de moi, ils utiliseraient Chrome :)
Jason Sperske
4
La meilleure partie à ce sujet est l'avertissement que mon éditeur de texte donne: "Utilisation confuse de"! ""
Jake Johnson

Réponses:

83

Tout d'abord, je voudrais remercier Jason et tous les contributeurs d'avoir joué avec cet extrait amusant. J'ai écrit ce morceau de code juste pour m'amuser afin de l'envoyer à ma femme le 14 février :) N'ayant que Chrome installé sur l'ordinateur portable, je n'avais aucune option pour vérifier son fonctionnement dans Firefox et IE. De plus, je ne m'attendais pas vraiment à ce que la toString()représentation des méthodes intégrées puisse avoir un aspect différent dans d'autres navigateurs.

Passons maintenant au vrai problème , examinons précisément le code. Oui, "v"c'était le vrai "problème" ici. Je n'ai trouvé aucun autre moyen d'obtenir cette lettre à l'exception de la [native code]chaîne d' analyse , qui peut être extraite de n'importe quelle méthode intégrée. Puisque je me suis limité à n'avoir aucune chaîne et aucun nombre sauf 1utilisé, j'ai 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 et des représentations de chaîne existants, soit dès le début nous avons eu NaN, null, undefined, Infinity, true, falseet "[object Object]". Certains d'entre eux peuvent être facilement convertis en chaînes, par exemple 1/!1+[]donne "Infinity".

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

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

Comme cela a déjà été discuté, 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 ce dernier accordez une attention particulière à l'espace avant le functionmot-clé)

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

Afin de faire la même sortie dans tous les navigateurs, j'ai utilisé une approche différente de celle illustrée 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 pour cela. Je crois honnêtement que vous comprendrez facilement comment cela fonctionne ... et certains peuvent même surprendre leur bien-aimé de manière cross-browser;)

PS Encore un autre Obfuscator

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

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

Vision
la source
4
"constructeur" ... wow c'est incroyable et vous avez gardé le rectangle parfait avec des sauts de ligne valides. Vous êtes bon
Jason Sperske
1
J'ai créé un Obfuscator qui crée une chaîne en accord avec vos règles de style: jsfiddle.net/w9rFF/8
Jason Sperske
@JasonSperske C'était une belle astuce! Bon travail! J'essaierai d'y contribuer.
VisioN
26

Pourquoi le native codebit de la question n'est-il pas utilisé? Celui-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]

Modifiez pour prendre en charge IE et faites-le 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)
]
Supr
la source
C'est intéressant. À l'origine, il a été écarté que le placement des mots «code natif» était imprévisible entre Firefox et Chrome. Cela résout cela mais ne fonctionne pas dans IE10 (où il renvoie "i"). Je me demande encore si cette option pourrait offrir de nouvelles idées
Jason Sperske
L'idée est de choisir simplement les deux net vet choisir seulement selon la valeur la plus importante: str[23]>str[27]?str[23]:str[27]. En d'autres termes, l'opérateur tertiaire est l'astuce. Pourrait être étendu pour prendre en charge IE également:([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1+(1^(11+1+1)<<1)]
Supr
1
Votre réponse était la première (avant le créateur du code original), mais j'ai senti que sa réponse pouvait très logiquement être considérée comme la bonne. Encore un excellent travail (et 13 votes
positifs
1
Petit pinaillage: un opérateur tertiaire est le troisième opérateur le plus important, après le primaire et le secondaire. Un opérateur qui prend trois opérandes est ternaire.
Eric Lippert
1
@EricLippert, gah, je l'ai même cherché sur Google pour m'assurer que j'utilisais le bon terme, mais je me suis quand même retrouvé avec le mauvais! Merci, corrigé.
Supr
8

C'est à peu près aussi proche que possible, malheureusement, cela viole la convention de l'obfuscation d'origine en appelant unescape():

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

Abattre:

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

Autres idées:

  1. En quelque sorte arriver à unescape("\x76")
  2. En quelque sorte convertir 118sans appelerString.fromCharCode()
  3. Récupérer 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 des pièces par plus de 1s, etc.

Cᴏʀʏ
la source
J'aime aussi celui-ci. Je suis un peu déchiré dans la sélection d'une réponse "correcte", car la vôtre et celle de @ alpha123 semblent extrêmement obscurcies et cachent intelligemment l'intention originale.
Jason Sperske
Et le support IE10 scelle l'accord (avec des excuses sincères @ alpha123 pour l'excellente réponse)
Jason Sperske
Vous pouvez remplacer cela '%'par la (/%/+[[]+1/!1])[1]suppression des guillemets. J'ai également ajouté l' l=unescape;utilisation de minuscules Lpour masquer la référence unescape. Cela a été amusant :)
Jason Sperske
@JasonSperske: Encore plus court:(/%/+[])[1]
Cᴏʀʏ
1
Ou vous pouvez nommer votre variable $1;
Cᴏʀʏ
4

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. Donc, en raison de l'espace blanc supplémentaire de Firefox, ce n'est pas tout à fait suffisant pour atteindre le «v», et c'est plutôt «n».

Et c'est pourquoi vous ne devriez pas vous fier au comportement de Function # toString. ;)

EDIT: Enfin, j'ai trouvé une version cross-browser raisonnablement obscurcie:

[[]+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 dans parseInt (apparemment, Firefox analyse les nombres commençant par 0 comme octal, alors que Chrome ne le fait pas) pour ajouter 4 dans le cas de Firefox, obtenant ainsi 'v' de 'native' dans les deux cas (je ne trouve pas d'autre 'v ': P).
Le parseInt semble un peu déplacé, mais c'est le mieux que je puisse faire pour le moment.

Peter C
la source
1
La question estDoes anyone else have an idea of how to generate a "v" that is in keeping with the original obfuscated code?
Ian
Merci. Maintenant, j'essaie de trouver un moyen multi-navigateurs pour le faire ... 'V' est une lettre étonnamment rare ....
Peter C
@Ian - eh bien alors probablement, [(1 ^ 11 << 1) + 1 + 1 + 1 + 1] le ferait?
enhzflep
@JanDvorak - Je n'ai pas de FF pour le moment. À quoi évalue-t-il? Si je peux être assez présomptueux pour demander, c'est.
enhzflep
@enhzflep désolé, je voulais dire "cela ne fonctionnerait pas dans Chrome, d'autre part"
John Dvorak
4

Pour le cas d'utilisation général , si la casse des caractères n'est pas un gros problème, je pourrais être enclin à tricher un peu.

Créez la fonction "c" qui transforme un nombre 0 .. 25 en 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, pré-mettez en cache les lettres, 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].

Alternativement, 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 ce problème spécifique , peut-être simplement:

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

Cela donne av dans Chrome:

Object.getOwnPropertyNames(Object)[17][3];

Et cela le fait dans Firefox:

Object.getOwnPropertyNames(Object)[9][3]

Ils le retirent tous les deux Object.prototype.preventExtensions(), vous pourriez donc probablement trouver un moyen multi-navigateurs pour référencer cette méthode. (C'est le seul nom de 17 caractères dans Object.Prototype pour les débutants.)

N'hésitez pas à créer une version plus obscure de ceci et prenez tout le mérite pour vous-même, je n'ai plus de temps;)

Nathan Friedly
la source
2

Dans Chrome, l'expression ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])s'évalue à "function test() { [native code] }", l' [1^11<<1]évalue à 23 (les opérateurs au niveau du bit entraînent la troncature de la variable à 32 bits)

enhzflep
la source
La question estDoes anyone else have an idea of how to generate a "v" that is in keeping with the original obfuscated code?
Ian