Pull to refresh

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

Reading time20 min
Views56K
Деобфускация 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)
Спс за обзор, но код пишет программист, а не я:-)

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

Использованные материалы:
Tags:
Hubs:
Total votes 120: ↑105 and ↓15+90
Comments34

Articles