Еще раз об обфускации JavaScript или сказ о том, как я обфускатор писал. Часть 1

в 8:00, , рубрики: Brainfuck, javascript, ненормальное программирование, обфускация, метки: , , ,

Возникла тут задача, написать код на php, который принимает js-код и обфусцирует его по самое не балуй. После курения гугла и хабра я приступил к работе. Как и следовало, я начал того, что запустил консоль JS в хроме и начал пытаться получать строки из месива символов, вот что получилось (с пояснениями):

(![]+[])

«false»
[] — пустой массив
! — операция логическое НЕ, особенность js (и не только), в том, то при булевых операциях если операнд не является булевым типом и не равен 0 то он признается за true
То есть (![]) = false
+ — операция сложения и объединения строк, если оба операнда числа, то произойдет сложения, иначе это будет объединение строк с приведением типов. Кстати, тут есть особая магия типов, но это позже.

(!(![])+[]) 

«true»
Абсолютно тот же принцип, только добавилось двойное отрицание array=>false=>true=>«true»

Теперь нам надо получить два числа, в свое распоряжение, кто угадает какие?

([]|[])

0
Тут у нас снова идут пустые массивы пропущенные через побитовое ИЛИ, суть проста пропускаем любые пустые элементы — получаем ноль

(-~[])

1
А вот тут все малость по сложнее, как мы помним [] — пустой массив, а мы берем его и отрицаем, да не просто так, а побитово, но [] в битовом представлении это будет что-то типа 00000000, а если инвертировать 11111111, казалось бы должно получиться 255, однако это не так, не вдаваясь в подробности представления чисел и всякие дебри (мантиссы, знаковые разряды), достаточно сказать, что в битовом представлении в памяти машины хранят не только число, но и знак, вообщем если надо, почитаете, что это я объясняю, рокомнадзор еще не запретил гугл. Вообщем из 0 мы получаем -1, а так, как у на уже есть один знак минус, то получается --1=1
Уважаемый vitvad в комментариях любезно дал ссылку на видео, где объясняют «магию» чисел

Хм, мы конечно получили уже не мало, но чем больше, тем лучше!

([]+{})

"[object Object]"
Тут опять все просто, до зубовного скрежета, пустой массив плюс пустой объект, объединение строк. А! Стоп! Я же хотел немного рассказать по этому поводу — если при объединении строк один из операндов является объектом, то за место него возвращается "[object %object_name%]"

([]/[]+[])

«NaN»
Сколько будет ноль делить на ноль? А хрен его знает, вот и JavaScript тоже не знает, но те, кто его придумывали были люди умные (впрочем, создатели других языков ни разу не глупее, но зачастую имеют меньше склонностей к мазохизму) и ввели в язык специальное число (и не одно, но об этом чуть ниже), так, что NaN это число, при чем ничему не равное, даже самому себе и обозначает «а хрен его знает». Что же мы тут сделали? Мы разделили пустой массив, на пустой массив, сработало приведение типов, и это получило равно делению 0 на 0. Дальше как обычно

(~[]/-[]+[])

«Infinity»
Давайте еще подумаем, сколько будет -1/-0? Бесконечность и для обозначения бесконечности в JS так-же есть свое число. В принципе, я думаю вы уже догадались как это работает…

([][[]]+[])

«undefined»
Тут дело принимает интересный оборот, как мы помним [] — пустой массив, но обратившись к нему, мы выделили под него место, и мы можем обращаться к его элементам, чем мы и не замедлили воспользоваться, обратившись к элементу массива по индексу… пустого массива, но, так, как до нашего обращения там ничего не было нам возвращается undefined, специальный тип, обозначающий «здесь что-то могло быть, но его не было, пока я не посмотрел, а сейчас здесь оно есть, но внутри пусто» или короче «не заданно».

Ну, давайте подведем итог первой части, изыскательной и напишем простой аллерт

alert('cool')
_=[][(![]+[])[(-~[])+(-~[])+(-~[])]+([]+{})[(-~[])]+(!(![])+[])[(-~[])]+(!(![])+[])[([]|[])]];
_=_();
_[(![]+[])[(-~[])]+(![]+[])[(-~[])+(-~[])]+(![]+[])[(-~[])+(-~[])+(-~[])+(-~[])]+(!(![])+[])[(-~[])]+(!(![])+[])[([]|[])]](([]+{})[(-~[])+(-~[])+(-~[])+(-~[])+(-~[])]+([]+{})[(-~[])]+([]+{})[(-~[])]+(![]+[])[(-~[])+(-~[])]);

Разберем по строкам

1) _=[][«sort»] — сохраняем в переменную ссылку на метод sort массив
2) _=_(); — выполняем метод sort, получаем ссылку на объект Window
3) _['alert']('cool') — используя в объекте Window ссылку на метод alert выполняем его с аргументом 'cool'

Автор: t0pep0

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js