Главная » Хабрахабр » История одного вскрытия: как мы ревёрсили Hancitor

История одного вскрытия: как мы ревёрсили Hancitor

В дикой природе загрузчик Hancitor еще встречается в своей естественной среде обитания — спам-рассылках. Для тех, кто уже наигрался с задачками crackme, мы подвезли свежего троянца. В настоящее время он активно используется для прогрузки банковского трояна Panda, который является модификацией небезызвестного Zeus.

Если любите смотреть, что там у вредоносов «под капотом», почитайте наш новый реверс-разбор.
Наш вредоносный документ выглядит так: В один холодный летний вечер мы встретились с ним лицом к лицу, просматривая почтовый спам.

Однако содержимое письма уверяет, что макросы следует включить. По умолчанию запуск макросов блокируется, поэтому система предупреждает: «Макросы были отключены». После нажатия на кнопку Enable Content («Включить») происходит инфицирование компьютера. Что ж, давайте сделаем это. Это можно сделать сразу в ворде, перейдя на вкладку View->Vacros\View Macros. А теперь посмотрим, что за макрос выполняется и как именно происходит заражение.

Установить пакет можно там же по ссылке. Можно поступить более профессионально – заюзать olevba из пакета oletools. Далее набираем olevba doc_file –c –decode >source.txt и получаем исходник макроса.

Скрипт просто выкачивает откуда-то малвару. По коду сразу хочется сказать, что троян относится к классу даунлоадеров. Нам удобнее делать это сразу через hiew, чтобы сто раз не копипастить. Чтобы это доказать, давайте раскодируем base64 строки. Вот что получилось: Для этого мы используем специальный плагин, который описан тут.

В принципе нам особо не интересно, как он работает. Это вредоносный скрипт, разбитый на две части и сохраненный, как 1.hta. Единственный важный момент – определить URL, по которому происходит скачивание вредоносного файла. Тут всё довольно банально. Они могут добавить сетевые правила на блокировку запросов по таким URL, что может спасти компанию от заражения. Давайте его попробуем найти, так как эта информация может быть полезна безопасникам.

Ссылок никаких нет. Ха! Пришло время ещё раз взглянуть на наш доковский файл в hiew, но уже внимательнее: Но откуда тогда берётся файл 6.exe, который запускается 1.hta?

Да ещё и сильно упакованный. Да, в доковском документе встроен exe-шник. Макрос дропает вредоносный скрипт 1.hta в папку Temp и запускает его, а 1.hta запускает в свою очередь 6.exe из своей директории. Поясним, что происходит. Но нам сейчас интересно, как 6.exe дропается в %temp%. Ясное дело, что 6.exe – это тот самый запакованный PE-шник, который мы видим на скрине. Дело в том, что в любой OLE — документ может быть встроен любой другой файл в формате Ole10Native. А происходит это из-за интересной особенности в пакете Microsoft Office.

Давайте глянем на этот объект. Если это так, то MS-Office при запуске сам дропает встроенный таким образом файл в папку %temp% под именем, указанным в заголовке структуры Ole10Native. Открываем в плагине наш вредоносный документ, переходим в каталог ObjectPool\ _1593522492 и видим вот что: Нам помог плагин к FAR-manager – OLE2Viewer.

Скопируем этот файлик (Ole10Native) и откроем в hiew.

А теперь вернёмся к нашему макросу. Тут мы видим под каким именем дропнется в папку %temp% наш OLE-объект – 5c.pif. Его задача – запустить дропнутый exe-шник.

На самом деле, если быть точным, то макрос запускает дропнутый файл не всегда через 1.hta, а ещё и так: Shell «cmd.exe /c  ping localhost -n 100 && » & Environ(«Temp») & "\6.pif", vbHide

А зачем тогда нужен ping localhost -n 100? Способ запуска, как мы видим, зависит от присутствия следующих процессов в системе: bdagent.exe и PSUAMain.exe. Обычно его вариации используется для самоудаления. А это древнегреческий трюк для создания искусственной задержки, на всякий случай.

Нам стало ясно, что сам документ не относится к ВПО типа Trojan-Downloader, как казалось на первый взгляд, а подходит к типу Trojan-Dropper. На данном этапе мы разобрали схему работы вредоносного документа. Вот что получилось при запуске:

Мы уже поняли, что наш троян упакован, поэтому мы должны его сначала распаковать. Сейчас осталось разобрать сам payload. Снятие распакованного дампа + восстановление таблицы импорта.
2. Обычно этот процесс делится на две стадии:
1. Анализ и чистка глобальных переменных.

К примеру, CreatHeap вернёт нам дескриптор кучи, который далее будет использоваться для работы. Второй этап нужен нам потому, что существует множество API-функций, которые в результате своей работы нам возвращают неповторяющиеся значения. Но на момент снятия дампа переменная, содержащая данный дескриптор, была уже им инициализирована и в тот момент дескриптор был валиден. Очень часто в коде есть проверки типа: если дескриптор кучи == 0, то получить дескриптор кучи, иначе использовать уже инициализированный. Когда мы попробуем запустить снятый дамп, переменная с нашим дескриптором будет содержать старое значение, т.е не равное 0, а значит пройдёт проверку.

Так вот, чтобы такого не было, нужно эти переменные занулить. После этого, как только программа попытается использовать этот дескриптор, ОС бросит исключение, и программа вывалится с ошибкой. Наверное вы предложите открыть в hex-редакторе данную секцию и всё затереть нулями? Обычно они находятся в секции данных, доступной на запись. Есть такие трояны, которые производят проверку переменных не на 0, а на рандомный DWORD. Вы отчасти правы, но не стоит совершать необдуманных действий. За примерами далеко ходить не надо. И в зависимости от того, проходит проверка или нет, предпринимаются различные действия. Достаточно взглянуть на Cridex (в последнее время куда-то исчез с радаров, видимо, полностью проапгрейдился до EMOTETA).

Ещё желательно, чтобы трафик, который будет выходить из виртуальной машины, шел через VPN. Итак, давайте запустим наш семпл (на виртуальной машине, естественно).

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

Эта утилита не только находит все скрытые исполняемые модули и дампит их, но ещё и сама восстанавливает таблицу импорта. Для дампа используем замечательную утилиту – Process Dump, которую можно взять тут. После чего, утилита сдампит все модули процесса. Утилиту нужно запускать от имени администратора таким образом: pd /pid xxxx, где xxxx – id троянского процесса. Мы удалили лишние и вот что осталось:

Оказывается, по адресу 0x2C0000 находился распакованный троян. Имя исполняемого файла троянского процесса – 1.exe. Откроем его в hiew:

Теперь файл распакован, это отчётливо видно. Просто радуется глаз! Давайте откроем его в IDA-PRO. Таблица импортов также распозналась.

Первое, с чего начинает работу троян, — определяет адрес загрузки своего модуля. Некоторые функции мы уже переименовали, пока разбирали сэмпл. Делается это старой проверенной техникой – отлистыванием страницы памяти назад по 0x1000 относительно текущего адреса до тех пор, пока не наткнёмся на байты «MZ». И действительно: откуда ему знать по какому адресу его stub распаковал? Проверьте сами. Это работает, потому что исполняемые модули всегда загружаются ОС по адресу, кратному 0x1000. В нашем случае установлен лимит на 100 отлистываний.

Если кто не понял, где тут отлистывание назад, то вот где:
result += 0xFFFFF000 эквивалентно result -= 0x1000.

Для начала ищутся адреса двух функций – LoadLibraryA и GetProcAddress. После получения адреса загрузки своего модуля распакованный троян получает адреса нужных для своей работы функций. Эти функции находятся в библиотеке kernel32. Зная адреса этих функций, можно с помощью них получить все остальные. Указатель на список вытаскивается из PEBа. Её адрес получается с помощью чтения первого (нулевой — ntdll, первый kernelbase и тд) элемента кольцевого списка, описывающего все загруженные в порядке инициализации модули структурой _LDR_DATA_TABLE_ENTRY.

Получив адрес kernel32.dll (начиная с  Windows 7 – kernelBase.dll), троян может вручную распарсить её таблицу экспорта и найти нужные две функции, что предсказуемо выполняется в подпрограмме sub_EF1E60.

Теперь взглянем на функцию, которую мы назвали getHeap.

На момент дампа переменная hHeap содержала значение 600000h. Тут мы наблюдаем как раз ту ситуацию, которую описывали выше. Вместо этого программа перейдёт на метку loc_EF11DD, где вызовется HeapAlloc с невалидным дескриптором, что даст нам ошибку. Поэтому GetProcessHeap не вызовется. Подобных мест мы насчитали шесть. Поэтому, берём hex редактор и зануляем это число.

Троян генерирует уникальный ID «клиента», на основании серийного номера жёсткого диска и MAC адреса. Далее у нас начинается самое интересное. Информация получена здесь:

На основании всего этого формируется HTTP-запрос к админке, адрес которого мы пока не знаем. Также получаем следующее: IP адрес, версия ОС, сетевое имя и имя пользователя. А нет его там, потому, что он зашифрован в конфиге. В строках его нет (даже в распакованном виде). Его адрес можно вытащить из кода:

Конфиг весит 0x2008 байт и имеет такой формат: первые 8 байт – RC4 ключ, 0x2000 байт – зашифрованные данные.

То, что используется алгоритм шифрования RC4, становится понятно из следующего листинга:

Ключом является хеш SHA1 от этих байт. Обратите внимание, что первые 8 байт сами по себе не являются ключом к RC4. В MSDN есть оговорка по поводу данного флага: Также нужно обратить внимание на флаг 0x280011 к функции CryptDeriveKey.

Т.е в байтах размер ключа такой: (0x280011 >> 16) / 8 = 5. Из неё становится понятно, что старшие 16 бит этого флага задают размер ключа в битах. Сдампим конфиг и напишем скрипт на python, который расшифрует нам его. Поэтому ключом будут являться первые пять байт от хеша от первых восьми байт конфига. Скрипт выглядит так:

Откроем его в hiew: Результатом его работы стал файл config.rc4.

Первое слово – «19nep07» — номер билда. Мы видим расшифрованный список админок. Далее идёт список URL админок, разделённых "|". Под него отведено 16 байт.

0. Итак, первое обращение к админке будет иметь такой формат:
GUID=3068075364164635648&BUILD=19nep07&INFO=WIN-56G04BL06SL @ WIN -56G04BL06SL\Reverse&IP=35. 52&TYPE=1&WIN=6. 127. 1(x32

Потом сформированный запрос отправляется первой в списке админке.

Ответ должен быть в кодировке base64. Далее считывается ответ от админки, конечно, если она еще живая. Иногда живые админки возвращают странный ответ: Если это не так, то берётся следующая админка из списка.

Да это же те самые числа! Знакомо, не правда ли? В нормальном виде возвращается команда. На самом деле одному автору известно, почему админка их начинает возвращать! Раскодированный файл дополнительно расксоривается на 0x7A: К сожалению, с полной уверенностью нельзя сказать, какой будет формат ответа, так как трафика нет, все админки дохлые.

Если её нет, происходит обращение к следующей админке. Ответ должен содержать команду. Всего их 7: ‘r’,’l’,’e’,’b’,’d’,’c’,’n’. Код команды кодируется как «x:», где x – буква кодирующая определённую комманду. Рассмотрим команды «b» и «r».

Мы ее назвали, как GetExe. В обработчиках этих команд есть одна и та же функция. Вот как она выглядит:

Троян совершает http-запрос и ему возвращается в ответе исполняемый файл в сжатом виде, который потом расжимается. Думаю тут всё ясно. В случае с командой «b», происходят следующие три действия: После чего возможны вариации.

Создание процесса svchost в замороженном виде 1.

Инжект в адресное пространство процесса скачанного модуля 2.

Передача управления на заинжекченный модуль 3.

Скачивание исполняемого файла вызовом функции GetExe.
2. В случае с командой «r», происходят следующие три действия:
1. Запуск дропнутого файла. Сохранение скачанного файла в темповскую папку под случайным именем.
3.

Done.

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


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

Конференция «Контентинг» — теперь с поддержкой hyper-threading

Друзья, на связи контент-студия Хабра. 29 ноября мы проводим собственную конференцию про контент и авторов. Будем учить, вдохновлять и рассказывать, как лучше, — в два синхронных потока докладов и дискуссий. Спикеры — эксперты в области контент-маркетинга, которые годами нарабатывали и тестировали ...

J2CL — Лучше поздно, чем никогда

Ещё никому не удалось опоздать на свои похороны.Валентин Домиль Идея трансляции Java в JavaScript далеко не нова, и все уже давно набили шишек с Google Web Toolkit, однако этот продукт сообщество ждало как ни один другой — о нем говорили ...