Возникла тут задача, написать код на 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'
Комментариев нет:
Отправить комментарий