23 September 2009

Шифрование отдельной части PHP-скрипта

Lumber room
Многие из тех, кто программируют на PHP, сталкивались с необходимостью шифрования своих скриптов в байткод для передачи на сторону. Слава богу, в наши дни существует огромный ассортимент PHP Encoder'ов, — как говорится, на любой вкус и цвет!

Мы же в своей работе столкнулись с нетривиальной задачей. Требовалось скрыть лишь некоторую часть кода, — функцию, содержимое которой не должен увидеть никто, кроме нас.

При этом нельзя зашифровать весь файл, так как все, кроме этой функции, должно быть на виду, чтобы технические специалисты принимающей стороны убедились в отсутствии «криминала» в скрипте. Вынести функцию в отдельный файл тоже нельзя, ибо мы должны быть убеждены, что md5 всего кода остался неизменным, а это значит, что необходима уверенность в неизменности первоначального вида как зашифрованной, так и видимой части скрипта.

Что делать? Первое, что пришло на ум — так называемые обфускаторы, то есть «запутывальщики» кода. При этом такой код может быть загружен без необходимости дополнительных модулей loader'ов для PHP, что является плюсом. Минусом же является то, что даже самый лютый обфускатор, который удалось найти, шаг за шагом ломался в течение 15-20 минут без излишней спешки.

На полке тем временем пылился старый добрый Zend Encoder 3.6. Понятно, что encoder'ом часть скрипта не зашифруешь, но задача требовала решения. Если посмотреть в получившийся зашифрованный файл, то можно обнаружить некоторую часть PHP-кода в начале каждого файла, а именно:

  1. <?php @Zend;
  2. 3272;
  3. /* This is not a text file! */
  4. print "\n";
  5. print "\n";
  6. print "&#38;lt;h1>Zend Optimizer not installed</h1>";
  7. print "This file was encoded by the Zend Encoder / Zend SafeGuard Suite\n";
  8. print "In order to run it, please install the freely available Zend Optimizer, version 2.1.0 or later.\n";
  9. print "<h2>What is the Zend Optimizer?</h2>
  10. ";
  11. print <<<EOM
  12. The Zend Optimizer is one of the most popular PHP plugins for performance-improvement, and has been freely available since the early days of PHP 4. It improves performance by taking PHP's intermediate code through multiple Optimization Passes, which replace inefficient code patterns with efficient code blocks. The replacement code blocks perform exactly the same operations as the original code, only faster.
  13. In addition to performance-improvement, the Zend Optimizer also enables PHP to transparently load files encoded by the Zend Encoder or Zend SafeGuard Suite.
  14. The Zend Optimizer is a freely-available product from Zend Technologies. Zend Technologies is the company that develops the scripting engine of PHP, also known as the Zend Engine.
  15. EOM;
  16. print "\n";
  17. exit();
  18. ?>
* This source code was highlighted with Source Code Highlighter.


Этот кусок создается на случай, если на сервере не установлен Zend Optimizer, и при загрузке любого шифрованного файла заявляет на весь мир, что пора бы задуматься о смене системного администратора :). Но нас больше привлекло другое. Что же это за загадочное «@Zend; \n 3272;» в первых строчках скрипта? Опытным путем установлено, что 3272 — это количество байт, заключенное между строчками «/* This is not a text file! */» и «exit();», умноженное на два. При этом конструкции типа «\n» и «<<<EOM» принимаются за 1 байт. Смысл ясен? Zend Optimizer'овский загрузчик просто пропускает N-ное количество байт в начале файла, после чего исполняет зашифрованный байткод.

Далее задача свелась к размещению основного («видимого») кода на место этой Zend Encoder'овской занавески и написанию лоадера, который бы исполнил «видимый» скрипт после основного зашифрованного.

Итогом стал вполне простой файл:
  1. function Secret() {
  2. // наша секретная функция
  3. }
  4. // загрузчик "видимого" скрипта:
  5. $script = "";
  6. $file = file($_SERVER["script_FILENAME"]);
  7. foreach($file as $k => $v) {
  8. if($k >= 3) {
  9. $script .= $v;
  10. if(substr($v, 0, 7) == "exit();") break;
  11. }
  12. }
  13. eval($script);
  14. exit;
* This source code was highlighted with Source Code Highlighter.


Далее мы шифруем этот файл и вместо Encoder'овской заглушки ставим нужный нам скрипт.

Осталось лишь подсчитать количество байт в нашем «видимом» скрипте, дабы правильно установить значение для Zend Optimizer'а во второй строчке файла (после «@Zend»). Было лень высчитывать его вручную, поэтому написали еще один скрипт с двумя циклами: в первом цикле создавалось некоторое количество копий файла с разными «около-правдивыми» значениями байт, а во втором все эти скрипты дергались wget'ом. Скрипт с правильным значением вернет 200-й заголовок вместо 500-го.

Все готово. Итоговый файл содержит «видимую» часть скрипта и байткод. Если сервер сконфигурирован с модулем Zend Optimizer'а, то при вызове скрипта сначала исполнится его зашифрованная часть, а после — та, которую мы не скрываем. В некоторых коммерческих задачах это действительно очень необходимо.
Tags:шифрованиеzend encoderобфускатор
Hubs: Lumber room
+21
1.1k 32
Comments 20