Предыстория
Жил-был один старый-старый сайт. Родители от него отказались, и на втором десятке лет существования он попал к нам. Он представлял из себя джунгли PHP кода, разбросанного по папкам. Все это было написано в разное время, с использованием разных
<? if (cond) { ?>
в HTML разметке. Я провел не один час в увлекательных поисках нужного <? } ?>
Разработчики не забывали и про бэкапы: в корне можно было найти index.php, index_old.php, index.php.bak. Но несмотря ни на что, это чудо работало. А что работает — не трожь.Завязка
Эта история началась, когда солнечным декабрьским утром специалист по продвижению с удивлением обнаружил ссылки на чужеродные сайты в футере. Немного покопавшись выяснилось 2 вещи:
- это сапа;
- заказчик недоумевает.
Недоумение заказчика можно понять: у него этих ссылок не видно.
Расследование
Поставили задачу — найти, разобраться и уничтожить. Найдя искомое место в
![](https://habrastorage.org/getpro/habr/post_images/0e5/08d/2bd/0e508d2bda3c1644870beee4165c2310.png)
Ничего не понятно, но искреннее спасибо тому человеку, который не убрал аннотацию в шапке. Я начинаю гуглить ''Zend Oрtimizer'', справедливо полагая, что он приведет к расшифровке этого трэша. Поиск рабочего декодера заканчивается тут. Особо порадовала капча:
![](https://habrastorage.org/getpro/habr/post_images/83f/adb/703/83fadb7033b9018e0649f772c2e1957d.png)
С некоторым геморром, связанным с запретом копирования результата, я получил следующее:
![](https://habrastorage.org/getpro/habr/post_images/3ab/f8a/5d6/3abf8a5d6bde1328e8aeacf9cff5e926.png)
Я с недоверием отношусь к сложным регулярным выражениям, а тут и вовсе потух. Начинаю вспоминать как работает preg_replace(). И чем больше читаю, тем больше недоумеваю. Само регулярное выражение должно идти первым параметром, а во втором — то, на что заменяют. Посмотрел еще раз на то, что было дано. получается, в строке «x» заменяется "#x#e" на ту длинную штуку. Причем в функции preg_replace() используются модификаторы x и e. Но не дадим себя запутать: все, что помещено между # — экранируется, так что x - это на самом деле то, что следует заменить в строке «x» , т.е. все, а модификатор e позволяет исполнить результирующее выражение как PHP код. При внимательном взгляде на строку замены становится понятно, что большая ее часть — это шум.
![](https://habrastorage.org/getpro/habr/post_images/f89/c4b/331/f89c4b331c130928bde75035aa8f9d67.png)
Если убрать комментарии, получится
@eval(base64_decode($I0));
На этом месте мне пришлось погуглить значение "@" перед вызовом функции. Далее, спасибо онлайн декодерам, я получил следующую порцию загадок.![](https://habrastorage.org/getpro/habr/post_images/66f/336/d11/66f336d11ccc7f3fabdb10e0872603ec.png)
Тут я впервые увидел функцию chr(). Позалипал на
$ll = @explode(chr(187) , @implode('', @array_map('trim', @file($ll))));
Загуглил array_map(). В общем тут используется кусок из того самого первоначального файла, зашифрованного Zend Optimizer. Вот уж не знаю какой там алгоритм, но произведя перестановку символов и взяв уже становящийся привычным base64_decode() я получил крипто-функцию:![](https://habrastorage.org/getpro/habr/post_images/7dc/83d/20c/7dc83d20cbddbfa1ddeb84bad9475133.png)
Дальше ком стал разрастаться экспоненциально, и после нескольких итераций файл достиг 2к строк. Структуру файла после всего этого расследования я оставил на завтра, а пока пара забав:
![](https://habrastorage.org/getpro/habr/post_images/246/591/8ed/2465918ed2502fa3d75c61970c3a4969.png)
позволяет остаться незамеченными с терминалов внутренней подсети.
![](https://habrastorage.org/getpro/habr/post_images/393/325/48f/39332548fdec1b3eaec800e7058a6e0c.png)
Интересно, они там сразу делают шифровку такую, или это уже кто-то постарался спецом для нас?
Вместо послесловия
Если верить времени создания файлов — на дворе был суровый 2009. Только вот мне даже немного жаль времени тех людей, которые это все зашивали так упорно, потому как я уверен, что этот процесс занял у них времени поболее, чем обратный. И ведь всё это было бы невозможно, если бы только не осталась аннотация о Zend Optimizer.