27.05.2014

Как декодировать некоторые вредоносы, закодированные в несколько уровней

image

Время от времени мы сталкиваемся с интересными вредоносными программами, которые так и просятся, чтобы их раскодировали и узнали о них больше. И вот сейчас настал как раз один из таких случаев.

Автор: Анте Крешич (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-команд на сервере.

Удобно, не правда ли?

или введите имя

CAPTCHA