...

понедельник, 11 ноября 2013 г.

[Из песочницы] Еще раз об обфускации JavaScript или сказ о том, как я обфускатор писал

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

(![]+[])




«false»

[] — пустой массив

! — операция логическое НЕ, особенность js (и не только), в том, то при булевых операциях если операнд не является булевым типом и не равен 0 то он признается за true

То есть (![]) = false

+ — операция сложения и объединения строк, если оба операнда числа, то произойдет сложения, иначе это будет объединение строк с приведением типов. Кстати, тут есть особая магия типов, но это позже.



(!(![])+[])




«true»

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

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



([]|[])




0

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

(-~[])




1

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

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



([]+{})




"[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'


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends:



Комментариев нет:

Отправить комментарий