Blog. Just Blog

Обфускация строк на PHP

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Web-мастеру и не только | Автор: ManHunter
За несколько лет исследований различных кодировщиков и обфускаторов PHP-скриптов я изучил все используемые в них приемы сокрытия значений текстовых строк. Это могут быть названия функций или какие-то данные, которые должны быть представлены в виде строки. Так вот, во всех разобранных крипторах и обфускаторах символы в строке кодировались всего лишь несколькими способами: вариации преобразования строки из последовательности base64, декодирование из URL-encoded символов, escape-последовательности, упаковка строки в бинарные данные или результат функции chr по ординалу символа. Все подобные преобразования легко поддаются статическому анализу и декодированию типа замены по регулярным выражениям, то есть надежность сокрытия данных стремится к нулю.

В очередной раз экспериментируя с PHP, я решил на практике проверить, как поведет себя оператор инкремента и декремента в случае нецифровых значений. Согласно документации, при выполнении инкремента строковых переменных PHP следует соглашениям Perl, и рассматривает строку как условное число с базой значащих символов в диапазоне [a-z], [A-Z] и [0-9], причем одновременно. Проще всего это понять на следующих примерах:
  1. $a='K';
  2. $a++;
  3. echo $a;
  4. // L
  1. $a='a6';
  2. $a++;
  3. echo $a;
  4. // a7
Более интересные случаи для пограничных значений:
  1. $a='fZ9';
  2. $a++;
  3. echo $a;
  4. // gA0
  1. $a='ZZ';
  2. $a++;
  3. echo $a;
  4. // AAA
Постфиксный или префиксный инкремент тут значения не имеет, результат в обеих случаях одинаковый. При этом обратное действие, то есть декремент, как постфиксный, так и префиксный, на содержимое строки никак не влияет.

На служебные символы и символы, не относящиеся к латинскому алфавиту или цифрам, правило инкремента также не распространяется:
  1. // Декремент
  2. $a='ManHunter';
  3. $a--;
  4. echo $a;
  5. // ManHunter
  1. // Служебные символы
  2. $a='+#';
  3. $a++;
  4. echo $a;
  5. // +#
  1. // Кириллица
  2. $a='ПРИВЕТ';
  3. $a++;
  4. echo $a;
  5. // ПРИВЕТ
Исходя из вышеизложенного следует, что, используя начальное значение строки и определенное количество операций инкремента, мы можем сформировать абсолютно любую текстовую строку, состоящую из латинских символов и цифр. Обратите внимание, что конкатенация выполняется с одним и тем же символом "a", который затем при помощи операций инкремента подгоняется до нужного значения.
  1. $a='';
  2. $a.='a';
  3. $a++;
  4. $a.='a';
  5. $a++;
  6. $a++;
  7. $a.='a';
  8. $a++;
  9. $a++;
  10. $a++;
  11. $a.='0';
  12. $a++;
  13. echo $a;
  14. // bcd1
Это можно использовать при шифровании или обфускации PHP-скриптов. Кстати, ни в одном кодировщике или обфускаторе я подобные трюки не встречал. В качестве строк могут быть названия функций для их вызова через переменные или какие-либо критические значения, которые требуется скрыть. Более того, как следует из одного из приведенных примеров, при обработке строки с пограничными значениями "azz" при инкременте получится следущее:
  1. $a='azz';
  2. $a++;
  3. echo $a;
  4. // baa
На что похоже? Правильно, первые два символа равны началу названия функции PHP "base64_decode", третий символ подгоняется соответствующим количеством инкрементов символа до значения "s" и так далее. Это частный случай кодирования результирующей строки, в начале которой есть символы "a" и "b", его мы будем использовать в следующем примере.

В качестве "боевого" примера, название функции "base64_decode" можно превратить вот в такое адское месиво, совершенно неподъемное для статического анализатора:
  1. // base64_decode
  2. $_=($__=@a).($___=@z).$___;++$_;$_++;$_++;$_++;++$_;$_++;$_++;++$_;++$_;$_++;$_++;
  3. ++$_;$_++;++$_;$_++;$_++;$_++;++$_;$_++;$_.=$__;++$_;$_++;++$_;$_.=@+_;++$_;$_++;
  4. $_++;$_++;++$_;$_++;$_++;++$_;++$_;$_++;$_++;++$_;$_++;++$_;$_++;++$_;$_.=@+_;
  5. $_++;++$_;$_++;++$_;$_.=@_;$_.=$__;$_++;++$_;$_++;$_.=$__;$_++;++$_;$_++;$_++;
  6. $_.=$__;$_++;++$_;$_.=$__;$_++;$_++;++$_;++$_;$_++;++$_;$_++;$_++;++$_;$_++;$_++;
  7. ++$_;$_++;$_++;$_.=$__;++$_;$_++;$_++;$_.=$__;$_++;++$_;$_++;++$_;
  8.  
  9. eval($_('ZWNobyAnSGVsbG8sIHdvcmxkISc7'));
А если разбавить этот код мусором с префиксным и постфиксным вычитанием, которое, как я уже сказал, фактически никак не будет влиять на содержимое строки, то получится вполне неплохой обфускатор для сокрытия произвольных текстовых строк. Конечно, при таком способе кодирования объем исполняемого кода заметно увеличивается, но использование компрессии и защита только критических данных позволяют решить эту проблему. Да и вообще, в наше время скриптами на многие сотни килобайт уже никого не удивить.

Пока что все изложенное остается в состоянии "proof of concept" и теоретических выкладок, но не исключено, что я изготовлю и собственный криптор для PHP-скриптов. Повторюсь, что подобных способов обфускации строк "в дикой природе" я пока не встречал.

Поделиться ссылкой ВКонтакте
Просмотров: 3701 | Комментариев: 10

Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
stream (12.04.2021 в 12:41):
+100500
Алексей (20.07.2019 в 15:52):
Все бы хорошо, НО если убрать последний инкремент "++$_;" и вывести код, то название функции становится очевидным. В итоге быстро узнаем функцию которой закодирован код, но реализация красивая!
morgot (01.01.2019 в 12:20):
Идея очень интересная, спасибо.
proba (09.12.2016 в 12:44):
В общем, мне понравилось. :-) Возьму на вооружение.
ManHunter (09.12.2016 в 11:06):
Декремент используется просто в качестве мусора.
proba (09.12.2016 в 11:00):
echo "Hello World!";

Смущали "заморочки" подобные create_function, md5, mcrypt_create ..., но замена eval на echo спасало положение. Декремент расставляется произвольно или есть какая-то последовательность всё же?
ManHunter (14.09.2016 в 09:08):
Так никто и не разобрался с кодировщиком? Или очень сложно, или нахрен никому не нужно. Предполагаю второй вариант.
ManHunter (07.09.2016 в 17:09):
Пример зашифрованного hello world: http://rgho.st/private/6rYgNpz...9a7b4b9e31f9
Обфускации исходного текста скрипта нет, только шифрование. Разобрать, конечно, можно, но займет время. На паблик этого криптора, скорее всего, не будет.
ManHunter (07.09.2016 в 00:21):
Не вижу связи между паранойей и крипторами.
Станислав (06.09.2016 в 19:03):
Как главный параноик буду ждать с нетерпением криптор...

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.1 сек. / MySQL: 2 (0.0073 сек.) / Память: 4.5 Mb
Наверх