- PVSM.RU - https://www.pvsm.ru -

PHP / [Из песочницы] Деобфускация PHP кода

PHP / [Из песочницы] Деобфускация PHP кода

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

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

php-devel

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 "MarketGid
";$_GET['link']=$GLOBALS['_888028985_'][0]("%%","&",$_GET['link']);include('functions.php');@$GLOBALS['_888028985_'][1]('stop.txt');if($mainstop){die("Приобрести полноценную версию Вы можете на сайте www.zuziken.ru [1]
По вопросам покупки обращайтесь в ICQ 315-625-299");}if($_GET['link']== '')die('Забыли ввести ссылку в форму.');$p=get_page($_GET['link']);$GLOBALS['_888028985_'][2]('/

    [^<]*

  • (.+)
  • /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 "Создана категория " .$cat_name ."
    ";$GLOBALS['_888028985_'][16]();$GLOBALS['_888028985_'][17]();$GLOBALS['_888028985_'][18]();}else{echo "Данная категория уже есть. Пишем в нее. " .$cat_name ."
    ";$GLOBALS['_888028985_'][19]();$GLOBALS['_888028985_'][20]();$GLOBALS['_888028985_'][21]();}$GLOBALS['_888028985_'][22]($connect);if($GLOBALS['_888028985_'][23]('/>(d+)[^<]*

  • следующая
  • /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]('/

    (.+)

    .*

    (.*)

    /isU',$p,$items,$o);foreach($items as $it){if($GLOBALS['_888028985_'][27]('stop.txt'))die('Парсинг прерван по запросу пользователя.');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 "" .$res['name'] .' - товар УЖЕ ЕСТЬ ИЛИ НЕ ПОДХОДИТ ПО КЛЮЧЕВОМУ СЛОВУ
    ';$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]('/Производитель:.*>([^>]+)/iU',$p,$t);$res['proizv']=$GLOBALS['_888028985_'][46]($t[1]);if(!$GLOBALS['_888028985_'][47]('/Цена: $(d+)/iU',$p,$prices))$GLOBALS['_888028985_'][48]('/>$([d.]+)</iU',$p,$prices);$res['price']=$prices[1];$GLOBALS['_888028985_'][49]("/

    (.*?)

    /",$p,$gh);$GLOBALS['_888028985_'][50]("/strong>(.*?)(.*?)$hn){$hs2[$hn]=$hs[2][$id];}$GLOBALS['_888028985_'][51]('/

    (.+)

    /isU',$p,$t);$res['descr']=$GLOBALS['_888028985_'][52]($t[1]);$res['descr']=$GLOBALS['_888028985_'][53]('//iU','',$res['descr']);$res['descr']=$GLOBALS['_888028985_'][54]('//iU','',$res['descr']);$GLOBALS['_888028985_'][55]('/

    PHP / [Из песочницы] Деобфускация PHP кода$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 "" .$res['name'] ."
    ";$GLOBALS['_888028985_'][80]();$GLOBALS['_888028985_'][81]();$GLOBALS['_888028985_'][82]();$items_num++;if($_GET['num']!= ''and $items_num >= $_GET['num'])die('Задача выполнена. Спарсено ' .$_GET['num'] .' товаров.');}}echo "Отпарсена страница " .$i ."

    ";$GLOBALS['_888028985_'][83]();$GLOBALS['_888028985_'][84]();$GLOBALS['_888028985_'][85]();$i++;}
    ----
    Do you want to allow execution? [y/N]

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

    Копируем содержимое всех расшифрованных eval (код между ----) в блокнот, я получил вот такую картину:
    Чтобы не было всё в каше без пробелов пропустим это добро через 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 "MarketGid
    ";

    сохраним полученный код в тот же файл и выполним его просто через консоль (можно и в браузере):
    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. Естественно скрипты могут быть зашифрованы различными и более ухищренными способами и мой способ не панацея, я лишь показал логику дешифровки таких скриптов. Например некоторые обфускаторы могут всем переменным присвоить другие имена, и понять логику таких скриптов уже будет сложнее.Использованные материалы:
    rdot.org/forum/showthread.php?t=987 — статья по описанию работы Evalhook

    php-security.org/downloads/evalhook-0.1.tar.gz — собсно исходники evalhook 0.1

    www.php-crypt.com/demo/ — обфускатор, для тестов

    phpbeautifier.com — форматирование PHP кода в читабельный вид (ДЕ минимизатор)

    pastebin.com — публикация исходного кода

    Платный неработающий скрипт для парсинга маркетгид


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/news/1209

Ссылки в тексте:

[1] www.zuziken.ru: http://www.zuziken.ru