Глава 7. JavaScript без букв и цифр

Написание JavaScript без букв и цифр

Все началось с того, что пользователи форума бездельников (slackers) заметили неожиданный новый пост Йосуке Хасэгавы, выдающегося японского исследователя безопасности. В посте он подробно описал, как вы можете выполнять JavaScript не применяя буквенно-цифровые символы. Это стало для всех нас откровением, и мы начали анализировать как это работает. Основная идея состояла в том, чтобы для создания строк использовать квадратные скобки и выражения JavaScript, а затем для доступа к строкам и их объединения под создание допустимых имён свойств и, в конечном итоге, написания произвольного JavaScript без буквенно-цифровых символов применять числовые индексы, также основанные на выражениях. Это также стало известно как JSF*ck. Я скрыл букву "u", чтобы в этой книге не отображались нецензурные слова. С этого момента я буду называть его подходящим для семьи названием "без букв и цифр" JavaScript, или не-альфа JS. Чтобы создать не-альфа JS, вам сначала нужен способ генерации числа, а поскольку JavaScript обладает слабой типизацией, вы можете осуществить это при помощи инфиксного оператора "+", данный оператор попытается преобразовать следующее выражение в число или NaN (Not a number - не число), когда нет возможности такого преобразования. Итак, первый шаг — получение нуля:


1 +[]//0
 	   

Отлично, итак мы обладаем нулём, но это позволит нам получать лишь самый первый символ строки:


1 'abc'[+[]]//a
 	   

Но как мы можем получать "b"? Ладно, вы можете сочетать метод доступа квадратных скобок с неким массивом и получать ссылку на элемент в таком массиве, а JavaScript позволяет вам увеличивать/уменьшать на единицу это значение так же, как будто это было идентификатором:


1 [+[]]//создаёт массив с 0 в нём
2 
3 [+[]][+[]]//получает самый первый элемент в этом массиве
4 
5 ++[+[]][+[]]//увеличивает на единицу самый первый элемент в этом массиве для создания 1
6 
7 'abc'[++[+[]][+[]]]//сочетает все приведённое выше для получения b
 	   

Надеюсь, вы следите за ходом действий. Возможно, стоит попробовать каждый отдельный фрагмент кода и оценить его в консоли чтобы понять что происходит. Как только вы усвоите эту концепцию, вы сможете легко приступать к выработке строк и чисел. Вам просто необходимо просто вкладывать вырабатываемые массивы и продолжать увеличивать их и объединять буквы для формирования свойств JavaScript. Давайте сгенерируем число два, а я буду пользоваться пробелами чтобы различать числа:


1 ++[ ++[+[]][+[]] ] [+[]]//2
 	   

Обычно вы не пользуетесь пробелами. Я только что добавил их с тем, чтобы было проще отслеживать. Итак, из приведённого выше кода вы можете наблюдать, что при помощи +[] вы создаёте массив, в котором содержится ноль, затем вы получаете доступ к самому первому элементу в этом массиве, снова применяя +[], а потом вы применяете оператор приращения для увеличения числа, которое потом завёртываете в другой массив и следуете тем же самым процессом, причём становится трудно читать при вложениях дальше и дальше, но как только вы освоите эту концепцию, вы будете способны её писать.

Из своего текста мы способны получить "c":


1 'abc'[++[ ++[+[]][+[]] ] [+[]]]
 	   

Ну, у нас имеются основы выработки чисел без буквенно- цифровых символов, но как вы сгенерируете строки? Мы снова воспользуемся преимуществами слабой типизации JavaScript для преобразования различных типов в строки. Например, давайте посмотрим на логические значения, мы способны извлечь символы "f", "a", "l", "s" "e" из false и мы можем выполнить аналогичный процесс, который мы осуществляли для чисел, но на этот раз мы будем применять булев оператор not, данный оператор вернёт false если его операнд можно преобразовать в true и наоборот. Это означает, что мы можем воспользоваться пустым массивом снова и преобразовать его в булев:


1 ![]//false
 	   

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


1 ![]+[]//false (строка)
 	   

Великолепно, итак теперь у нас имеются символы, но как их выделить? Мы можем последовать тому же процессу что и ранее, мы можем поместить своё выражение вовнутрь массива и получить самый первый элемент в этом массиве (нашей строке), а затем воспользоваться индексом для получения отдельного символа:


1 [![]+[]]//добавляем строковое значение false в массив
2 [![]+[]][+[]]//получаем самый первый элемент своего массива
3 [![]+[]][+[]][+[]]//f - получаем самый первый символ из данной строки
 	   

Затем вы можете следовать этим же процессом для всех остающихся символов и просто увеличивать значение индекса, как мы это делали для инкрементации своих чисел. Самый простой способ выполнения этого заключается в выполнении этого для пометки вашего выражения комментария, как я это и сделали последующей комбинации их, таким образом, нам требуется значение следующего символа, стоящего в позиции один. Если мы вернёмся к фрагменту его кода для и скопируете это будет так, как приведено ниже:


1 ++[+[]][+[]]//1
 	   

Затем получим false из другого примера:


1 [![]+[]][+[]]//false (строка)
 	   

Теперь соединим вместе строку false и средство доступа к значению числа:


1 [ ![]+[]] [+[]] [ ++[+[]][+[]] ]//a
 	   

Для ясности я выше добавил пробелы. Когда вы собираете символы, целесообразно сохранять их в текстовом файле с комментариями, чтобы показывать что они собой представляют, это упрощает создание новых строк. Надеюсь, вы теперь достаточно уверенно создаёте такие символы. Давайте продолжим создавать оставшиеся символы для false.


1 [ ![]+[]] [+[]] [ ++[++[+[]][+[]]][+[]] ]//l
 	   

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


1 [   ![]+[]]   [+[]]    [   ++[++[++[+[]][+[]]][+[]]][+[]]    ]//s
2 [   ![]+[]]   [+[]]    [   ++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]    ]//e
 	   

Как вы можете наблюдать в приводимом выше сопоставлении, при создании символов "s" и "e" требуется лишь небольшое изменение. На самом деле, мы можем повторно применять весь этот процесс для создания противоположности true, которая выступает false. Итак, помните, когда мы обнаружили, что ![] вырабатывает false? Если мы снова воспользуемся логическим оператором not, он преобразует это в true:


1 !![]//true
 	   

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


1 [![]+[]][+[]][+[]]//f
 	   

становится


1 [!![]+[]][+[]][+[]]//t
 	   

и так далее:


1 [   !![]+[]]   [+[]]    [   ++[+[]][+[]]    ]//r
2 [   !![]+[]]   [+[]]    [   ++[++[+[]][+[]]][+[]]    ]//u
 	   

У нас уже имеется "e", поэтому нам не нужно вырабатывать его снова. Теперь вы можете увидеть, как довольно просто генерировать символы. Вы можете задуматься о том, как можно сгенерировать произвольный JavaScript. Ну, сначала вам нужно получить доступ к функции, и для этого вам нужно сгенерировать некоторые символы, которые при использовании в качестве средства доступа получают функцию, а затем вы можете применять эту функцию, чтобы получить её конструктор, который будет конструктором функции, Вы видите, куда это ведёт? Получив доступ к конструктору Function, вы можете вызывать его для генерации произвольного JavaScript, но об этом мы поговорим позже. Самый первый шаг состоит в получении функции, и очень удобно, что имеется хорошая короткая функция, к которой мы уже можем получить доступ при помощи выработанных нами символов. Функция at позволяет вам получать один символ строки или элемент массива в зависимости от того, для какого объекта вы её применяете. Мы собираемся применять это, потому как, очевидно, это длина сортировки. Итак, сначала нам нужен пустой массив:


1 []
 	   

Затем мы добавляем средство доступа:


1 [] [ ]
 	   

Теперь мы добавляем строку "a" и соединяем её с "t":


1 [] [   [   ![]+[]]   [+[]]    [   ++[+[]][+[]]    ] /*a*   +   [!![]+[]][+[]][+[]]  \
2 /*t*/ ]//функция at
 	   

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


1 [].at+''//function at() { [естественный код] }
 	   

Если мы ищем выработанные нами ранее символы, единственными остающимися для производства нами символами выступают "o", "c", "n". Мы можем сгенерировать "n" при помощи undefined, что мы и выполняем далее. Сначала мы создадим пустой массив и испытаем доступ к первому undefined символу:


1 [][+[]]//undefined
 	   

Затем мы преобразуем это в строку и выполним доступ ко второму символу с позицией один:


1 [[][+[]]+[]][+[]][++[+[]][+[]]]//n
 	   

Теперь мы можем выработать всё остальное для создания своего свойства конструктора. Для выработки остающихся символов мы можем повторно воспользоваться функцией at, преобразуя её в строку, выработать необходимое положение и, в конце концов, выделить его.

Сначала мы создаём пустой массив и получаем доступ к его первому элементу:


1 [][+[]]
 	   

Затем мы помещаем свою функцию вовнутрь этого массива и выполняем конкатенацию с пустым массивом для создания строки:


1 [    [] [[![]+[]][+[]][++[+[]][+[]]]+ [!![]+[]][+[]][+[]]] +[]     ][+[]]
 	   

Мы можем повторно воспользоваться строкой выше для выработки "c":


1 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
2 //function at() { [естественный код] } в качестве строки
3 [++[++[++[+[]][+[]]][+[]]][+[]]]//3
4 //совместно производят c
 	   

Самая первая приведённая выше строка вырабатывает функцию at в виде строки, вторая строка выполняет доступ к третьей позиции этой строки, которая производит "c".

Для выработки "o" нам снова требуется следовать этим же процессом, но получить доступ к 6й позиции строки:


1 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
2 //function at() { [естественный код] } в качестве строки
3 [++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]]//6
4 //совместно производят o
 	   

В точности как с пазлом, мы можем совместить это вместе для получения доступа к самому свойству конструктора:


 1 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
 2 [++[++[++[+[]][+[]]][+[]]][+[]]]
 3 //c
 4 
 5 +
 6 
 7 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
 8 [++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]]
 9 //o
10 
11 +
12 
13 [[][+[]]+[]][+[]][++[+[]][+[]]]//n
14 
15 +
16 
17 [   ![]+[]]   [+[]]    [   ++[++[++[+[]][+[]]][+[]]][+[]]    ]//s
18 
19 +
20 
21 [!![]+[]][+[]][+[]]//t
22 
23 +
24 
25 [   !![]+[]]   [+[]]    [   ++[+[]][+[]]    ]//r
26 
27 +
28 
29 [   !![]+[]]   [+[]]    [   ++[++[+[]][+[]]][+[]]    ]//u
30 
31 +
32 
33 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
34 [++[++[++[+[]][+[]]][+[]]][+[]]]
35 //c
36 
37 +
38 
39 [!![]+[]][+[]][+[]]//t
40 
41 +
42 
43 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
44 [++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]]
45 //o
46 
47 +
48 
49 [   !![]+[]]   [+[]]    [   ++[+[]][+[]]    ]//r
 	   

Выше я отделил все буквы и поместил оператор конкатенации строк в каждый раздел, чтобы вы могли наблюдать как это работает. Когда всё формируется воедино, это выстраивает строку "constructor". Для получения доступа к реальной функции- конструктору, нам необходимо воспользоваться функцией at(), к которой мы ранее в этой главе уже получили доступ без её преобразования в строку:


 1 [    [] [[![]+[]][+[]][++[+[]][+[]]]+ [!![]+[]][+[]][+[]]]      ][+[]]
 2 //функция at()
 3 [//добавили квадратные кавычки  для формирования доступа к предыдущей функции
 4 
 5 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
 6 [++[++[++[+[]][+[]]][+[]]][+[]]]+[[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]\
 7 ]]+[]][+[]]
 8 [++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]]+[[][+[]]+[]][+[]][++[+[]\
 9 ][+[]]]+[   ![]+[]]   [+[]]    [   ++[++[++[+[]][+[]]][+[]]][+[]]    ]+[!![]+[]][+[]
10 ][+[]]+[   !![]+[]]   [+[]]    [   ++[+[]][+[]]    ]+[   !![]+[]]   [+[]]    [   ++[
11 ++[+[]][+[]]][+[]]    ]+[[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[
12 ]]
13 [++[++[++[+[]][+[]]][+[]]][+[]]]+[!![]+[]][+[]][+[]]+[[] [[![]+[]][+[]][++[+[]][+[]]\
14 ]+[!![]+[]][+[]][+[]]]+[]][+[]]
15 [++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]]+[   !![]+[]]   [+[]]    \
16 [   ++[+[]][+[]]    ]
17 
18 ]//добавили квадратные кавычки для формирования доступа к предыдущей функции
19
20 //всё это вместе создаёт конструктор Function
 	   

Мы получили доступ к конструктору Function, соединив функцию at(), а добавляя [] после и внутри метода доступа мы разместили строку "constructor", которая затем возвращает необходимый конструктор Function. Теперь мы можем исполнить произвольный JavaScript, передавая конструктору Function некую строку и вызывая её дважды.

Теперь нам просто нужно выработать строку для её отправки конструктору Function. Мы собираемся вызвать alert(1) в качестве традиционной полезной нагрузки XSS. У нас уже есть буквы и цифра один:


1 [   ![]+[]]   [+[]]    [   ++[+[]][+[]]    ]//a
2 [   ![]+[]]   [+[]]    [   ++[++[+[]][+[]]][+[]]    ]//l
3 [   ![]+[]]   [+[]]    [   ++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]    ]//e
4 [   !![]+[]]   [+[]]    [   ++[+[]][+[]]    ]//r
5 [!![]+[]][+[]][+[]]//t
6 ++[+[]][+[]]//1
 	   

Нам остаётся сгенерировать открывающую и закрывающую скобки. Для этого мы можем повторно воспользоваться кодом, в котором мы выработали свою функцию at() и преобразовали это в строку и затем получить доступ к 6й позиции данной строки:


1 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
2 //function at() { [естественный код] } в качестве строки
3 [++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]]//6
 	   

Нам всего лишь требуется увеличить значение шесть для получения одиннадцатой позиции:


1 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]//function at() { [естест\
2 венный код] } в качестве строки
3 [++[++[++[++[++[++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]\
4 ]][+[]]][+[]]][+[]]]//11
5 //который производит (
 	   

И увеличить приведённое выше на единицу:


1 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
2 //function at() { [естественный код] } в качестве строки
3 [++[++[++[++[++[++[++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]][\
4 +[]]][+[]]][+[]]][+[]]][+[]]]//12
5 //который производит )
 	   

Нам просто нужно расположить эти части в верном порядке и передать их ранее выработанному конструктору и это всё. Не забывайте добавлять к каждой из строк оператор канкатенации "+".


 1 [    [] [[![]+[]][+[]][++[+[]][+[]]]+ [!![]+[]][+[]][+[]]]      ][+[]]
 2 
 3 [
 4 
 5 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
 6 [++[++[++[+[]][+[]]][+[]]][+[]]]+[[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]\
 7 ]]+[]][+[]]
 8 [++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]]+[[][+[]]+[]][+[]][++[+[]\
 9 ][+[]]]+[   ![]+[]]   [+[]]    [   ++[++[++[+[]][+[]]][+[]]][+[]]    ]+[!![]+[]][+[]
10 ][+[]]+[   !![]+[]]   [+[]]    [   ++[+[]][+[]]    ]+[   !![]+[]]   [+[]]    [   ++[
11 ++[+[]][+[]]][+[]]    ]+[[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[
12 ]]
13 [++[++[++[+[]][+[]]][+[]]][+[]]]+[!![]+[]][+[]][+[]]+[[] [[![]+[]][+[]][++[+[]][+[]]\
14 ]+[!![]+[]][+[]][+[]]]+[]][+[]]
15 [++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]]+[   !![]+[]]   [+[]]    \
16 [   ++[+[]][+[]]    ]
17 
18 ]
19 (
20 [   ![]+[]]   [+[]]    [   ++[+[]][+[]]    ]+//a
21 [   ![]+[]]   [+[]]    [   ++[++[+[]][+[]]][+[]]    ]+//l
22 [   ![]+[]]   [+[]]    [   ++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]    ]+//e
23 [   !![]+[]]   [+[]]    [   ++[+[]][+[]]    ]+//r
24 [!![]+[]][+[]][+[]]+//t
25 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
26 //function at() { [естественный код] } в качестве строки
27 [++[++[++[++[++[++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]\
28 ]][+[]]][+[]]][+[]]]+
29 //(
30 
31 ++[+[]][+[]]+//1
32 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
33 //function at() { [естественный код] } в качестве строки
34 [++[++[++[++[++[++[++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]][\
35 +[]]][+[]]][+[]]][+[]]][+[]]]//12
36 //)
37 )
 	   

Я надеюсь, вы следовали за нами и теперь способны создавать JS без альфа! С этим кодом вы можете осуществить некоторые оптимизации, например, сократить [![]+[]][+[]] до (![]+[]), в этом коде присутствует большое число мест для уменьшения. В качестве упражнения попробуйте сократить приведённый выше код до минимально возможного, тем самым вы больше узнаете о JavaScript и вскоре будете способны писать JS без альфа как обычный код.

Безбуквенность без скобок

Теперь, когда вы уверенно пишите не-альфа код, мы можем воспользоваться полученные в предыдущих главах знаниями чтобы попытаться создать не-альфа код без круглых скобок. Для этой задачи мы будем применять ограниченный набор символов, а именно:


1 []`+!${}
 	   

Как вы уже знаете, шаблонные строки способны выполнять JavaScript через заполнители, причём их можно применять и для передачи аргументов функциям. Мы намерены неверно воспользоваться этим фактом дабы создать некую не- альфа последовательность, которая вызывает конструктор Function с нашей строкой alert.

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

Мы намерены вызвать такой конструктор Function воспользовавшись помеченной строкой шаблона, что просто означает, что мы намерены поместить `` после такой функции, а затем мы намерены выработать свою строку для прохода к ней. Для представления аргумента конструктору Function мы воспользуемся символом $, который мы не собираемся применять, но он необходим, поскольку мы не можем контролировать первый отправляемый в нашу функцию аргумент. Чтобы разобраться с тем что происходит, попробуйте оценить данный вызов функции чтобы увидеть возвращаемый результат:


1 Function`$${"x"}$`
2 /*
3 function anonymous($,$
4 ) {
5 x
6 }
7 */
 	   

Как мы наблюдаем выше, эта функция вызывается с двумя следующими друг за другом $, а третий аргумент применяется для выработки кода. Самый первый аргумент преобразуется из массива в строку, поэтому нам надлежит помещать символы долларов до и после соответствующего заполнителя. Если бы мы не применяли эти доллары, конструктор Function возбудил бы исключительную ситуацию из- за недопустимого JavaScript. Очень удобно, что доллар является допустимым идентификатором JavaScript и разрешён в качестве имени параметра. Мы можем повторно воспользоваться кодом из предыдущей главы, причём мы сначала поместим код конструктора Function, затем доллар, потом наш заполнитель, который вырабатывает строку alert, а затем следует ещё один доллар. Данный код завершается ``, которая вызывает выработанную нами функцию:


 1 [[][[![]+[]][+[]][++[+[]][+[]]]+ [!![]+[]][+[]][+[]]]][+[]][[[] [[![]+[]][+[]][++[+[\
 2 ]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
 3 [++[++[++[+[]][+[]]][+[]]][+[]]]+[[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]\
 4 ]]+[]][+[]]
 5 [++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]]+[[][+[]]+[]][+[]][++[+[]\
 6 ][+[]]]+[![]+[]][+[]][   ++[++[++[+[]][+[]]][+[]]][+[]]]+[!![]+[]][+[]][+[]]+[!![]+[
 7 ]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][++[++[+[]][+[]]][+[]]]+[[][[![]+[]][+[]][++[+[]
 8 ][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]][++[++[++[+[]][+[]]][+[]]][+[]]]+[!![]+[]][+[]]
 9 [+[]]+[[][[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]][++[++[++[++[++[+
10 +[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]]+[!![]+[]][+[]][++[+[]][+[]]]]
11 
12 `$${[   ![]+[]]   [+[]]    [   ++[+[]][+[]]    ]+
13 [   ![]+[]]   [+[]]    [   ++[++[+[]][+[]]][+[]]    ]+
14 [   ![]+[]]   [+[]]    [   ++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]    ]+
15 [   !![]+[]]   [+[]]    [   ++[+[]][+[]]    ]+
16 [!![]+[]][+[]][+[]]+
17 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
18 [++[++[++[++[++[++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]\
19 ]][+[]]][+[]]][+[]]]+
20 ++[+[]][+[]]+
21 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
22 [++[++[++[++[++[++[++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]][\
23 +[]]][+[]]][+[]]][+[]]][+[]]]
24 }$` ``
 	   

Стена из шести символов

После большого числа взломов на форуме бездельников, пытавшихся выяснить, что было возможно при помощи не-альфа кода, мы все пришли к выводу, что минимальное ограничение, которым вы можете обладать для выполнения произвольного JavaScript, составляет шесть символов. Это стало известно как великая стена символов. Предел обусловлен тем, что без ! вы не можете создавать логические значения, а без + вы не можете конвертировать в целые числа и объединять строки, не используя больше символов. Наиболее вероятный способ сломать эту стену — использовать следующую кодировку +* и найти способ выработки логического значения. Это важно, потому что false содержит "s", а true содержит "r". Без этих символов вы не сможете построить свойство конструктора и, следовательно, не сможете выработать требуемую строку, чтобы получить к нему доступ.

Бесконечность и за её пределами

Если бы вы собрались попытаться сломать эту стену, вам необходимо было бы вырабатывать больше символов, потому как вы застряли бы с "NaN" и "undefined". Ну, только с помощью +[] можно выработать Infinity! Давайте посмотрим, как это делается. Сначала мы собираемся выработать, как и раньше, число один, затем вам нужно сгенерировать неопределённую строку, и нам требуется из неё "е". После этого вы просто объединяете больше единиц в конце, чтобы сформировать строку "1e1111", которая производит Бесконечность Infinity.


1 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
2 //function at() { [естественный код] } в качестве строки
3 [++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]]//6
 	   

Прежде всего вырабатываем 1:


1 ++[+[]][+[]]//1
 	   

Затем вырабатываем строку undefined:


1 [][+[]]+[]//undefined в качестве строки
 	   

Из строки undefined нам требуется получить доступ к из неё "е":


1 [[][+[]]+[]][+[]][++[++[++[+[]][+[]]+[]][+[]]][+[]]]//e
 	   

Соединяем всё вместе для формирования 1e1111:


1 [++[+[]][+[]]+[[][+[]]+[]][+[]][++[++[++[+[]][+[]]+[]][+[]]][+[]]]+[++[+[]][+[]]]+[+\
2 +[+[]][+[]]]+[++[+[]][+[]]]+[++[+[]][+[]]]]
 	   

Наконец, нам необходимо преобразовать массив/ строку в число при помощью инфиксного оператора + и, в конечном счёте, обернуть его в массив и получить к нему доступ как к строке:


1 [[+[++[+[]][+[]]+[[][+[]]+[]][+[]][++[++[++[+[]][+[]]+[]][+[]]][+[]]]+[++[+[]][+[]]]\
2 +[++[+[]][+[]]]+[++[+[]][+[]]]+[++[+[]][+[]]]]]+[]][+[]]
3 //Infinity в качестве строки
 	   

Вы можете видеть, насколько это близко к разрушению нашей стены, хотя отсутствие логических значений имеет решающее значение для доступа к конструктору. Мы можем только надеяться, что браузеры представят новые функции или методы, которые позволят нам получить доступ к необходимым символам. На данный момент стена символов выглядит как состоящая из шести.

Выводы

В этой главе мы рассмотрели, как вырабатывать числа с помощью безбуквенно-цифрового JavaScript, как использовать эти числа для получения строк, комбинировать эти строки, для получения большего числа символов через доступ к свойствам и преобразования вывода в строку. Затем я показал, как вы можете собрать это воедино для получения исполнения произвольного кода JavaScript. После этого я продемонстрировал, как вырабатывать не-альфа код без применения круглых скобок. Наконец, я познакомил вас с великой стеной символов и показал метод создания Infinity, с применением только +[].