Время от времени мы сталкиваемся с интересными вредоносными программами, которые так и просятся, чтобы их раскодировали и узнали о них больше. И вот сейчас настал как раз один из таких случаев.
Автор: Анте Крешич (Ante Kresic)
Время от времени мы сталкиваемся с интересными вредоносными программами, которые так и просятся, чтобы их раскодировали и узнали о них больше. И вот сейчас настал как раз один из таких случаев.
Недавно я столкнулся вот с таким самородком:
Рисунок 1: Закодированная часть вредоноса
На Рисунке 1 показано закодированное содержимое вредоносной программы. Полная «полезная нагрузка» намного больше (12816 символов, если быть точным). По крайней мере, на первый взгляд все выглядит интересно, и я решил шаг за шагом декодировать этот кусок.
1-й уровень кодирования
С какой же стороны подойти к решению этой задачи? Как всегда существует два пути. Простой путь – заменить функцию Eval() на функцию Echo. Сделав так, на выходе мы лишь получим расшифрованное содержимое, что слишком просто, и мы не узнаем ничего нового. Давайте повнимательнее рассмотрим этот код.
Первая строка – стандартный цикл, содержащий полезную нагрузку. Условие прекращения цикла выглядит немного забавно.
@ord($e[$o])
Функция ord возвращает ASCII-код в виде целочисленного значения на основе входного аргумента. Как же подобная конструкция может останавливать цикл? Все дело в том, что когда мы выбираем несуществующий символ в массиве, который представляет собой полезную нагрузку (например, когда мы выходим за границы массива), функция возвращает ошибку и цикл заканчивается. Следовательно, используя это условие, мы обойдем весь код полезной нагрузки.
Следующая пара строк представляется интересной:
if ($o < 16) {
$h[$e[$o]] = $o;
} else ...
Здесь создается массив, который будет содержать первые 16 символов полезной нагрузки, которые используются в качестве словаря.
После этого начинается декодирование полезной нагрузки:
...
else {
$d .= @chr(($h[$e[$o]] << 4) + ($h[$e[++$o]]));
}
...
Бит за битом мы декодируем полезную нагрузку и помещаем ее в переменную $d. Но как? Все выглядит так, что полезная нагрузка декодируется парами символов.
Первый символ полезной нагрузки, идущий после 16-ти символьного словаря, представляет первые 4 бита первого декодированного символа. Второй символ представляет последние 4 бита того же самого символа. Например, первый 2 символа полезной нагрузки – «,,», которые декодируются в символ «f».
После использования этой техники декодирования полезная нагрузка выглядит так:
Рисунок 2: Полезная нагрузка после первого уровня декодирования
На Рисунке 2 мы опять видим ту же самую схему кодирования.
2-й уровень кодирования
После декодирования первой части, используя технику, описанную выше, мы получаем нечто интересное. В переменной $d находятся двоичные данные. Затем в переменную $k заносятся данные от пользователя либо из cookie, либо из post/get запроса. После этого идет интересный код:
3-й уровень шифрования
Рисунок 3: Кусок кода, отвечающий за дешифровку данных
На Рисунке 3 мы видим объявление функции с именем «decrypt». Интересно, как она работает? J
После углубленного изучения вопроса мы пришли к выводу, что это функция предназначена для дешифровки XOR-шифрования. Повсюду криптография! Для того чтобы расшифровать вредонос нам нужен был ключ. Мы могли бы использовать частотный анализ и некоторые другие техники для нахождения ключа, но должен существовать более простой путь. Это отняло бы много времени, поскольку я не эксперт в этом вопросе.
Однако решение было найдено. Через гугл мы нашли статью на HackerNews, где был пароль, использовав который мы смогли полностью расшифровать вредонос.
Рисунок 4: Расшифрованный вредонос
Что же он делает? Этот вредонос позволяет загружать любой файл из интернета и сохранять его на сервере, на котором находится вредоносный скрипт. Кроме того, этот скрипт также можно использовать для запуска linux-команд на сервере.
Удобно, не правда ли?