Что такое встроенные строки 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]
Однако, чтобы интриговать читателей, я не буду предлагать для этого решения. Я искренне верю, что вы легко поймете, как это работает... и некоторые могут даже удивить своих возлюбленных кросс-браузерным способом;)
Вдохновленный идеей Джейсона создать универсальный инструмент для обфускации, я написал еще одно. Вы можете найти его в 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 бит)