Was sind die in JavaScript integrierten Zeichenfolgen?

147

Diese Frage ist schwer in einem Fragentitel zusammenzufassen

UPDATE Ich habe eine JSFiddle , die eine verschleierte Zeichenfolge aus Ihrer Eingabe baut auf der Grundlage der Briefe aus dieser Frage extrahiert: Sie können darauf zugreifen hier , oder wäre ein Kern einfacher sein?

Ich bin kürzlich auf ein lustiges Stück verschleiertes JavaScript in diesem Profil gestoßen , das so aussieht:

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]

Es tut mir leid, die Überraschung zu ruinieren, aber wenn dies ausgewertet wird, wird Folgendes zurückgegeben:

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

Die Art und Weise, wie dies funktioniert, wenn es ausgebrochen ist, besteht darin, eine Reihe von Nachrichten zu generieren und Buchstaben wie folgt daraus herauszuziehen (am Beispiel des "Ich"):

[]+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"

Andere Zeichenfolgen, die generiert werden, sind:

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

Ich war daran interessiert, einen Ersatz für "n" und "[" zu finden, und fand Folgendes:

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

Was ich im Geiste der Verwendung von Einsen und Nullen empfinde, aber gegen einen der eleganteren Aspekte des ursprünglichen Codes verstößt, nämlich den Anschein, überhaupt nichts mit Zeichenfolgen zu tun zu haben. Hat jemand eine Idee, wie ein "v" generiert werden kann, das dem ursprünglichen verschleierten Code entspricht?

Hier sind einige zusätzliche Informationen, die gefunden wurden, nachdem viele talentierte JavaScript-Programmierer dies genauer untersucht hatten

Firefox gibt "Ich habe dich allein" zurück. Wegen dieser Zeile:

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

[1^11<<1] schneidet einen bestimmten Charakter daraus ab:

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

Was dazu führt:

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

Was so aussieht, als hätten wir unser "V" !!!

Chrome gibt "Ich liebe dich" zurück, da derselbe Code dies zurückgibt:

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

Bevor die Frage wegen fragwürdiger Verbindung mit "einem echten Programmierproblem" geschlossen wird, dachte ich, ich würde eine zusammengefasste Lösung hinzufügen, die auf @ Supr's , @ Cory's und @ alpha123's aufbaut , sehen:

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

Angesichts der Komplexität des Codes und der von ihm erzeugten Nachricht ist es fast so, als würde die JavaScript-Engine sagen, wie besonders Sie sich fühlen :)

Jason Sperske
quelle
9
In der Chrome-Konsole steht "Liebe". i.imgur.com/rVyKMoP.png
bfavaretto
2
Was ist, wenn Sie keine Buchstaben aus dem function test() { [native code] }
entfernen
4
Code basiert auf einer nicht standarddefinierten Zeichenfolgenausgabe, um eine Nachricht mit verschleiertem Code zu drucken ... Ich nenne dies einen Weg zu lokalisiert.
2
@ Ian, stimmt. Wenn sich die Menschen in meinem Leben, die ich liebe, wirklich um mich
kümmern
4
Das Beste daran ist die Warnung, die mein Texteditor gibt: "Verwirrende Verwendung von '!'"
Jake Johnson

Antworten:

83

Zunächst möchte ich Jason und allen Mitwirkenden dafür danken, dass sie mit diesem lustigen Ausschnitt gespielt haben. Ich habe diesen Code nur zum Spaß geschrieben, um ihn am 14. Februar an meine Frau zu senden :) Da nur Chrome auf dem Laptop installiert war, hatte ich keine Möglichkeit zu überprüfen, wie er in Firefox und IE funktioniert. Außerdem habe ich nicht wirklich erwartet, dass die toString()Darstellung von integrierten Methoden in anderen Browsern anders aussehen könnte.

Kommen wir nun zum eigentlichen Problem und schauen wir uns den Code genau an. Ja, "v"war das eigentliche "Problem" hier. Ich habe keine andere Möglichkeit gefunden, diesen Buchstaben zu erhalten [native code], als die Zeichenfolge zu analysieren , die von jeder integrierten Methode übernommen werden kann. Da habe ich mich darauf beschränkt, keine Strings und keine Zahlen außer zu haben1 verwendet zu haben, musste ich eine Methode ausnutzen, deren Name nur Zeichen enthält.

Verfügbare Zeichen können aus vorhandenen Keywords und String - Darstellungen, dh vom Start erhalten werden , die wir hatten NaN, null, undefined, Infinity, true, false, und "[object Object]". Einige von ihnen können leicht in Zeichenfolgen umgewandelt werden, z . B. 1/!1+[]gibt "Infinity".

Ich habe verschiedene eingebaute Methoden für Arrays [], Objekte {}, reguläre Ausdrücke /(?:)/, Zahlen 1.1, Zeichenfolgen analysiert "1"und eine schöne RegExpObjektmethode namens entdeckt test(). Sein Name kann aus allen verfügbaren Zeichen zusammengestellt werden, z. B. "t"und "e"von trueund "s"von false. Ich habe eine Zeichenfolge erstellt "test"und diese Methode in eckigen Klammern für das Regex-Literal behandelt /-/, das in dieser Zeile korrekt angegeben ist:

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

Wie bereits erwähnt, wird dieser Code in Chrome wie folgt ausgewertet:

function test() { [native code] }

in Firefox als:

function test() {
    [native code]
}

und im IE als:

 function test() {     [native code] }  

(in letzterem achten Sie besonders auf das Leerzeichen vor dem functionSchlüsselwort)

Wie Sie deutlich sehen, erhielt mein Code das 24. Zeichen aus der dargestellten Zeichenfolge, die in Chrome "v"(wie geplant) vorhanden war, aber leider in Firefox und IE - "n"und"[" sind.

Um in allen Browsern die gleiche Ausgabe zu erzielen, habe ich einen anderen Ansatz gewählt als in den anderen Antworten dargestellt. Jetzt sieht die modifizierte Version so aus:

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]

Um die Leser zu faszinieren, werde ich jedoch keine Lösung dafür anbieten. Ich glaube ehrlich, dass Sie leicht verstehen werden, wie es funktioniert ... und einige können sogar ihre Geliebte browserübergreifend überraschen;)

PS Noch ein Obfuscator

Inspiriert von Jasons Idee, ein universelles Verschleierungswerkzeug zu schaffen, habe ich noch eines geschrieben. Sie finden es unter JSBin: http://jsbin.com/amecoq/2 . Es kann jeden Text verschleiern, der Zahlen [0-9], kleine lateinische Buchstaben [a-z]und Leerzeichen enthält. Die Stringlänge ist meistens mit Ihrem RAM begrenzt (zumindest der Text meiner Antwort wurde erfolgreich verschleiert). Die Ausgabe wird von Chrome, Firefox und IE unterstützt.

Hinweis: Das Tool verwendet einen anderen Verschleierungsansatz als oben dargestellt.

Vision
quelle
4
"Konstruktor" ... wow, das ist erstaunlich und Sie haben das perfekte Rechteck mit gültigen Zeilenumbrüchen beibehalten. Sie sind gut
Jason Sperske
1
Ich habe einen Obfuscator erstellt, der eine Zeichenfolge gemäß
Jason Sperske
@ JasonSperske Das war ein schöner Trick! Gute Arbeit! Ich werde versuchen, dazu beizutragen.
VisioN
26

Warum wird das native codeBit aus der Frage nicht verwendet? Dieser gibt eine 'v'in Chrome und 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]

Bearbeiten Sie, um IE zu unterstützen, und verzichten Sie auf den ternären Operator: Dieser funktioniert in Chrome, IE und FF. Erstellt ein Array und ==bestimmt den Browser.

[([]+/-/[(!!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)]

Lesbar:

[
    //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
quelle
Das ist interessant. Ursprünglich wurde abgewiesen, dass die Platzierung der Wörter "nativer Code" zwischen Firefox und Chrome nicht vorhersehbar war. Dies löst das, funktioniert aber nicht in IE10 (wo es "i" zurückgibt). Trotzdem frage ich mich, ob diese Option einige frische Ideen bieten könnte
Jason Sperske
Die Idee ist, wählen Sie einfach beides nund vund nur wählen je nachdem , was am größten ist : str[23]>str[27]?str[23]:str[27]. Mit anderen Worten, der Tertiäroperator ist der Trick. Könnte erweitert werden, um auch IE zu unterstützen:([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1+(1^(11+1+1)<<1)]
Supr
1
Ihre Antwort war die erste (vor dem Ersteller des ursprünglichen Codes), aber ich hatte das Gefühl, dass seine Antwort logischerweise als die richtige angesehen werden kann. Immer noch großartige Arbeit (und gut verdiente 13 Stimmen)
Jason Sperske
1
Minor nitpick: Ein tertiärer Operator ist nach dem primären und sekundären der drittwichtigste Operator. Ein Operator, der drei Operanden akzeptiert, ist ternär.
Eric Lippert
1
@EricLippert, gah, ich habe es sogar gegoogelt, um sicherzugehen, dass ich den richtigen Begriff verwendet habe, aber ich habe immer noch den falschen gefunden! Danke, korrigiert.
Supr
8

Dies ist ungefähr so ​​nah wie möglich, leider verstößt es gegen die Konvention der ursprünglichen Verschleierung, indem es anruft unescape():

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

Niederreissen:

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

Andere Ideen:

  1. Irgendwie zu bekommen unescape("\x76")
  2. Irgendwie konvertieren, 118ohne anzurufenString.fromCharCode()
  3. Holen Sie sich den Text aus einer Ausnahme mit dem Wort "Ungültig"

Aktualisierung:

Ich habe angefangen, Code Golf zu spielen und habe es kürzer gemacht, Teile durch mehr 1s usw. ersetzt.

Cᴏʀᴏʀ
quelle
Ich mag diesen auch. Ich bin ein bisschen hin und her gerissen in der Auswahl einer "richtigen" Antwort, da sowohl Ihre als auch die von @ alpha123 extrem verschleiert aussehen und die ursprüngliche Absicht geschickt verbergen.
Jason Sperske
Und IE10-Unterstützung besiegelt den Deal (mit aufrichtiger Entschuldigung @ alpha123 für die hervorragende Antwort)
Jason Sperske
Sie könnten , dass ersetzen '%'mit (/%/+[[]+1/!1])[1]keinen Anführungszeichen zu entfernen. Ich habe auch die l=unescape;Verwendung von Kleinbuchstaben hinzugefügt L, um den Verweis auf auszublenden unescape. Das hat Spaß gemacht :)
Jason Sperske
@ JasonSperske: Noch kürzer:(/%/+[])[1]
12.
1
Oder Sie könnten Ihre Variable benennen $1;
12.
4

Hier ist der Teil, der die n / v generiert:

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

In Firefox wird ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])ausgewertet

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

während in Chrome ist es

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

1^11<<1 gleich 23. Aufgrund des zusätzlichen Leerzeichens von Firefox reicht dies nicht aus, um zum 'v' zu gelangen, sondern ist stattdessen 'n'.

Aus diesem Grund sollten Sie sich nicht auf das Verhalten von Function # toString verlassen. ;)

EDIT: Endlich habe ich eine einigermaßen verschleierte Cross-Browser-Version gefunden:

[[]+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]

Dies ersetzt den n / v-Abschnitt durch:

([]+/-/[(!!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)]

Dies nutzt Unterschiede in parseInt aus (anscheinend analysiert Firefox Zahlen, die mit 0 als Oktal beginnen, während Chrome dies nicht tut), um in Firefox 'Fall 4 hinzuzufügen, wodurch in beiden Fällen' v 'von' native 'erhalten wird (ich kann kein anderes' v finden ': P).
Das parseInt sieht ein wenig fehl am Platz aus, aber das ist das Beste, was ich jetzt tun kann.

Peter C.
quelle
1
Die Frage istDoes anyone else have an idea of how to generate a "v" that is in keeping with the original obfuscated code?
Ian
Vielen Dank. Jetzt versuche ich, einen browserübergreifenden Weg zu finden, um dies zu tun ... 'V' ist ein überraschend ungewöhnlicher Buchstabe ...
Peter C
@ Ian - na dann würde vermutlich [(1 ^ 11 << 1) + 1 + 1 + 1 + 1] es tun?
Enhzflep
@ JanDvorak - Ich habe momentan kein FF. Was bewertet es? Wenn ich so anmaßend sein darf, dass ich frage, dann.
Enhzflep
@ Enhzflep Entschuldigung, ich meinte "das würde in Chrome andererseits nicht funktionieren"
John Dvorak
4

Für den General Anwendungsfall neige ich möglicherweise dazu, ein wenig zu schummeln, wenn die Groß- und Kleinschreibung von Charakteren kein großes Problem darstellt.

Erstellen Sie die Funktion "c", die aus einer Zahl 0 .. 25 ein Zeichen macht.

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]}}}};

Speichern Sie die Buchstaben aus Leistungsgründen vorab, wenn Sie möchten.

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

In der Chrome-Konsole sieht das resultierende Array folgendermaßen aus:

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

Also ... dein v könnte seinl[10+10+1] .

Alternativ eine allgemeine Lösung wie diese:

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

Oder für dieses spezielle Problem vielleicht nur:

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

Dies gibt av in Chrome:

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

Und das macht es in Firefox:

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

Sie ziehen es beide heraus Object.prototype.preventExtensions() , sodass Sie wahrscheinlich einen browserübergreifenden Weg finden könnten, um auf diese Methode zu verweisen. (Es ist der einzige 17-stellige Name in Object.Prototype für den Anfang.)

Fühlen Sie sich frei, eine verschleierte Version davon zu erstellen und alle Ehre für sich selbst zu nehmen, ich habe keine Zeit mehr;)

Nathan Friedly
quelle
2

In Chrom, die Expression ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])zu auswertet "function test() { [native code] }", die [1^11<<1]auswertet bis 23 (Bitoperatoren Ursache der Variablen auf 32 Bits abgeschnitten werden)

Enhzflep
quelle
Die Frage istDoes anyone else have an idea of how to generate a "v" that is in keeping with the original obfuscated code?
Ian