Obfuscated код javascript с двоичными значениями?

Этот код выводит D. Вопрос: КАК?

alert([][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()[([][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(![]+[])[+!+[]]](+[]+[+[]])[+!+[]]);

Я понимаю, что ![] оценивается как false или 0 и т.д., но как он выполняется? И как я могу преобразовать это в нечто, что могут понять люди, и не только Джон Скит?

Может кто-то сломать часть этого кода и объяснить мне, что происходит?

Ответы

Ответ 1

Ну, оценивая выражение в частях, в конце это эквивалентно:

[]['sort']['call']()["btoa"]("00")[1]; // "D"

Что можно упростить до:

btoa("00")[1]; // "D"

Как вы можете "декодировать его"?

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

Как это работает?

Хитрость заключается в цепочке преобразований нескольких типов, например, для получения буквы f:

(![]+[])[+[]]

Если мы рассмотрим первую часть в круглых скобках ![]+[], мы увидим логическое отрицание, которое вернет false, потому что объект массива всегда правдивый, а затем конкатенация.

Это создает строку "false", затем вторую часть мы видим скобки, применяемые к этой строке, для доступа к символу и выражение +[], что приводит к 0.

+[] дает нуль, потому что метод Array toString возвращает пустую строку для пустого массива, подобного этой, и пустая строка генерирует нуль, когда она преобразуется в число (унарный оператор + в этом пример).

Есть только такие трюки, вещи, которые производят строку, такие "true", "false", "null", "undefined" и т.д.... и больше трюков, чтобы получить числовое значение.

Например, чтобы получить номер - для доступа к символу - они снова используют преобразование скрытого типа:

+[];            // 0, equivalent to +""
+!+[];          // 1, equivalent to +true
!+[]+!+[];      // 2, equivalent to +true+true
!+[]+!+[]+!+[]; // 3, equivalent to +true+true+true

Ответ 2

Он делает некоторые трюки с преобразованиями типа javascript. Как указывала CMS, это эквивалентно: []['sort']['call']()["btoa"]("00")[1];

Они строят строки, вытаскивая их из таких вещей, как false и т.д.

Например, чтобы получить s в "sort":

Получить "false": (![]+[]) - ![] возвращает false и +[] преобразует его в строку.

Получить значение 3 с помощью: !+[]+!+[]+!+[] - каждый !+[] возвращает true, но когда вы добавляете логические значения, вы получаете целочисленное представление. например true + true = 2

Получите s с записью доступа к индексу строки ("false"[3] = 's'): (![]+[]) [!+[]+!+[]+!+[]]

И теперь у вас есть s. Они продолжают делать это до тех пор, пока у них не будет достаточно доступа к тому, какой метод или свойство они хотят.

Ответ 3

! [] неверно.! [] + [] оценивает значение "false". +[] равно 0, поэтому! + [] истинно и т.д. javascript очень странно с его подразумеваемыми преобразованиями типов