Download_Link
Участник клуба
Как расшифровать обфусцированный PHP-скрипт
Очень часто непосвященные люди задают вопросы вроде "Как расшифровать обфусцированный PHP-скрипт?", "Хороша ли защита PHP-скрипта обфускатором?" и даже "Помогите деобфусцировать! Вам же не сложно?". Цель этой статьи - показать, что обфускаторы дают в 90% случаев никакущую защиту (которая способна защитить только от людей, увидевших язык программирования первый раз в жизни). Снять ее можно обычно минут за 10-20, получив исходный PHP-скрипт в первозданном виде.
Остальные 10% случаев - это немного усложненная защита, которая, впрочем, снимается теми же путями. Если вы желаете самостоятельно научиться снимать обфускацию со скриптов, то эта статья специально для вас!
Как я уже говорил выше, задача деобфускации PHP-cкриптов очень актуальна. Достаточно взглянуть на один популярный хак-форум:
Что ж, давайте по шагам разберем, как в большинстве случаев деобфусцируются скрипты на PHP. Возьмем пример прямо из темы на вышеупомянутом форуме с просьбами людей, не желающих разобраться самостоятельно либо думающих, что это невероятно сложно.
Для деобфускации нам потребуются руки, трезвая голова и Notepad++ (можно и другой редактор, желательно умеющий подсвечивать одинаковые подстроки в документе - это ускорит снятие обфускатора).
Для примера берем совершенно абстрактный, накрытый неизвестным мне, но в последнее время чрезвычайно популярным обфускатором, скрипт: original.php.
Сохраняем его в директорию нашего Web-сервера под именем original.php, а затем дублируем его же под другим именем, например, script.php. Позже я поясню, для чего это надо. Открываем скрипт и начинаем его изучение.
Видим, что сам скрипт по размеру небольшой, зато в конце файла, уже после скрипта, находится некий зашифрованный кусок текста. Видим также вызов инструкции PHP eval(), которая исполняет переданный ей PHP-код. Первым делом меняем eval на print, чтобы просмотреть, что же она выполняет. Дабы убедиться, что скрипт не натворит на нашем компьютере ничего плохого, просматриваем то, что идет выше - а это безобидный вызов urldecode(), несколько конкатенаций строк и присвоение значений паре переменных. Кроме того, перед вызовом eval() выполняется функция, имя которой хранится в переменной $OOO0000O0.
Проверим, что эта функция не делает чего-либо зловредного, для начала просто выведя ее имя и временно закомментировав строку с eval:
Обратите внимание, что редактирую я скрипт script.php, а оригинал original.php оставил без изменений. Обращаемся в браузере к скрипту script.php и видим вывод: base64_decode. Понятно, значит, перед вызовом eval() ничего плохого не происходит, и можно смело менять его на print():
Снова запускаем script.php через браузер и видим следующий вывод:
$O000O0O00=$OOO000O00($OOO0O0O00,'rb');$O0O00OO00($O000O0O00,0x49f);$OO00O00O0=$OOO0000O0($OOO00000O($O0O00OO00($O000O0O00,0x17c),'EnteryouwkhRHYKNWOUTAaBbCcDdFfGgIiJjLlMmPpQqSsVvXxZz0123456789+/=','ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'));eval($OO00O00O0);
Уже по этому неразборчивому коду можно догадаться, что он открывает какой-то файл на выполнение и что-то с ним делает (скорее всего, читает). Кроме того, тут появился очередной вызов eval(). Выведя значение переменной $OOO000O00 видим, что это не что иное, как имя функции fopen(). Какой же файл открывает данный код? Воспользуемся подсветкой Notepad++:
Видим, что это имя текущего файла, то есть script.php. Мы уже серьезно изменили этот скрипт, но можно же заставить код считывать оригинал, который мы заботливо припасли!
Далее, выводя содержимое переменной $O0O00OO00, убеждаемся, что это имя функции fread и файл действительно читается. Сначала считывается 0х49f байтов, которые никуда не сохраняются, а затем еще 0х17c, и вот с ними скрипт уже что-то делает. Чтобы определить, что именно он с ними творит, выводим как обычно содержимое переменных $OOO0000O0 (это base64_decode) и $OOO00000O (это strtr).
Таким образом, считанное содержимое сначала прогоняется через strtr(), а затем через base64_decode(). Проще говоря, производится раскодирование. А раскодированное содержимое затем пропихивается в eval(). Теперь мы его снова можем безболезненно заменить на print():
Снова исполняем через браузер script.php и видим очередную порцию кода:
$OO00O00O0=str_replace('__FILE__',"'".$OOO0O0O00."'",$OOO0000O0($OOO00000O($O0O00OO00($O000O0O00,$OO00O0000),'EnteryouwkhRHYKNWOUTAaBbCcDdFfGgIiJjLlMmPpQqSsVvXxZz0123456789+/=','ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/')));fclose($O000O0O00);eval($OO00O00O0);
Добавляем этот код в файл script.php и начинаем его разбирать:
С помощью подсветки Notepad++ (выделяя по очереди переменные с исковерканными именами) узнаем уже знакомую конструкцию base64_decode(strtr(fread())), только вот в fread теперь количество байтов для считывания указано неявно, но и это не проблема, ведь чуть выше оно пишется в переменную, которая и передается в fread:
$OO00O0000=0x2f24;
Здесь же явно вызывается str_replace, меняющая в считанной и декодированной строке все вхождения подстроки "__FILE__" на имя нашего файла. Значит, меняем замену на "original.php", как мы делали выше:
После всего этого мы видим вызов fclose - значит, с файлом делаться больше ничего не будет. Остается последний вызов eval(), который мы в очередной раз меняем на print():
И снова запускаем скрипт из браузера... Ура! Наконец-то мы получили исходный код скрипта! В нем немного исковерканы некоторые имена переменных, но это уже не проблема, так как мы видим исходный код!
Вот и все, скрипт расшифрован без проблем и сложностей! Таким методом, пошагово анализируя кусочки кода, которые нам встречаются, можно снять любую обфускацию, потратив на это не более получаса! Проведя такую работу несколько раз с разными типами обфускаторов и разными скриптами, вы научитесь распознавать их сразу по внешнему виду и расшифровывать буквально за 5 минут!
Стоит заметить, что в накрытых рассмотренным обфускатором скриптах не стоит ничего менять (в том числе и комментарии), потому что скрипт считывает сам себя, а смещения, используемые при считывании, жестко забиты в файл. Таким образом, если поправить начальный комментарий, например, укоротив его всего на 1 символ, мы превращаем скрипт в неработоспособный текстовик.
Также отмечу, что при деобфускации данного скрипта я производил множество лишних действий (для того, чтобы как можно более подробно показать пошаговый процесс снятия обфускатора), но все это можно проделать гораздо быстрее и оптимальнее, если немного знать, как устроен тот или иной обфускатор.
Для конкретных обфускаторов можно написать автоматический скрипт-деобфускатор, чтобы свести работу к минимуму.
В свое время я уже писал скрипт, позволяющий снимать конкретно такую обфускацию, и с радостью делюсь им с вами. Этот скрипт также умеет и снимать привязку (так как такой обфускатор, который я рассмотрел в статье, умеет делать привязку скрипта к конкретному домену).
Очень часто непосвященные люди задают вопросы вроде "Как расшифровать обфусцированный PHP-скрипт?", "Хороша ли защита PHP-скрипта обфускатором?" и даже "Помогите деобфусцировать! Вам же не сложно?". Цель этой статьи - показать, что обфускаторы дают в 90% случаев никакущую защиту (которая способна защитить только от людей, увидевших язык программирования первый раз в жизни). Снять ее можно обычно минут за 10-20, получив исходный PHP-скрипт в первозданном виде.
Остальные 10% случаев - это немного усложненная защита, которая, впрочем, снимается теми же путями. Если вы желаете самостоятельно научиться снимать обфускацию со скриптов, то эта статья специально для вас!
Как я уже говорил выше, задача деобфускации PHP-cкриптов очень актуальна. Достаточно взглянуть на один популярный хак-форум:

Что ж, давайте по шагам разберем, как в большинстве случаев деобфусцируются скрипты на PHP. Возьмем пример прямо из темы на вышеупомянутом форуме с просьбами людей, не желающих разобраться самостоятельно либо думающих, что это невероятно сложно.
Для деобфускации нам потребуются руки, трезвая голова и Notepad++ (можно и другой редактор, желательно умеющий подсвечивать одинаковые подстроки в документе - это ускорит снятие обфускатора).
Для примера берем совершенно абстрактный, накрытый неизвестным мне, но в последнее время чрезвычайно популярным обфускатором, скрипт: original.php.
Сохраняем его в директорию нашего Web-сервера под именем original.php, а затем дублируем его же под другим именем, например, script.php. Позже я поясню, для чего это надо. Открываем скрипт и начинаем его изучение.

Видим, что сам скрипт по размеру небольшой, зато в конце файла, уже после скрипта, находится некий зашифрованный кусок текста. Видим также вызов инструкции PHP eval(), которая исполняет переданный ей PHP-код. Первым делом меняем eval на print, чтобы просмотреть, что же она выполняет. Дабы убедиться, что скрипт не натворит на нашем компьютере ничего плохого, просматриваем то, что идет выше - а это безобидный вызов urldecode(), несколько конкатенаций строк и присвоение значений паре переменных. Кроме того, перед вызовом eval() выполняется функция, имя которой хранится в переменной $OOO0000O0.
Проверим, что эта функция не делает чего-либо зловредного, для начала просто выведя ее имя и временно закомментировав строку с eval:

Обратите внимание, что редактирую я скрипт script.php, а оригинал original.php оставил без изменений. Обращаемся в браузере к скрипту script.php и видим вывод: base64_decode. Понятно, значит, перед вызовом eval() ничего плохого не происходит, и можно смело менять его на print():

Снова запускаем script.php через браузер и видим следующий вывод:
$O000O0O00=$OOO000O00($OOO0O0O00,'rb');$O0O00OO00($O000O0O00,0x49f);$OO00O00O0=$OOO0000O0($OOO00000O($O0O00OO00($O000O0O00,0x17c),'EnteryouwkhRHYKNWOUTAaBbCcDdFfGgIiJjLlMmPpQqSsVvXxZz0123456789+/=','ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'));eval($OO00O00O0);
Уже по этому неразборчивому коду можно догадаться, что он открывает какой-то файл на выполнение и что-то с ним делает (скорее всего, читает). Кроме того, тут появился очередной вызов eval(). Выведя значение переменной $OOO000O00 видим, что это не что иное, как имя функции fopen(). Какой же файл открывает данный код? Воспользуемся подсветкой Notepad++:

Видим, что это имя текущего файла, то есть script.php. Мы уже серьезно изменили этот скрипт, но можно же заставить код считывать оригинал, который мы заботливо припасли!

Далее, выводя содержимое переменной $O0O00OO00, убеждаемся, что это имя функции fread и файл действительно читается. Сначала считывается 0х49f байтов, которые никуда не сохраняются, а затем еще 0х17c, и вот с ними скрипт уже что-то делает. Чтобы определить, что именно он с ними творит, выводим как обычно содержимое переменных $OOO0000O0 (это base64_decode) и $OOO00000O (это strtr).
Таким образом, считанное содержимое сначала прогоняется через strtr(), а затем через base64_decode(). Проще говоря, производится раскодирование. А раскодированное содержимое затем пропихивается в eval(). Теперь мы его снова можем безболезненно заменить на print():

Снова исполняем через браузер script.php и видим очередную порцию кода:
$OO00O00O0=str_replace('__FILE__',"'".$OOO0O0O00."'",$OOO0000O0($OOO00000O($O0O00OO00($O000O0O00,$OO00O0000),'EnteryouwkhRHYKNWOUTAaBbCcDdFfGgIiJjLlMmPpQqSsVvXxZz0123456789+/=','ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/')));fclose($O000O0O00);eval($OO00O00O0);
Добавляем этот код в файл script.php и начинаем его разбирать:

С помощью подсветки Notepad++ (выделяя по очереди переменные с исковерканными именами) узнаем уже знакомую конструкцию base64_decode(strtr(fread())), только вот в fread теперь количество байтов для считывания указано неявно, но и это не проблема, ведь чуть выше оно пишется в переменную, которая и передается в fread:
$OO00O0000=0x2f24;
Здесь же явно вызывается str_replace, меняющая в считанной и декодированной строке все вхождения подстроки "__FILE__" на имя нашего файла. Значит, меняем замену на "original.php", как мы делали выше:

После всего этого мы видим вызов fclose - значит, с файлом делаться больше ничего не будет. Остается последний вызов eval(), который мы в очередной раз меняем на print():

И снова запускаем скрипт из браузера... Ура! Наконец-то мы получили исходный код скрипта! В нем немного исковерканы некоторые имена переменных, но это уже не проблема, так как мы видим исходный код!

Вот и все, скрипт расшифрован без проблем и сложностей! Таким методом, пошагово анализируя кусочки кода, которые нам встречаются, можно снять любую обфускацию, потратив на это не более получаса! Проведя такую работу несколько раз с разными типами обфускаторов и разными скриптами, вы научитесь распознавать их сразу по внешнему виду и расшифровывать буквально за 5 минут!
Стоит заметить, что в накрытых рассмотренным обфускатором скриптах не стоит ничего менять (в том числе и комментарии), потому что скрипт считывает сам себя, а смещения, используемые при считывании, жестко забиты в файл. Таким образом, если поправить начальный комментарий, например, укоротив его всего на 1 символ, мы превращаем скрипт в неработоспособный текстовик.
Также отмечу, что при деобфускации данного скрипта я производил множество лишних действий (для того, чтобы как можно более подробно показать пошаговый процесс снятия обфускатора), но все это можно проделать гораздо быстрее и оптимальнее, если немного знать, как устроен тот или иной обфускатор.
Для конкретных обфускаторов можно написать автоматический скрипт-деобфускатор, чтобы свести работу к минимуму.
В свое время я уже писал скрипт, позволяющий снимать конкретно такую обфускацию, и с радостью делюсь им с вами. Этот скрипт также умеет и снимать привязку (так как такой обфускатор, который я рассмотрел в статье, умеет делать привязку скрипта к конкретному домену).