Как стать автором
Обновить

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

Время на прочтение20 мин
Количество просмотров55K
Деобфускация PHP
Так уж случилось, что на днях мне попался один нужный PHP скрипт, но обфусцированный.
По какой-то причине он никак не работал. Я пишу на PHP достаточно давно, и мне очень нравится отлавливать нестандартные ситуации в скриптах, особенно когда при выполнении в логах нет ошибок, а скрипт просто не выполняет своих предназначенных обязанностей, руки так и чесались расшифровать. Последней каплей стало то, что автора этого скрипта не было в сети, чтобы помочь решить мою проблему. Скрипт кстати куплен моим товарищем, собственно он и попросил помочь.

Цель данной статьи, показать принцип дешифровки, зашифрованных скриптов, чтобы например расшифровать залитый злоумышленником вирус на PHP.



Анализирование кода



Вот один из этих скриптов, открывая такой скрипт в блокноте, мы увидим:


Разобьем для начала его на строки:

и сохраним в файл encoded_script.php

Видно что тут код разбит на 4е части. В каждой выполняется eval.
Для удобства дешифровки eval воспользуемся расширением для PHP — Evalhook. Его написал Stefan Esser за что ему большущее спасибо. С помощью него можно расшифровывать в несколько проходов например монстров закодированных через www.php-crypt.com функциями eval, gzuncompress, base64_decode и тд.

Установка evalhook



Требуется:
  1. PHP >= v5.2
  2. php-devel
  3. PHP Zend Optimizer


Скачиваем архив с исходниками
fetch http://php-security.org/downloads/evalhook-0.1.tar.gz


Распаковываем и собираем расширение для PHP
tar xvfz evalhook-0.1.tar.gz
cd evalhook
phpize 
./configure
make
sudo make install


расширение готово, теперь его можно динамически подгружать в консоль и смотреть зашифрованный скрипт.
php -d extension=evalhook.so encoded_script.php


где encoded_script.php — закодированный файл.
Для получения исходного кода просто жмем «Y» несколько раз в процессе деобфускации. Каждый новый Y будет расшифровывать следующий eval. Ну что ж вооружимся консолью и в бой!

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


1-й проход
%php -d extension=evalhook.so encoded_script.php
Script tries to evaluate the following string.
----
$GLOBALS['_562306928_']=Array(base64_decode('' .'Ym' .'FzZTY' .'0X2RlY2' .'9kZQ=='),base64_decode('Y' .'mFzZTY0X2R' .'lY29' .'kZ' .'Q=='),base64_decode('' .'YmFzZT' .'Y0X2RlY29kZ' .'Q=='),base64_decode('YmF' .'zZTY0X2Rl' .'Y29' .'kZQ=='),base64_decode('YmF' .'zZTY' .'0X2RlY2' .'9kZQ=' .'='),base64_decode('' .'Y' .'m' .'FzZTY0X2RlY29k' .'ZQ=='),base64_decode('YmFzZ' .'TY0X2R' .'l' .'Y' .'29k' .'ZQ' .'=='),base64_decode('Y' .'m' .'FzZTY0X2' .'Rl' .'Y' .'29k' .'ZQ=='),base64_decode('YmFzZT' .'Y0X2RlY2' .'9kZQ' .'=='),base64_decode('YmFzZ' .'T' .'Y0X' .'2' .'RlY29kZ' .'Q=='),base64_decode('' .'Y' .'m' .'FzZT' .'Y0X2RlY2' .'9k' .'ZQ=='),base64_decode('Ym' .'FzZTY0X' .'2Rl' .'Y29' .'kZQ=='),base64_decode('YmF' .'zZT' .'Y0' .'X2RlY29' .'kZ' .'Q=='),base64_decode('YmFzZ' .'TY0X2RlY29kZQ=='),base64_decode('Ym' .'FzZTY0X' .'2RlY29k' .'ZQ=='),base64_decode('YmFzZTY0' .'X2RlY' .'29kZQ=='),base64_decode('Ym' .'FzZTY0X2Rl' .'Y2' .'9kZ' .'Q=='),base64_decode('Ym' .'FzZTY0X2' .'R' .'lY29kZQ=='),base64_decode('Y' .'mFz' .'ZTY' .'0' .'X2R' .'lY29k' .'Z' .'Q=='),base64_decode('Y' .'mFzZT' .'Y0X2R' .'lY2' .'9kZQ=' .'='),base64_decode('' .'YmFzZTY' .'0X' .'2' .'RlY29k' .'ZQ=='),base64_decode('' .'Y' .'mFzZTY0' .'X2R' .'lY' .'29kZQ=='),base64_decode('YmFzZTY0' .'X2Rl' .'Y29k' .'ZQ=='),base64_decode('YmFzZ' .'TY0' .'X2Rl' .'Y' .'29k' .'Z' .'Q=='),base64_decode('YmFzZT' .'Y' .'0X2Rl' .'Y' .'29kZQ=='),base64_decode('YmFzZTY0X2Rl' .'Y29k' .'Z' .'Q=='),base64_decode('' .'Y' .'m' .'FzZ' .'TY0X' .'2RlY29kZQ=' .'='),base64_decode('YmF' .'z' .'ZTY' .'0X2R' .'lY29kZQ' .'=='),base64_decode('YmF' .'zZTY0X2RlY29kZQ=='),base64_decode('YmFz' .'ZTY0X2RlY29kZQ=='),base64_decode('' .'Ym' .'FzZ' .'TY0' .'X2RlY2' .'9' .'kZ' .'Q=='),base64_decode('YmFzZT' .'Y0X2' .'R' .'lY29kZQ=='),base64_decode('YmFzZTY0' .'X2' .'RlY29kZ' .'Q=='),base64_decode('Ym' .'F' .'zZ' .'TY0X2' .'R' .'lY29kZQ=='),base64_decode('Ym' .'FzZTY' .'0X2RlY29kZ' .'Q=='),base64_decode('YmF' .'z' .'ZT' .'Y0X' .'2RlY29kZQ=='),base64_decode('YmFzZ' .'TY0X2RlY29kZQ=' .'='),base64_decode('YmFz' .'ZTY0X2Rl' .'Y29' .'kZQ=='),base64_decode('Y' .'mFzZTY' .'0' .'X2Rl' .'Y2' .'9kZ' .'Q=='),base64_decode('YmFzZ' .'T' .'Y0X2RlY2' .'9kZQ=='),base64_decode('YmFz' .'Z' .'T' .'Y0X2RlY29kZ' .'Q=='),base64_decode('YmFzZT' .'Y0X2RlY29' .'kZQ=' .'='),base64_decode('' .'YmFzZTY0X2RlY29kZ' .'Q=='),base64_decode('YmFz' .'ZTY0X2' .'RlY29kZQ=='),base64_decode('Ym' .'FzZ' .'TY0X' .'2R' .'l' .'Y2' .'9' .'kZQ=='),base64_decode('Ym' .'FzZT' .'Y0X2Rl' .'Y29kZQ=='),base64_decode('YmFzZTY0X' .'2RlY29' .'kZQ=='),base64_decode('YmFzZTY0X2' .'RlY29kZQ' .'=='),base64_decode('' .'Ym' .'F' .'zZT' .'Y0X2RlY29k' .'Z' .'Q' .'=='),base64_decode('YmFzZTY0' .'X' .'2R' .'lY2' .'9kZ' .'Q=='),base64_decode('' .'YmF' .'zZTY0X' .'2RlY29' .'kZQ=='),base64_decode('Y' .'m' .'Fz' .'ZTY0X2R' .'l' .'Y29kZQ=' .'='),base64_decode('Y' .'m' .'FzZ' .'TY0X2R' .'lY' .'2' .'9' .'kZQ=='),base64_decode('YmFz' .'ZTY0' .'X' .'2RlY29kZ' .'Q=='),base64_decode('YmFzZTY0X2' .'RlY' .'29kZQ=='),base64_decode('' .'YmFzZ' .'TY0X2RlY29' .'kZ' .'Q=='),base64_decode('Y' .'mFzZTY0X2R' .'l' .'Y29' .'kZQ=='),base64_decode('Y' .'mFzZ' .'T' .'Y0X2RlY29k' .'ZQ=' .'='),base64_decode('Y' .'mFzZTY0X2' .'RlY2' .'9k' .'ZQ=' .'='),base64_decode('Ym' .'FzZTY0X2RlY' .'29' .'kZQ=' .'='),base64_decode('YmFzZTY0X2R' .'lY29kZQ' .'=='),base64_decode('YmF' .'zZTY0X2RlY29k' .'ZQ=='),base64_decode('' .'YmFzZ' .'T' .'Y0X2' .'R' .'lY29kZQ' .'=='),base64_decode('YmFzZTY0' .'X2R' .'lY29kZQ=='),base64_decode('YmFz' .'ZTY' .'0X2' .'RlY29kZQ' .'=='),base64_decode('' .'YmF' .'zZTY0X2RlY29kZQ=='),base64_decode('Y' .'mF' .'zZTY0X2Rl' .'Y29kZQ' .'=='),base64_decode('Y' .'mF' .'z' .'ZTY0X2' .'RlY29kZQ=' .'='),base64_decode('Y' .'m' .'FzZTY0' .'X2RlY29kZQ=='),base64_decode('Y' .'mFzZTY' .'0X' .'2R' .'lY' .'29kZQ=='),base64_decode('Y' .'mFzZ' .'TY0X' .'2Rl' .'Y' .'29kZ' .'Q=='),base64_decode('YmF' .'zZTY0X2' .'RlY' .'29' .'kZQ' .'=='),base64_decode('' .'YmFzZTY0X2' .'RlY29kZQ=='),base64_decode('YmFzZTY0X2RlY29kZQ=='),base64_decode('YmFzZTY0' .'X2RlY' .'29k' .'Z' .'Q=='),base64_decode('Ym' .'FzZ' .'TY0X2RlY' .'29' .'kZ' .'Q=='),base64_decode('Y' .'mFzZTY0X2RlY29kZQ=='),base64_decode('YmF' .'z' .'ZTY0' .'X2RlY29' .'kZQ=='),base64_decode('YmF' .'zZTY0X' .'2R' .'lY29kZ' .'Q=='),base64_decode('YmFz' .'ZT' .'Y0X2' .'RlY29kZQ=' .'='),base64_decode('Y' .'mF' .'zZ' .'TY' .'0' .'X2R' .'lY' .'29kZQ=='),base64_decode('' .'YmFzZ' .'TY0X2' .'RlY' .'29' .'kZQ=='),base64_decode('Ym' .'F' .'zZTY' .'0X' .'2' .'RlY' .'29' .'kZQ=='),base64_decode('' .'Ym' .'F' .'zZ' .'TY0X' .'2RlY29' .'kZQ=='),base64_decode('' .'Y' .'mFzZTY' .'0' .'X' .'2' .'R' .'lY29kZ' .'Q=='),base64_decode('' .'YmFz' .'Z' .'TY0X2' .'RlY29kZQ' .'=='));
----
Do you want to allow execution? [y/N]


1-й eval расшифровали, нужный нам код находится между символами"----". Впоследствии после всех шагов нужно будет его скопировать в файл. Нажимаем Y и продолжаем расшифровывать.
2-й проход:
Script tries to evaluate the following string.
----
$GLOBALS['_223713416_']=Array($GLOBALS['_562306928_'][0]('YmFzZTY0' .'X2RlY29kZQ=' .'='),$GLOBALS['_562306928_'][1]('' .'YmFz' .'ZTY' .'0X2' .'RlY29' .'kZQ=='),$GLOBALS['_562306928_'][2]('Ym' .'F' .'zZTY0X2RlY29kZQ=='),$GLOBALS['_562306928_'][3]('YmFz' .'ZTY0X2' .'RlY2' .'9kZQ' .'=='),$GLOBALS['_562306928_'][4]('Ym' .'F' .'zZTY0' .'X2R' .'lY' .'29kZQ' .'=' .'='),$GLOBALS['_562306928_'][5]('YmFz' .'ZT' .'Y' .'0X2' .'RlY29k' .'ZQ=' .'='),$GLOBALS['_562306928_'][6]('YmFzZTY0X2RlY29kZQ=='),$GLOBALS['_562306928_'][7]('' .'YmFz' .'ZTY0X2RlY29kZQ=' .'='),$GLOBALS['_562306928_'][8]('' .'Y' .'mFzZT' .'Y' .'0X2RlY2' .'9kZQ=='),$GLOBALS['_562306928_'][9]('' .'Ym' .'FzZTY0' .'X2R' .'lY2' .'9kZQ=='),$GLOBALS['_562306928_'][10]('Y' .'m' .'Fz' .'ZTY0X2RlY29k' .'ZQ=' .'='),$GLOBALS['_562306928_'][11]('Ym' .'FzZTY0X2Rl' .'Y29k' .'ZQ=='),$GLOBALS['_562306928_'][12]('Y' .'m' .'Fz' .'ZT' .'Y' .'0' .'X2' .'R' .'lY2' .'9kZQ=='),$GLOBALS['_562306928_'][13]('YmF' .'zZTY0X2' .'RlY29kZQ=='),$GLOBALS['_562306928_'][14]('YmFzZTY0X' .'2' .'RlY29kZ' .'Q=='),$GLOBALS['_562306928_'][15]('' .'YmFz' .'ZTY0' .'X2RlY29kZQ=='),$GLOBALS['_562306928_'][16]('Ym' .'FzZT' .'Y0' .'X2R' .'lY' .'29' .'k' .'Z' .'Q=='),$GLOBALS['_562306928_'][17]('YmF' .'z' .'ZTY0X2RlY2' .'9kZQ=='),$GLOBALS['_562306928_'][18]('Y' .'mFzZ' .'TY0X2RlY29kZ' .'Q=='),$GLOBALS['_562306928_'][19]('' .'Ym' .'FzZTY0X2RlY' .'2' .'9k' .'ZQ=' .'='),$GLOBALS['_562306928_'][20]('YmFzZTY0X' .'2RlY29kZQ=='),$GLOBALS['_562306928_'][21]('' .'YmFz' .'ZTY0X2RlY29kZQ' .'=='),$GLOBALS['_562306928_'][22]('YmFzZTY0X2R' .'l' .'Y29k' .'Z' .'Q=='),$GLOBALS['_562306928_'][23]('Y' .'mFz' .'Z' .'TY0X2RlY' .'2' .'9kZQ=' .'='),$GLOBALS['_562306928_'][24]('' .'YmFzZTY0X2RlY29k' .'ZQ=' .'='),$GLOBALS['_562306928_'][25]('' .'Y' .'mFzZTY0' .'X2' .'R' .'lY29kZQ=' .'='),$GLOBALS['_562306928_'][26]('YmF' .'zZTY0X2RlY29kZQ=' .'='),$GLOBALS['_562306928_'][27]('Ym' .'F' .'zZTY0X2' .'R' .'lY29kZQ=='),$GLOBALS['_562306928_'][28]('YmF' .'zZTY' .'0X2' .'RlY2' .'9kZQ=='),$GLOBALS['_562306928_'][29]('YmFzZTY' .'0X2' .'RlY' .'29kZQ' .'=='),$GLOBALS['_562306928_'][30]('Y' .'mFzZTY0X2R' .'l' .'Y29kZ' .'Q=='),$GLOBALS['_562306928_'][31]('Y' .'mFzZTY0X2R' .'l' .'Y29kZQ=='),$GLOBALS['_562306928_'][32]('YmFz' .'ZTY0X' .'2RlY29kZQ=='),$GLOBALS['_562306928_'][33]('Y' .'mFzZTY0X2RlY29kZQ=='),$GLOBALS['_562306928_'][34]('YmFzZ' .'TY' .'0X2RlY29' .'kZ' .'Q=' .'='),$GLOBALS['_562306928_'][35]('YmFzZTY' .'0X2R' .'lY' .'29kZQ=='),$GLOBALS['_562306928_'][36]('Ym' .'FzZTY0X2RlY2' .'9kZQ=='),$GLOBALS['_562306928_'][37]('' .'Y' .'mFzZTY' .'0X2RlY29' .'kZQ' .'=='),$GLOBALS['_562306928_'][38]('Y' .'mFzZTY' .'0' .'X' .'2R' .'l' .'Y29kZQ=='),$GLOBALS['_562306928_'][39]('Ym' .'FzZT' .'Y0X' .'2RlY29k' .'ZQ=='),$GLOBALS['_562306928_'][40]('' .'YmFzZTY' .'0X2RlY2' .'9kZQ=='),$GLOBALS['_562306928_'][41]('Y' .'mFzZTY0X2RlY2' .'9kZQ=='),$GLOBALS['_562306928_'][42]('Ym' .'FzZTY0X2' .'Rl' .'Y' .'29kZQ=' .'='),$GLOBALS['_562306928_'][43]('' .'Ym' .'FzZ' .'TY0' .'X2' .'RlY' .'29' .'k' .'ZQ=='),$GLOBALS['_562306928_'][44]('YmFzZTY0' .'X2R' .'l' .'Y2' .'9kZQ=='),$GLOBALS['_562306928_'][45]('' .'Y' .'mF' .'zZTY0X' .'2Rl' .'Y' .'29' .'kZQ' .'=='),$GLOBALS['_562306928_'][46]('YmF' .'z' .'ZTY0' .'X' .'2RlY29' .'kZQ' .'=='),$GLOBALS['_562306928_'][47]('Ym' .'FzZTY' .'0X' .'2' .'RlY' .'29k' .'Z' .'Q=' .'='),$GLOBALS['_562306928_'][48]('Y' .'mFz' .'ZTY0X' .'2Rl' .'Y29k' .'Z' .'Q=' .'='),$GLOBALS['_562306928_'][49]('YmFz' .'ZT' .'Y0X2Rl' .'Y' .'29kZQ=' .'='),$GLOBALS['_562306928_'][50]('YmFzZTY0X2' .'R' .'lY29kZQ' .'=='),$GLOBALS['_562306928_'][51]('YmFzZTY0X2R' .'l' .'Y29kZQ=='),$GLOBALS['_562306928_'][52]('Y' .'mF' .'zZT' .'Y0X2Rl' .'Y29kZQ=='),$GLOBALS['_562306928_'][53]('YmFzZTY0X' .'2RlY2' .'9kZ' .'Q=' .'='),$GLOBALS['_562306928_'][54]('YmFzZTY0X2' .'RlY29kZQ=='),$GLOBALS['_562306928_'][55]('YmFzZTY' .'0X2' .'R' .'lY29kZQ=='),$GLOBALS['_562306928_'][56]('YmFzZTY' .'0X2RlY2' .'9k' .'ZQ=='),$GLOBALS['_562306928_'][57]('' .'YmFzZ' .'TY0X2Rl' .'Y29kZQ=='),$GLOBALS['_562306928_'][58]('' .'YmF' .'zZTY0X2RlY29kZ' .'Q=='),$GLOBALS['_562306928_'][59]('YmFzZTY0X2R' .'lY29' .'kZQ=='),$GLOBALS['_562306928_'][60]('Ym' .'FzZT' .'Y0X2Rl' .'Y29' .'kZQ=='),$GLOBALS['_562306928_'][61]('YmFzZT' .'Y0X2RlY29kZQ=='),$GLOBALS['_562306928_'][62]('' .'Y' .'m' .'FzZ' .'T' .'Y0X' .'2RlY' .'2' .'9kZQ=='),$GLOBALS['_562306928_'][63]('YmFzZTY0X2RlY29kZQ=='),$GLOBALS['_562306928_'][64]('Ym' .'F' .'zZTY' .'0X' .'2RlY' .'29kZQ=='),$GLOBALS['_562306928_'][65]('YmF' .'zZTY0X2R' .'lY29kZ' .'Q' .'=='),$GLOBALS['_562306928_'][66]('YmFzZ' .'TY0X2' .'R' .'lY' .'29kZQ=='),$GLOBALS['_562306928_'][67]('Ym' .'FzZTY0X2Rl' .'Y2' .'9kZQ=='),$GLOBALS['_562306928_'][68]('YmFzZ' .'TY0' .'X2RlY29kZQ=='),$GLOBALS['_562306928_'][69]('YmFzZTY0X2RlY29kZQ=='),$GLOBALS['_562306928_'][70]('Ym' .'Fz' .'ZT' .'Y0' .'X2RlY29kZQ=='),$GLOBALS['_562306928_'][71]('YmFzZTY0X2' .'RlY29k' .'Z' .'Q=='),$GLOBALS['_562306928_'][72]('YmF' .'zZTY' .'0X2RlY' .'29kZQ' .'=='),$GLOBALS['_562306928_'][73]('YmFzZTY0X' .'2' .'RlY2' .'9kZQ=' .'='),$GLOBALS['_562306928_'][74]('' .'Ym' .'FzZTY0X2R' .'lY29' .'kZQ=='),$GLOBALS['_562306928_'][75]('YmFzZTY0X' .'2RlY29kZQ' .'=='),$GLOBALS['_562306928_'][76]('Y' .'mFzZ' .'TY0X2R' .'lY29kZQ=' .'='),$GLOBALS['_562306928_'][77]('YmFzZTY0X2RlY29kZQ' .'=='),$GLOBALS['_562306928_'][78]('YmFzZT' .'Y0X2' .'RlY29kZQ=='),$GLOBALS['_562306928_'][79]('YmFzZTY0X2' .'RlY2' .'9kZQ=='),$GLOBALS['_562306928_'][80]('YmFzZTY0X2RlY29kZ' .'Q=='),$GLOBALS['_562306928_'][81]('Ym' .'F' .'zZ' .'TY0X2R' .'l' .'Y2' .'9kZQ=='),$GLOBALS['_562306928_'][82]('YmFzZ' .'TY0X2RlY29kZQ=='),$GLOBALS['_562306928_'][83]('YmF' .'zZTY0X2RlY' .'2' .'9kZQ=='),$GLOBALS['_562306928_'][84]('YmFzZT' .'Y0X2RlY' .'29kZQ=' .'='),$GLOBALS['_562306928_'][85]('Y' .'mFzZTY0X2RlY29kZQ=='));
----
Do you want to allow execution? [y/N]


3.
Script tries to evaluate the following string.
----
$GLOBALS['_888028985_']=Array($GLOBALS['_223713416_'][0]('' .'c3Ry' .'X' .'3JlcG' .'xhY2U='),$GLOBALS['_223713416_'][1]('' .'dW5s' .'aW' .'5r'),$GLOBALS['_223713416_'][2]('cHJl' .'Z' .'1' .'9t' .'YXRja' .'A=' .'='),$GLOBALS['_223713416_'][3]('bXlz' .'cWx' .'f' .'Y29u' .'bmVjdA=='),$GLOBALS['_223713416_'][4]('bX' .'lzcW' .'x' .'fZ' .'XJyb3I='),$GLOBALS['_223713416_'][5]('b' .'XlzcW' .'xfc2VsZWN0X2Ri'),$GLOBALS['_223713416_'][6]('bX' .'l' .'zcWxfZXJ' .'yb3I='),$GLOBALS['_223713416_'][7]('bXlzcWxfc' .'XVlcnk' .'='),$GLOBALS['_223713416_'][8]('b' .'X' .'lz' .'cWx' .'fcXV' .'lcnk='),$GLOBALS['_223713416_'][9]('bXlzcWxf' .'ZX' .'NjYXBlX3' .'N0cm' .'luZ' .'w=='),$GLOBALS['_223713416_'][10]('bXlzcWxfZX' .'J' .'y' .'b3I='),$GLOBALS['_223713416_'][11]('bXl' .'zc' .'WxfZmV0Y2hfYX' .'Nzb2M='),$GLOBALS['_223713416_'][12]('bX' .'l' .'zc' .'Wx' .'fcXVlcnk='),$GLOBALS['_223713416_'][13]('' .'bXl' .'zcW' .'xfZX' .'N' .'jYXBlX3' .'N0cmluZw=='),$GLOBALS['_223713416_'][14]('bX' .'lzc' .'WxfZX' .'J' .'y' .'b3I='),$GLOBALS['_223713416_'][15]('bXl' .'zcWx' .'faW5zZXJ0' .'X2lk'),$GLOBALS['_223713416_'][16]('Zmx1c' .'2g='),$GLOBALS['_223713416_'][17]('b2J' .'fZmx' .'1c2g='),$GLOBALS['_223713416_'][18]('Zmx' .'1c2g' .'='),$GLOBALS['_223713416_'][19]('Zmx' .'1c' .'2g='),$GLOBALS['_223713416_'][20]('b2JfZm' .'x' .'1c2g='),$GLOBALS['_223713416_'][21]('Zmx1c2g' .'='),$GLOBALS['_223713416_'][22]('bXl' .'zc' .'WxfY2' .'xvc2U='),$GLOBALS['_223713416_'][23]('cHJlZ19' .'tYXRj' .'aA=='),$GLOBALS['_223713416_'][24]('' .'cmFu' .'ZA=='),$GLOBALS['_223713416_'][25]('c3RyX3J' .'l' .'cGxhY' .'2U='),$GLOBALS['_223713416_'][26]('cHJlZ' .'19tYXRj' .'aF9hb' .'Gw' .'='),$GLOBALS['_223713416_'][27]('ZmlsZV9leGlzdHM='),$GLOBALS['_223713416_'][28]('dHJp' .'bQ=='),$GLOBALS['_223713416_'][29]('c' .'3RyaXBf' .'dGFn' .'cw=' .'='),$GLOBALS['_223713416_'][30]('bXlzcWxfY29' .'ubmVj' .'dA' .'=='),$GLOBALS['_223713416_'][31]('b' .'Xlzc' .'WxfZX' .'Jyb3I='),$GLOBALS['_223713416_'][32]('' .'b' .'X' .'lzcWxf' .'c2VsZWN0' .'X2' .'R' .'i'),$GLOBALS['_223713416_'][33]('bXlzc' .'WxfZXJyb3' .'I='),$GLOBALS['_223713416_'][34]('bXlzc' .'WxfcXVl' .'c' .'nk='),$GLOBALS['_223713416_'][35]('' .'bX' .'lz' .'cWxfc' .'XVlcnk' .'='),$GLOBALS['_223713416_'][36]('bXlzcWxfZXNjYX' .'BlX3N' .'0c' .'mluZw' .'=='),$GLOBALS['_223713416_'][37]('b' .'XlzcWxfZXJyb3I='),$GLOBALS['_223713416_'][38]('' .'bXlzcWxfY2' .'xvc2U='),$GLOBALS['_223713416_'][39]('bXlzcW' .'xfZmV0Y' .'2hfYXNzb2M='),$GLOBALS['_223713416_'][40]('' .'c3' .'V' .'ic3Ry' .'X2NvdW5' .'0'),$GLOBALS['_223713416_'][41]('Zm' .'x1c' .'2' .'g='),$GLOBALS['_223713416_'][42]('b2JfZ' .'mx1c2g='),$GLOBALS['_223713416_'][43]('Zmx' .'1' .'c2g='),$GLOBALS['_223713416_'][44]('dHJpbQ' .'=='),$GLOBALS['_223713416_'][45]('c' .'H' .'JlZ1' .'9tYX' .'RjaA=='),$GLOBALS['_223713416_'][46]('' .'dHJpbQ=='),$GLOBALS['_223713416_'][47]('cHJlZ' .'19tYXRjaA=' .'='),$GLOBALS['_223713416_'][48]('c' .'HJlZ19tY' .'XRjaA' .'=' .'='),$GLOBALS['_223713416_'][49]('cHJlZ19tYX' .'RjaF' .'9h' .'bGw' .'='),$GLOBALS['_223713416_'][50]('cH' .'JlZ19tYXRjaF9hbGw='),$GLOBALS['_223713416_'][51]('cHJlZ19tYX' .'R' .'jaA=='),$GLOBALS['_223713416_'][52]('' .'dHJpbQ=='),$GLOBALS['_223713416_'][53]('cH' .'JlZ' .'19yZX' .'BsYWNl'),$GLOBALS['_223713416_'][54]('c' .'HJlZ' .'1' .'9y' .'ZX' .'BsYWN' .'l'),$GLOBALS['_223713416_'][55]('c' .'HJ' .'lZ19tYXRj' .'aA=='),$GLOBALS['_223713416_'][56]('dGltZQ=='),$GLOBALS['_223713416_'][57]('ZmlsZV9w' .'dXRfY2' .'9u' .'dGVu' .'dHM='),$GLOBALS['_223713416_'][58]('' .'bXl' .'zc' .'WxfY2' .'9ubm' .'V' .'jd' .'A=='),$GLOBALS['_223713416_'][59]('b' .'XlzcWxf' .'ZXJyb3' .'I='),$GLOBALS['_223713416_'][60]('b' .'XlzcWxfc2' .'VsZW' .'N0' .'X' .'2Ri'),$GLOBALS['_223713416_'][61]('bXl' .'zc' .'Wx' .'fZXJyb' .'3I' .'='),$GLOBALS['_223713416_'][62]('bX' .'lzcW' .'xfc' .'XVlc' .'nk' .'='),$GLOBALS['_223713416_'][63]('bXlzcWxfZXNjY' .'XB' .'lX3N0cml' .'uZ' .'w' .'=='),$GLOBALS['_223713416_'][64]('' .'c' .'3' .'RyX3JlcG' .'xhY' .'2' .'U='),$GLOBALS['_223713416_'][65]('cmFuZA=='),$GLOBALS['_223713416_'][66]('bXlzcWxfcX' .'Vlcnk='),$GLOBALS['_223713416_'][67]('' .'bXlzc' .'W' .'x' .'fZXJyb' .'3I='),$GLOBALS['_223713416_'][68]('' .'bXlzcWxfa' .'W5zZXJ' .'0X2lk'),$GLOBALS['_223713416_'][69]('b' .'XlzcWxfcXVlcnk='),$GLOBALS['_223713416_'][70]('bX' .'lzcWx' .'fZm' .'V0' .'Y2h' .'fYXJ' .'yYXk='),$GLOBALS['_223713416_'][71]('bXlzc' .'Wxf' .'cXVlcnk='),$GLOBALS['_223713416_'][72]('' .'b' .'XlzcWxfa' .'W5zZ' .'XJ0' .'X' .'2lk'),$GLOBALS['_223713416_'][73]('b' .'Xl' .'zcWxfcXVl' .'cn' .'k='),$GLOBALS['_223713416_'][74]('bXlzcWxfZ' .'m' .'V0Y2' .'hfYXJ' .'yYXk='),$GLOBALS['_223713416_'][75]('bXlzcWxfcXV' .'l' .'cnk' .'='),$GLOBALS['_223713416_'][76]('bX' .'lzc' .'WxfaW5zZ' .'XJ0X2lk'),$GLOBALS['_223713416_'][77]('' .'bXlzcWxf' .'c' .'XVlcnk' .'='),$GLOBALS['_223713416_'][78]('' .'bXlzc' .'WxfcXVlc' .'nk='),$GLOBALS['_223713416_'][79]('bXlz' .'cW' .'x' .'fY2' .'x' .'v' .'c2U='),$GLOBALS['_223713416_'][80]('Zmx1c2g='),$GLOBALS['_223713416_'][81]('b2JfZm' .'x1' .'c2g='),$GLOBALS['_223713416_'][82]('' .'Zmx1c' .'2' .'g' .'='),$GLOBALS['_223713416_'][83]('Zm' .'x1c2g='),$GLOBALS['_223713416_'][84]('b' .'2J' .'fZmx' .'1' .'c2g='),$GLOBALS['_223713416_'][85]('Zmx' .'1c2g='));
----
Do you want to allow execution? [y/N]

4.
Script tries to evaluate the following string.
----
echo "<b>MarketGid</b><br />";$_GET['link']=$GLOBALS['_888028985_'][0]("%%","&",$_GET['link']);include('functions.php');@$GLOBALS['_888028985_'][1]('stop.txt');if($mainstop){die("<center>Приобрести полноценную версию Вы можете на сайте <a href='http://www.zuziken.ru'>www.zuziken.ru</a><br>По вопросам покупки обращайтесь в ICQ 315-625-299</center>");}if($_GET['link']== '')die('<b>Забыли ввести ссылку в форму.</b>');$p=get_page($_GET['link']);$GLOBALS['_888028985_'][2]('/<ul class="hmenu-1 clearfix hmactive-1">[^<]*<li class="tm-1"><span>(.+)<\/span><\/li>/isU',$p,$t);$cat_name=$t[1];$connect=$GLOBALS['_888028985_'][3]($host,$login,$password)or die($GLOBALS['_888028985_'][4]());$select_db=$GLOBALS['_888028985_'][5]($database,$connect)or die($GLOBALS['_888028985_'][6]());$GLOBALS['_888028985_'][7]("set names cp1251");$q=$GLOBALS['_888028985_'][8]("select `id` from `category` where `cat_name` = '" .$GLOBALS['_888028985_'][9]($cat_name) ."'")or die($GLOBALS['_888028985_'][10]());$cat_id=0;while($q_r=$GLOBALS['_888028985_'][11]($q))$cat_id=$q_r['id'];if($cat_id == 0){$GLOBALS['_888028985_'][12]("insert into `category` set `cat_name` = '" .$GLOBALS['_888028985_'][13]($cat_name) ."' ")or die($GLOBALS['_888028985_'][14]());$cat_id=$GLOBALS['_888028985_'][15]();echo "<b>Создана категория</b> <b>" .$cat_name ."</b><br>";$GLOBALS['_888028985_'][16]();$GLOBALS['_888028985_'][17]();$GLOBALS['_888028985_'][18]();}else{echo "<b>Данная категория уже есть. Пишем в нее.</b> <b>" .$cat_name ."</b><br>";$GLOBALS['_888028985_'][19]();$GLOBALS['_888028985_'][20]();$GLOBALS['_888028985_'][21]();}$GLOBALS['_888028985_'][22]($connect);if($GLOBALS['_888028985_'][23]('/>(\d+)<\/a><\/li>[^<]*<li><a href="[^"]*" target="_blank">следующая<\/a><\/li>/isU',$p,$t))$num_pages=$t[1];else $num_pages=2;$list_link=$_GET['link'];$i=1;$c=0;$letter=$GLOBALS['_888028985_'][24](1,20);$items_num=0;while($i<$num_pages){$k=$i*60;$cur_list_link=$GLOBALS['_888028985_'][25]('/0/','/' .$k .'/',$list_link);if($i != 1)$p=get_page($cur_list_link);$GLOBALS['_888028985_'][26]('/<h1><a href="(.+)".*>(.+)<\/a><\/h1>.*<p>(.*)<\/p>/isU',$p,$items,$o);foreach($items as $it){if($GLOBALS['_888028985_'][27]('stop.txt'))die('<b>Парсинг прерван по запросу пользователя.</b>');unset($res);$res['name']=$GLOBALS['_888028985_'][28]($GLOBALS['_888028985_'][29]($it[2]));$connect=$GLOBALS['_888028985_'][30]($host,$login,$password)or die($GLOBALS['_888028985_'][31]());$select_db=$GLOBALS['_888028985_'][32]($database,$connect)or die($GLOBALS['_888028985_'][33]());$GLOBALS['_888028985_'][34]("set names cp1251");$q=$GLOBALS['_888028985_'][35]("select `id` from `product` where `cat_id` = '" .$cat_id ."' and `name` = '" .$GLOBALS['_888028985_'][36]($res['name']) ."' ")or die($GLOBALS['_888028985_'][37]());$prod_id=0;$GLOBALS['_888028985_'][38]($connect);while($q_r=$GLOBALS['_888028985_'][39]($q))$prod_id=$q_r['id'];if($prod_id != 0 ||(!empty($_GET['key'])&&!$GLOBALS['_888028985_'][40]($res['name'],$_GET['key']))){echo "<font color='green'>" .$res['name'] .' - товар</font> <b>УЖЕ ЕСТЬ ИЛИ НЕ ПОДХОДИТ ПО КЛЮЧЕВОМУ СЛОВУ</b><br>';$GLOBALS['_888028985_'][41]();$GLOBALS['_888028985_'][42]();$GLOBALS['_888028985_'][43]();}else{$_url='http://goods.marketgid.com' .$it[1];$p=get_page('http://goods.marketgid.com' .$it[1]);$res['brief']=$GLOBALS['_888028985_'][44]($it[3]);$GLOBALS['_888028985_'][45]('/<span>Производитель:.*>([^>]+)<\/a>/iU',$p,$t);$res['proizv']=$GLOBALS['_888028985_'][46]($t[1]);if(!$GLOBALS['_888028985_'][47]('/Цена: <em>\$(\d+)<\/em>/iU',$p,$prices))$GLOBALS['_888028985_'][48]('/>\$([\d\.]+)</iU',$p,$prices);$res['price']=$prices[1];$GLOBALS['_888028985_'][49]("/<div class=\"box\" id=\"good-characteristic\">(.*?)<\/div>/",$p,$gh);$GLOBALS['_888028985_'][50]("/strong>(.*?)<\/strong>(.*?)\</",$gh[0][0],$hs);unset($hs2);foreach($hs[1]as $id=>$hn){$hs2[$hn]=$hs[2][$id];}$GLOBALS['_888028985_'][51]('/<div class="box" id="good-description">(.+)<\/div>/isU',$p,$t);$res['descr']=$GLOBALS['_888028985_'][52]($t[1]);$res['descr']=$GLOBALS['_888028985_'][53]('/<a.*>/iU','',$res['descr']);$res['descr']=$GLOBALS['_888028985_'][54]('/<\/a>/iU','',$res['descr']);$GLOBALS['_888028985_'][55]('/<td id="good-img"><img.*src="(.+)"/iU',$p,$t);$im=get_page1($t[1]);$l=$GLOBALS['_888028985_'][56]()+$c;$res['fname']=$letter .$l .'.jpg';$GLOBALS['_888028985_'][57]("images/" .$res['fname'],$im);$c++;$connect=$GLOBALS['_888028985_'][58]($host,$login,$password)or die($GLOBALS['_888028985_'][59]());$select_db=$GLOBALS['_888028985_'][60]($database,$connect)or die($GLOBALS['_888028985_'][61]());$GLOBALS['_888028985_'][62]("set names cp1251");foreach($res as $key=>$value){$res[$key]=$GLOBALS['_888028985_'][63]($value);$res[$key]=$GLOBALS['_888028985_'][64]("","",$res[$key]);}if(empty($res['price'])){if(!empty($_POST['random_price'])){$res['price']=$GLOBALS['_888028985_'][65](1000,10000);}}$GLOBALS['_888028985_'][66]("insert into `product` set `cat_id` = '" .$cat_id ."',
	                `name` = '" .$res['name'] ."',
	                `image` = '" .$res['fname'] ."',
	                `price` = '" .$res['price'] ."',
	                `url` = '" .$_url ."',
	                `brand` = '" .$res['proizv'] ."'          ")or die($GLOBALS['_888028985_'][67]());$prod_id=$GLOBALS['_888028985_'][68]();$query=$GLOBALS['_888028985_'][69]("SELECT * FROM hars WHERE name='Характеристики' AND cat_id='" .$cat_id ."'");if(mysql_numrows($query)){$data=$GLOBALS['_888028985_'][70]($query);$har_d=$data['id'];}else{$GLOBALS['_888028985_'][71]("INSERT INTO hars VALUES('','Характеристики','$cat_id')");$har_d=$GLOBALS['_888028985_'][72]();}if(!empty($hs2)){foreach($hs2 as $name=>$har){if(!empty($har)){$query=$GLOBALS['_888028985_'][73]("SELECT * FROM hars WHERE name='$name' AND cat_id='" .$cat_id ."'");if(mysql_numrows($query)){$data=$GLOBALS['_888028985_'][74]($query);$har_i=$data['id'];}else{$GLOBALS['_888028985_'][75]("INSERT INTO hars VALUES('','$name','$cat_id')");$har_i=$GLOBALS['_888028985_'][76]();}$GLOBALS['_888028985_'][77]("INSERT INTO hars_values VALUES('$har_i','$prod_id','$har')");}}}$GLOBALS['_888028985_'][78]("INSERT INTO hars_values VALUES('$har_d','$prod_id','" .$res['descr'] ."')");$GLOBALS['_888028985_'][79]($connect);echo "<font color='green'>" .$res['name'] ."</font><br>";$GLOBALS['_888028985_'][80]();$GLOBALS['_888028985_'][81]();$GLOBALS['_888028985_'][82]();$items_num++;if($_GET['num']!= ''and $items_num >= $_GET['num'])die('<b>Задача выполнена. Спарсено ' .$_GET['num'] .' товаров.</b>');}}echo "<b>Отпарсена страница " .$i ."</b><br><br />";$GLOBALS['_888028985_'][83]();$GLOBALS['_888028985_'][84]();$GLOBALS['_888028985_'][85]();$i++;}
----
Do you want to allow execution? [y/N]


Ну вот и всё, дальше продолжать нет смысла, потому что внутри нашего шифрованного файла, как видно по коду, includ'ится еще один зашифрованный файл, но мы его потом отдельно расшифруем. Главное правило сколько у нас eval, столько раз жмём Y, иначе наш скрипт выполнится вплоть до исполнения кода целиком, нам это не нужно.

Собираем полученное в один файл


Копируем содержимое всех расшифрованных eval (код между ----) в блокнот, я получил вот такую картину:
image

Чтобы не было всё в каше без пробелов пропустим это добро через php beautifier, дабы получить нормальные отступы.

Наш код уже становится похож на человечный


Далее, видим что вместо привычных нами функций, в файле определены глобальные переменные с их именами, чтобы нам расшифровать их имена, и не заниматься этим вручную, после последнего определения $GLOBALS['_888028985_'] = Array(… сделаем var_export, выглядеть будет примерно так:

$GLOBALS['_888028985_'] = Array(
	//...
	$GLOBALS['_223713416_'][82]('' . 'Zmx1c' . '2' . 'g' . '=') ,
	$GLOBALS['_223713416_'][83]('Zm' . 'x1c2g=') ,
	$GLOBALS['_223713416_'][84]('b' . '2J' . 'fZmx' . '1' . 'c2g=') ,
	$GLOBALS['_223713416_'][85]('Zmx' . '1c2g=')
);
var_export($GLOBALS['_888028985_']);die;
echo "<b>MarketGid</b><br />";

сохраним полученный код в тот же файл и выполним его просто через консоль (можно и в браузере):
php encoded_script.php

получаем заветные названия функций:
%php encoded_script.php
array (
  0 => 'str_replace',
  1 => 'unlink',
  2 => 'preg_match',
  3 => 'mysql_connect',
  4 => 'mysql_error',
  5 => 'mysql_select_db',
  6 => 'mysql_error',
  7 => 'mysql_query',
  8 => 'mysql_query',
  9 => 'mysql_escape_string',
  10 => 'mysql_error',
  11 => 'mysql_fetch_assoc',
  12 => 'mysql_query',
  13 => 'mysql_escape_string',
  14 => 'mysql_error',
  15 => 'mysql_insert_id',
  16 => 'flush',
  17 => 'ob_flush',
  18 => 'flush',
  19 => 'flush',
  20 => 'ob_flush',
  21 => 'flush',
  22 => 'mysql_close',
  23 => 'preg_match',
  24 => 'rand',
  25 => 'str_replace',
  26 => 'preg_match_all',
  27 => 'file_exists',
  28 => 'trim',
  29 => 'strip_tags',
  30 => 'mysql_connect',
  31 => 'mysql_error',
  32 => 'mysql_select_db',
  33 => 'mysql_error',
  34 => 'mysql_query',
  35 => 'mysql_query',
  36 => 'mysql_escape_string',
  37 => 'mysql_error',
  38 => 'mysql_close',
  39 => 'mysql_fetch_assoc',
  40 => 'substr_count',
  41 => 'flush',
  42 => 'ob_flush',
  43 => 'flush',
  44 => 'trim',
  45 => 'preg_match',
  46 => 'trim',
  47 => 'preg_match',
  48 => 'preg_match',
  49 => 'preg_match_all',
  50 => 'preg_match_all',
  51 => 'preg_match',
  52 => 'trim',
  53 => 'preg_replace',
  54 => 'preg_replace',
  55 => 'preg_match',
  56 => 'time',
  57 => 'file_put_contents',
  58 => 'mysql_connect',
  59 => 'mysql_error',
  60 => 'mysql_select_db',
  61 => 'mysql_error',
  62 => 'mysql_query',
  63 => 'mysql_escape_string',
  64 => 'str_replace',
  65 => 'rand',
  66 => 'mysql_query',
  67 => 'mysql_error',
  68 => 'mysql_insert_id',
  69 => 'mysql_query',
  70 => 'mysql_fetch_array',
  71 => 'mysql_query',
  72 => 'mysql_insert_id',
  73 => 'mysql_query',
  74 => 'mysql_fetch_array',
  75 => 'mysql_query',
  76 => 'mysql_insert_id',
  77 => 'mysql_query',
  78 => 'mysql_query',
  79 => 'mysql_close',
  80 => 'flush',
  81 => 'ob_flush',
  82 => 'flush',
  83 => 'flush',
  84 => 'ob_flush',
  85 => 'flush',
)%


Далее последняя стадия, замена всех функций из глобального массива ($GLOBALS['_888028985_']) на их настоящие аналоги.
Но для начала удалим все вспомогательные куски (те что идут до var_export($GLOBALS['_888028985_']);die;).
Как вы поняли обфускатор первые три eval'a использовал для 3х разового кодирования функций в глобальный массив $GLOBALS['_888028985_'], в четвертом eval'e все настоящие функции были заменены их псевдонимами из $GLOBALS['_888028985_'], поэтому нам нужно оставить только четвертый раскодированный код, первые три раскодированных куска, включая наш код для вывода ($GLOBALS['_888028985_']) нам больше не нужны.

Окончательная замена функций:


Есть два пути решения:
1) вручную поиск всех строк типа $GLOBALS['_888028985_'][...]() и замена их на соответствующий им ключ в расшифрованном массиве функций.
2) автоматом, я выбрал этот вариант, так как файлов было много, я написал простенький скрипт __decode.php для автозамены данных функций, привожу его код тут.

пример использования:
%php __decode.php encoded_script.php >> unencoded_script_full.php

в итоге в файле unencoded_script_full.php будет полностью искомый скрипт с нормальными функциями, полученный код смотреть здесь.

Кстати деобфускация помогла мне решить проблему, из-за чего не работал скрипт, но это уже другая история…

P.S. Естественно скрипты могут быть зашифрованы различными и более ухищренными способами и мой способ не панацея, я лишь показал логику дешифровки таких скриптов. Например некоторые обфускаторы могут всем переменным присвоить другие имена, и понять логику таких скриптов уже будет сложнее.

UPD от автора скрипта:
zuziken (20:30:15 2/02/2012)
*THUMBS UP*
zuziken (21:10:42 2/02/2012)
Спс за обзор, но код пишет программист, а не я:-)

еще и спасибо говорит ))

Использованные материалы:
Теги:
Хабы:
+90
Комментарии34

Публикации

Истории

Работа

PHP программист
157 вакансий

Ближайшие события