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

этот вопрос трудно подытожить в заголовке вопроса

UPDATE Я создал JSFiddle, который строит запутанную строку из вашего ввода на основе букв, извлеченных из этого вопроса: вы можете получить к нему доступ здесь или gist быть проще?

Недавно я встретил забавный бит запутанного 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 "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 и @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 рассказывает, насколько вы его чувствуете:)

Ответ 1

Прежде всего, я хотел бы поблагодарить Джейсона и всех участников за то, что он играл с этим смешным фрагментом. Я написал этот кусок кода просто для удовольствия, чтобы отправить его моей жене 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" и обратился к этому методу с использованием обозначения квадратных скобок для литерала regex /-/, правильно идентифицированного в этой строке:

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

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

P.S. Еще один обфускатор

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

Совет: инструмент использует различные методы обфускации, чем было представлено выше.

Ответ 2

Почему не используется бит 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)
]

Ответ 3

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

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

Teardown:

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

Другие идеи:

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

Обновление:

Я начал играть в гольф кода и сокращал его, заменяя части более 1 s и т.д.

Ответ 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".

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

EDIT: Наконец, я нашел достаточно запутанную кросс-браузерную версию:

[[]+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': P).
ParseInt выглядит немного неуместно, но это лучшее, что я могу сделать сейчас.

Ответ 5

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

Создайте функцию "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"

Ответ 6

Это дает v в Chrome:

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

И это происходит в Firefox:

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

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

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

Ответ 7

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