Что такое встроенные строки JavaScript?


147

этот вопрос сложно обобщить в названии вопроса

ОБНОВЛЕНИЕ Я создал JSFiddle, который строит запутанную строку из вашего ввода на основе букв, извлеченных из этого вопроса: вы можете получить к нему доступ здесь , или суть будет проще?

Недавно я наткнулся на забавный фрагмент JavaScript в этом профиле, который выглядит следующим образом:

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]

Извините, что испортил сюрприз, но когда это оценивается, возвращается следующее:

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

Способ, которым это работает в случае разрыва, состоит в том, чтобы генерировать серию сообщений и извлекать из них буквы, например, так (используя «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"

Другие строки, которые генерируются включают в себя:

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

Я был заинтересован в поиске замены для "n" и "[" и придумал это:

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

Что я чувствую в духе использования 1 и 0, но нарушает один из более элегантных аспектов исходного кода, который заключается в том, что он не имеет ничего общего со строками. Кто-нибудь еще имеет представление о том, как сгенерировать "v" в соответствии с оригинальным запутанным кодом?

Вот некоторая дополнительная информация, которая была найдена после того, как многие талантливые программисты JavaScript более глубоко взглянули на это

Firefox возвращает «я одинок» из-за этой строки:

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

[1^11<<1] обрезает определенный символ из этого:

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

Который оценивает это:

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

Похоже, у нас может быть "V" !!!

Chrome возвращает «Я люблю тебя», потому что тот же код возвращает это:

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

До того, как вопрос был закрыт для сомнительной связи с «реальной проблемой программирования», я подумал, что хотел бы добавить обобщенное решение, основанное на @ Supr , @ Cory's и @ alpha123 , вот:

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

Учитывая сложность кода и создаваемого им сообщения, почти как движок JavaScript говорит о том, насколько особенным вы его чувствуете :)


9
Это говорит "любовь" в консоли Chrome. i.imgur.com/rVyKMoP.png
bfavaretto

2
Что если вы удалите не те буквы function test() { [native code] }, которые у вас есть, то вы можете нормализовать их и извлечь
нужную

4
Основывая код на нестандартном выводе строки, чтобы напечатать сообщение, используя запутанный код ... Я называю это слишком локализованным способом .

2
@ Ян, правда. Если бы люди в моей жизни, которых я люблю, действительно заботились обо мне, они бы использовали Chrome :)
Джейсон Сперске

4
Лучшая часть об этом - предупреждение, которое мой текстовый редактор дает: «Запутанное использование«! »
Джейк Джонсон

Ответы:


83

Прежде всего, я хотел бы поблагодарить Джейсона и всех авторов за игру с этим забавным фрагментом. Я написал этот фрагмент кода просто для развлечения , чтобы отправить его своей жене 14 февраля :). На ноутбуке был установлен только Chrome, и у меня не было возможности проверить, как он работает в Firefox и IE. Более того, я не ожидал, что toString()представление встроенных методов может выглядеть иначе в других браузерах.

Теперь, переходя к реальной проблеме , давайте точно посмотрим на код. Да, "v"была настоящая «проблема» здесь. Я не нашел других способов получить это письмо, кроме парсинга [native code]строки, который можно взять из любого встроенного метода. Поскольку я ограничивал себя тем, что в нем не было ни строк, ни чисел, кроме 1используемых, мне нужно было использовать какой-то метод, в имени которого есть только доступные символы.

Доступные символы могут быть получены из существующих ключевых слов и строк представлений, то есть с самого начала мы имели NaN, null, undefined, Infinity, true, false, и "[object Object]". Некоторые из них могут быть легко преобразованы в строки, например, 1/!1+[]дает "Infinity".

Я проанализировал различные встроенные методы для массивов [], объектов {}, регулярных выражений /(?:)/, чисел 1.1, строк "1"и обнаружил один прекрасный метод RegExpобъекта под названием test(). Его имя может быть составлено из всех доступных символов, например, "t"и "e"из true, и "s"из false. Я создал строку "test"и обратился к этому методу, используя обозначение в квадратных скобках для литерала регулярного выражения /-/, правильно обозначенного в этой строке:

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

Как уже обсуждалось, этот фрагмент кода оценивается в Chrome как:

function test() { [native code] }

в Firefox как:

function test() {
    [native code]
}

и в IE как:

 function test() {     [native code] }  

(в последнем обращайте особое внимание на пробел перед functionключевым словом)

Итак, как вы ясно видите, мой код получал 24-й символ из представленной строки, которая в Chrome была "v"(как и было запланировано), но, к сожалению, в Firefox и IE - "n"и "["соответственно.

Чтобы сделать одинаковый вывод во всех браузерах, я использовал другой подход, чем показано в других ответах. Теперь модифицированная версия выглядит так:

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]

Однако, чтобы заинтриговать читателей, я не буду предлагать решение для этого. Я искренне верю, что вы легко поймете, как это работает ... а некоторые могут даже удивить своих любимых кросс-браузерным способом;)

PS Еще один обфускатор

Вдохновленный идеей Джейсона создать универсальный запутывающий инструмент, я написал еще один. Вы можете найти его на JSBin: http://jsbin.com/amecoq/2 . Он может запутать любой текст, который содержит цифры [0-9], маленькие латинские буквы [a-z]и пробелы. Длина строки ограничена в основном вашей оперативной памятью (по крайней мере, тело моего ответа было успешно скрыто). Вывод поддерживается Chrome, Firefox и IE.

Подсказка: инструмент использует другой способ запутывания, чем был представлен выше.


4
"конструктор" ... вау, это удивительно, и вы сохранили идеальный прямоугольник с правильными переносами строк. Вы хороши
Джейсон Сперске

1
Я создал Обфускатор, который создает строку в соответствии с вашими правилами стиля: jsfiddle.net/w9rFF/8
Джейсон Сперске

@JasonSperske Это был хороший трюк! Отличная работа! Я постараюсь внести свой вклад в это.
VisioN

26

Почему не native codeбит из вопроса используется? Это дает 'v'в Chrome и 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]

Изменить для поддержки IE и сделать это без троичного оператора: этот работает в Chrome, IE и FF. Создает массив и использует его ==для определения браузера.

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

Удобочитаемый:

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

Это интересно. Первоначально было отклонено, что размещение слов «родной код» было непредсказуемым между Firefox и Chrome. Это решает эту проблему, но не работает в IE10 (где он возвращает «i»). Тем не менее, мне интересно, если этот вариант может предложить некоторые свежие идеи
Джейсон Сперске

Идея заключается в том , чтобы просто выбрать как nи vи просто выбрать в зависимости от того является самым большим: str[23]>str[27]?str[23]:str[27]. Другими словами, третичный оператор - хитрость. Может быть расширен и для поддержки IE:([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1+(1^(11+1+1)<<1)]
Supr

1
Ваш ответ был первым (впереди автора оригинального кода), но я чувствовал, что его ответ наиболее логично можно считать правильным. Все еще отличная работа (и вполне заслуженные 13 голосов)
Джейсон Сперске

1
Незначительная мелочь: третичный оператор является третьим по важности оператором после первичного и вторичного. Оператор, который принимает три операнда, является троичным.
Эрик Липперт

1
@EricLippert, ага, я даже прибегнул к гуглу, чтобы убедиться, что я использовал правильный термин, но я все же получил неправильный! Спасибо, исправлено.
13

8

Это примерно так близко, как я мог бы, к сожалению, это нарушает соглашение оригинальной запутывания, делая вызов unescape():

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

Срывать:

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

Другие идеи:

  1. Как-то добраться до unescape("\x76")
  2. Как-то конвертировать 118без звонкаString.fromCharCode()
  3. Получить текст из исключения со словом «Неверный»

Обновления:

Я начал играть в гольф-код и делаю его короче, заменяя детали на новые 1и т.д.


Мне тоже нравится этот Я немного разорван в выборе «правильного» ответа, так как ваш и @ alpha123 выглядят крайне запутанными и умно скрывают первоначальное намерение.
Джейсон Сперске

И поддержка IE10 заключает сделку (с искренними извинениями @ alpha123 за отличный ответ)
Джейсон Сперске

Можно заменить , что '%'с (/%/+[[]+1/!1])[1]удалением любых цитат. Я также добавил l=unescape;использование строчных букв, Lчтобы скрыть ссылку на unescape. Это было весело :)
Джейсон Сперске

@JasonSperske: еще короче:(/%/+[])[1]
Cᴏʀʏ

1
Или вы можете назвать свою переменную $1;
Cᴏʀʏ

4

Вот часть, которая генерирует n / v:

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

В Firefox ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])оценивает

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

в то время как в Chrome это

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

1^11<<1 равно 23. Так что из-за лишних пробелов в Firefox этого недостаточно для того, чтобы добраться до «v», а вместо этого «n».

И именно поэтому вы не должны полагаться на поведение Function # toString. ;)

РЕДАКТИРОВАТЬ: Наконец-то я нашел достаточно запутанную кросс-браузерную версию:

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

Это заменяет n / v раздел с:

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

который использует различия в parseInt (очевидно, Firefox анализирует числа, начинающиеся с 0 как восьмеричные, в то время как Chrome нет), чтобы добавить 4 в случае Firefox, таким образом получая 'v' от 'native' в обоих случаях (я не могу найти другой 'v ' :П).
ParseInt выглядит немного неуместно, но это лучшее, что я могу сделать на данный момент.


1
ВопросDoes anyone else have an idea of how to generate a "v" that is in keeping with the original obfuscated code?
Ян

Спасибо. Теперь я пытаюсь найти кросс-браузерный способ сделать это ... «V» - удивительно необычное письмо…
Peter C

@Ian - ну тогда, по-видимому, [(1 ^ 11 << 1) + 1 + 1 + 1 + 1] это сделает?
Enhzflep

@JanDvorak - у меня нет FF на данный момент. Что он оценивает? Если я могу быть настолько самонадеянным, чтобы спросить, то есть.
Enhzflep

@enhzflep извините, я имел в виду "это не сработает в Chrome, с другой стороны"
Джон Дворак

4

Для общего случая использования, если регистр символов не является большой проблемой, я могу склониться немного обмануть.

Создайте функцию «c», которая превращает число 0 .. 25 в символ.

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

Из соображений производительности предварительно кэшируйте буквы, если хотите.

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

В консоли Chrome результирующий массив выглядит следующим образом:

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

Так что ... твой V может быть l[10+10+1].

В качестве альтернативы общее решение, подобное этому:

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

Или, для этой конкретной проблемы, может быть просто:

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

3

Это дает AV в Chrome:

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

И это делает это в Firefox:

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

Они оба вытаскивают его Object.prototype.preventExtensions(), так что вы можете найти кросс-браузерный способ ссылки на этот метод. (Это единственное 17-символьное имя в Object.Prototype для начинающих.)

Не стесняйтесь создавать более запутанную версию этого и взять на себя всю ответственность, я вне времени;)


2

В chrome выражение ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])оценивает до "function test() { [native code] }", [1^11<<1]вычисляет до 23 (побитовые операторы приводят к усечению переменной до 32 бит)


ВопросDoes anyone else have an idea of how to generate a "v" that is in keeping with the original obfuscated code?
Ян
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.