Jakie są wbudowane ciągi JavaScript?

147

pytanie to jest trudne do podsumowania w tytule pytania

AKTUALIZACJA Stworzyłem JSFiddle, który tworzy zaciemniony ciąg znaków z twoich danych wejściowych w oparciu o litery wyodrębnione z tego pytania: Możesz uzyskać do niego dostęp tutaj , czy może istota byłaby łatwiejsza?

Niedawno natknąłem się na zabawny kawałek zaciemnionego JavaScript w tym profilu, który wygląda tak:

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]

Przepraszam, że psuję niespodziankę, ale po ocenie zwraca to:

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

Sposób, w jaki to działa po rozbiciu, polega na wygenerowaniu serii wiadomości i wyciągnięciu z nich liter w ten sposób (na przykładzie „I”):

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

Inne generowane ciągi to:

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

Byłem zainteresowany znalezieniem zamiennika dla „n” i „[” i wymyśliłem to:

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

Który czuję w duchu używania jedynek i zer, ale narusza jeden z bardziej eleganckich aspektów oryginalnego kodu, którym jest pozory, że nie ma nic wspólnego ze stringami. Czy ktoś jeszcze ma pomysł, jak wygenerować „v”, które jest zgodne z oryginalnym zaciemnionym kodem?

Oto kilka dodatkowych informacji, które znaleziono po tym, jak wielu utalentowanych programistów JavaScript przyjrzało się temu dokładniej

Firefox zwraca „I lone you” Z powodu tego wiersza:

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

[1^11<<1] wycina z tego określony znak:

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

Który ocenia to:

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

Co wygląda na to, że możemy mieć nasze „V” !!!

Chrome zwraca „Kocham cię”, ponieważ ten sam kod zwraca to:

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

Zanim pytanie zostanie zamknięte z powodu wątpliwego połączenia z „prawdziwym problemem programistycznym”, pomyślałem, że dodam podsumowane rozwiązanie, które opiera się na @ Supr's , @ Cory's i @ alpha123's , oto:

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

Biorąc pod uwagę złożoność kodu i generowanego przez niego komunikatu, jest to prawie tak, jakby silnik JavaScript mówił, jak wyjątkowo czujesz się w nim :)

Jason Sperske
źródło
9
W konsoli Chrome jest napisane „miłość”. i.imgur.com/rVyKMoP.png
bfavaretto
2
A co jeśli function test() { [native code] }
usuniesz nieliterów
4
Oparcie kodu na wyjściu w postaci łańcucha znaków niezgodnych ze standardami w celu wydrukowania wiadomości przy użyciu zaciemnionego kodu ... Wywołuję to w sposób zbyt lokalny.
2
@Ian, prawda. Gdyby ludzie w moim życiu, których kocham, naprawdę się o mnie troszczyli,
używaliby
4
Najlepsze w tym wszystkim jest ostrzeżenie, które daje mój edytor tekstu: „Mylące użycie znaku '!'”
Jake Johnson,

Odpowiedzi:

83

Przede wszystkim chciałbym podziękować Jasonowi i wszystkim współpracownikom za zabawę z tym zabawnym fragmentem. Napisałem ten kod dla zabawy , aby 14 lutego wysłać go żonie :) Mając na laptopie tylko Chrome'a ​​nie miałem możliwości sprawdzenia jak to działa w Firefoksie i IE. Co więcej, nie spodziewałem się, że toString()reprezentacja metod wbudowanych może wyglądać inaczej w innych przeglądarkach.

Teraz przeniósł się do prawdziwego problemu , niech dokładnie przyjrzeć się kod. Tak, "v"był to prawdziwy „problem”. Nie znalazłem innych sposobów na uzyskanie tej litery, z wyjątkiem parsowania [native code]ciągu, który można pobrać z dowolnej wbudowanej metody. Ponieważ ograniczyłem się do nie posiadania żadnych ciągów ani liczb poza 1używanymi, musiałem wykorzystać metodę, która ma tylko dostępne znaki w nazwie.

Dostępne znaki mogą być uzyskane z istniejących słów kluczowych i reprezentacji ciąg, czyli od samego początku mieliśmy NaN, null, undefined, Infinity, true, false, i "[object Object]". Część z nich można łatwo zamienić na stringi, np . 1/!1+[]Daje "Infinity".

Przeanalizowałem różne wbudowane metody dla tablic [], obiektów {}, wyrażeń regularnych /(?:)/, liczb 1.1, łańcuchów "1"i odkryłem jedną piękną metodę RegExpobiektu o nazwie test(). Jego nazwa może być montowane ze wszystkich dostępnych znaków, na przykład "t"i "e"od truei "s"od false. Utworzyłem ciąg "test"i odniosłem się do tej metody, używając notacji w nawiasach kwadratowych dla literału wyrażenia regularnego /-/, poprawnie zidentyfikowanego w tym wierszu:

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

Jak już wspomniano, ten fragment kodu jest oceniany w Chrome jako:

function test() { [native code] }

w przeglądarce Firefox jako:

function test() {
    [native code]
}

aw IE jako:

 function test() {     [native code] }  

(w tym drugim przypadku należy zwrócić szczególną uwagę na miejsce przed functionsłowem kluczowym)

Czyli jak widać, mój kod pobierał 24. znak z przedstawionego ciągu, który w Chrome był "v"(tak jak planowano), ale niestety w Firefoksie i IE - "n"i "["odpowiednio.

Aby uzyskać taki sam wynik we wszystkich przeglądarkach, zastosowałem inne podejście niż pokazano w innych odpowiedziach. Teraz zmodyfikowana wersja wygląda tak:

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]

Aby jednak zaintrygować czytelników, nie podam na to rozwiązania. Szczerze wierzę, że łatwo zrozumiesz, jak to działa ... a niektórzy potrafią nawet zaskoczyć ukochaną w cross-browser sposób;)

PS Jeszcze inny zaciemniacz

Zainspirowany pomysłem Jasona, aby stworzyć uniwersalne narzędzie zaciemniające, napisałem jeszcze jedno. Możesz go znaleźć na JSBin: http://jsbin.com/amecoq/2 . Może zaciemniać dowolny tekst zawierający cyfry [0-9], małe litery łacińskie [a-z]i spacje. Długość łańcucha jest ograniczona głównie przez pamięć RAM (przynajmniej treść mojej odpowiedzi została skutecznie zaciemniona). Dane wyjściowe są obsługiwane przez przeglądarki Chrome, Firefox i IE.

Wskazówka: narzędzie korzysta z innego podejścia do zaciemniania niż zostało to przedstawione powyżej.

Wizja
źródło
4
„konstruktor” ... wow to niesamowite i zachowałeś idealny prostokąt z prawidłowymi znakami końca linii. Jesteś dobry
Jason Sperske
1
Stworzyłem Obfuscator, który tworzy string zgodnie z Twoimi zasadami stylu: jsfiddle.net/w9rFF/8
Jason Sperske Kwietnia
@JasonSperske To była niezła sztuczka! Świetna robota! Spróbuję się do tego przyczynić.
VisioN
26

Dlaczego nie native codeużywa się fragmentu z pytania? Ten daje 'v'w obu Chrome i 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]

Edytuj, aby obsługiwać IE i zrób to bez operatora trójargumentowego: ten działa w Chrome, IE i FF. Buduje tablicę i używa ==do określenia przeglądarki.

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

Czytelny:

[
    //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
źródło
To jest interesujące. Pierwotnie odrzucono, że umieszczenie słów „kod natywny” między przeglądarką Firefox a Chrome jest nieprzewidywalne. To rozwiązuje problem, ale nie działa w IE10 (gdzie zwraca „i”). Nadal zastanawiam się, czy ta opcja może zaoferować jakieś świeże pomysły
Jason Sperske,
Chodzi o to, aby po prostu wybrać zarówno na vi po prostu wybrać cokolwiek jest największy: str[23]>str[27]?str[23]:str[27]. Innymi słowy, podstępem jest operator trzeciorzędny. Może zostać rozszerzony, aby obsługiwał również IE:([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1+(1^(11+1+1)<<1)]
Supr
1
Twoja odpowiedź była pierwsza (przed twórcą oryginalnego kodu), ale czułem, że jego odpowiedź można logicznie uznać za właściwą. Wciąż świetna robota (i zasłużona 13 pozytywnych głosów)
Jason Sperske,
1
Drobny dzióbek: operator trzeciorzędny jest trzecim najważniejszym operatorem, po pierwszym i drugim. Operator, który przyjmuje trzy operandy, jest trójskładnikowy.
Eric Lippert
1
@EricLippert, gah, nawet wyszukałem go w Google, aby upewnić się, że używam właściwego terminu, ale nadal trafiłem na niewłaściwy! Dzięki, poprawione.
Supr
8

To jest tak blisko, jak tylko mogłem, niestety narusza konwencję oryginalnego zaciemniania, dzwoniąc pod numer unescape():

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

Zburzyć:

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

Inne pomysły:

  1. Jakoś się dostać unescape("\x76")
  2. Jakoś przekonwertuj 118bez dzwonieniaString.fromCharCode()
  3. Pobierz tekst z wyjątku ze słowem „Nieprawidłowy”

Aktualizacje:

Zacząłem grać w code-golfa i skracałem go, wymieniając części na więcej 1itd.

Cᴏʀʏ
źródło
Ten też mi się podoba. Jestem trochę rozdarty, jeśli chodzi o wybraną „poprawną” odpowiedź, ponieważ zarówno Twój, jak i @ alpha123 wyglądają niezwykle zaciemnione i sprytnie ukrywają pierwotny zamiar.
Jason Sperske
A obsługa IE10 przypieczętowuje umowę (ze szczerymi przeprosinami @ alpha123 za doskonałą odpowiedź)
Jason Sperske
Można wymienić, że '%'przy (/%/+[[]+1/!1])[1]usuwaniu żadnych cytatów. Dodałem również l=unescape;użycie małych liter, Laby ukryć odniesienie do unescape. Było fajnie :)
Jason Sperske
@JasonSperske: Jeszcze krócej:(/%/+[])[1]
Cᴏʀʏ
1
Możesz też nazwać swoją zmienną $1;
Cᴏʀʏ
4

Oto część, która generuje n / v:

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

W przeglądarce Firefox ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])ocenia jako

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

podczas gdy w Chrome jest

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

1^11<<1 równa się 23. Tak więc, ze względu na dodatkowe białe znaki Firefoksa, to nie wystarczy, aby dostać się do „v”, a zamiast tego jest „n”.

I dlatego nie powinieneś polegać na zachowaniu Function # toString. ;)

EDYCJA: Wreszcie znalazłem rozsądnie zaciemnioną wersję dla różnych przeglądarek:

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

Spowoduje to zastąpienie sekcji n / v przez:

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

która wykorzystuje różnice w parseInt (najwyraźniej Firefox analizuje liczby zaczynające się od 0 jako ósemkowe, podczas gdy Chrome nie), aby dodać 4 w przypadku Firefoksa, uzyskując w ten sposób „v” z „natywnego” w obu przypadkach (nie mogę znaleźć innego „v ': P).
ParseInt wygląda trochę nie na miejscu, ale to najlepsze, co mogę teraz zrobić.

Peter C.
źródło
1
Pytanie brzmiDoes anyone else have an idea of how to generate a "v" that is in keeping with the original obfuscated code?
Ian
Dzięki. Teraz próbuję wymyślić sposób, w jaki można to zrobić w różnych przeglądarkach ... „V” to zaskakująco rzadki list ....
Peter C
@Ian - cóż, więc prawdopodobnie [(1 ^ 11 << 1) + 1 + 1 + 1 + 1] zrobiłby to?
enhzflep
@JanDvorak - w tej chwili nie mam FF. Do czego to się odnosi? To znaczy, jeśli mogę być tak arogancki, żeby zapytać.
enhzflep
@enhzflep przepraszam, miałem na myśli „to nie zadziała w Chrome, z drugiej strony”
John Dvorak
4

W przypadku ogólnego zastosowania, jeśli wielkość liter nie jest dużym problemem, mogę być skłonny do trochę oszukiwania.

Utwórz funkcję „c”, która zamienia liczbę 0 ... 25 na znak.

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

Ze względu na wydajność, jeśli chcesz, wstępnie zapisz litery w pamięci podręcznej.

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

W konsoli Chrome wynikowa tablica wygląda następująco:

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

Więc ... Twoje v może być l[10+10+1].

Alternatywnie, ogólne rozwiązanie takie jak to:

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

Lub w przypadku tego konkretnego problemu może po prostu:

(function(){v=1}+[])[10+(1<<1)]; // "v"
svidgen
źródło
3

To daje av w Chrome:

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

I robi to w Firefoksie:

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

Obaj wyciągają to z Object.prototype.preventExtensions(), więc prawdopodobnie możesz znaleźć sposób na odwołanie się do tej metody w różnych przeglądarkach. (To jedyna 17-znakowa nazwa w Object.Prototype na początek.)

Zapraszam do zbudowania bardziej zaciemnionej wersji tego i weź wszystko za siebie, nie mam czasu;)

Nathan Friedly
źródło
2

W chrome, wyrażenie ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])szacuje się na "function test() { [native code] }", [1^11<<1]zwraca 23 (operatory bitowe powodują obcięcie zmiennej do 32 bitów)

enhzflep
źródło
Pytanie brzmiDoes anyone else have an idea of how to generate a "v" that is in keeping with the original obfuscated code?
Ian