Pull to refresh

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

Reading time3 min
Views13K
Возникла тут задача, написать код на php, который принимает js-код и обфусцирует его по самое не балуй. После курения гугла и хабра (в том числе, как правильно подсказывает monolithed, вот этой статьи) я приступил к работе. Как и следовало, я начал того, что запустил консоль JS в хроме и начал пытаться получать строки из месива символов, вот что получилось (с пояснениями):
(![]+[])

«false»
[] — пустой массив
! — операция логическое НЕ, особенность js (и не только), в том, что при булевых операциях если операнд равен 0, false, undefined, null, '' (пустой строке), то он приводится к false. Во всех остальных случаях — к true. (спасибо oshibka404 за поправки)
То есть (![]) = 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'
Tags:
Hubs:
If this publication inspired you and you want to support the author, do not hesitate to click on the button
+24
Comments37

Articles

Change theme settings