Trojan-Downloader.Win32.Cabby.cemx — Часть вторая — Функционал
В предыдущей части разобрали и сняли первый слой обороны зловреда. Сделали дамп процесса после расшифровки основного кода, сохранив его в отдельном исполняемом файле.Настало время разобраться с логикой и смысловой нагрузкой самого Downloader’а.
Сетевая активностьЭкспресс анализ сетевой активности показал, что зловред перебирает по списку несколько ресурсов и скачивает с первого доступного некий «efax.jpg». Вот пример запроса: Скачаем .jpg и посмотрим внутренности данного файла — беспорядочный набор байтов. Ни сигнатуры JPG «FF D8», ни каких-либо строк. Снова шифрованные данные? Разберемся позже.Восстановление API Практически в самом начале листинга утыкаемся в процедуру 0×0040214C. Она восстанавливает адреса API функций, необходимых для исполнения кода Downloader’а.Весь листинг процедуры приводить смысла нет — слишком громоздкий и однотипный. В самом начале расшифровываются строки с именами DLL, после чего эти DLL подключаются с помощью LoadLibrary, а указатели на них сохраняются в стек: Далее, используя полученные указатели и расшифрованные имена необходимых API, с помощью GetProcAddress находятся адреса необходимых API и сохраняются в переменных.Это вся смысловая нагрузка данной процедуры.Единственное, что можно рассмотреть подробнее — процедуру расшифровки строковых переменных.Пример ее использования: Внутренности самой процедуры: Расшифровка побайтная, ключ 16 байт. Если строка больше 16 байт, ключ циклически повторяется.Обманка для пользователя Сразу после восстановления необходимых API идет выделение трех 512 байтовых буферов. Будем следить за ними.Далее один из буферов используется для сохранения пути к директории %Temp% полученного с помощью GetTempPath. Возьмем на заметку…Немного ниже расшифровывается строка имени ресурса с помощью разобранной выше процедуры 0×00402F4F, находится его смещение и сохраняется в директорию %Temp%, как архив .cab. Имя архива генерируется случайным образом процедурой 0×00401EE8.Пример создания файла: Запись данных из ресурсов в новый файл: Из созданного в %Temp% .cab архива извлекается файл .rtf с именем файла, как у исполняемого модуля, после чего запускается для показа пользователю: Антиэвристика? После распаковки и запуска .rtf отмечаем относительно приятное открытие — данную процедуру: Вызов находится по смещению 0×00401D04.В самом начале GetTickCount возвращает количество миллисекунд с момента старта системы, после чего идет цикл со Sleep и вторым запросом GetTickCount. Далее из последнего результата вычитается самый первый, а полученная дельта сравнивается с константой 0×668A0. Переводим константу в десятичную, получаем 420000, или 7 минут. Почему открытие приятное? Да потому, что после открытия .rtf можно просто завершить процесс в течении 7 минут и забыть про CTB-Locker (хотя, наверно, кто может заподозрить процесс в подозрительных действиях и завершить его просто не будет даже запускать неизвестное вложение). Возможно это time-атака на эвристики некоторых антивирусов.Для реверсинга это не особо приятный момент, т.к. не очень хочется ждать 7 минут каждый раз, когда приходится рестартовать процесс. Поэтому поменяем константу на 1 секунду и забудем про этот таймер, вот так: Загрузка JPG Подошли к фрагменту, который загружает из сети упомянутый в самом начале .jpg. Существует цикл, который рандомно выбирает указатель на зашифрованную строковую переменную (URL), расшифровывает разобранной выше процедурой, передает URL в процедуру загрузки (ее разбирать не будем, ничего интересного — стандартное формирование запроса на web-сервер), снова шифрует URL той же процедурой. После описанных действий ответ от web-сервера передается в процедуру 0×00402019, в самом начале которой по объему принятых данных определяется был ли получен файл или пустой ответ от сервера, после чего принимается решение продолжить цикл перебора URL или расшифровать принятый файл.Первый запрос всегда идет на «sintjoep.nl/images/efax.jpg», причем никак не проверяется ответ от сервера и сразу начинается цикл перебора остальных URL. Непонятно, зачем…Как же вычислить все ресурсы, с которых может загрузиться поддельный .jpg? Ведь после каждого запроса URL снова шифруется, а при успешной загрузке происходит выход из цикла перебора ресурсов… Небольшие манипуляции с кодом и BP на ключевых точках: Здесь мы затерли NOP’ами (No OPeration) процедуры обратного шифрования URL. Не стоит забывать и про выход из цикла перебора. Там тоже затрем условный переход после проверки ответа от сервера, что приведет к бесконечному циклу: В итоге вот чего удалось добиться: Так-как в цикле случайно выбирается URL, то шанс, что с первого раза расшифруются все строки по порядку как-то маловат… Что как раз можно заметить на скриншоте — один URL так и не расшифровался при довольно длительных попытках перебора. «Корейский рандом!» Неее, так не интересно… Есть же процедура 0×00401FF3, которая генерирует данный рандом, но зачем ее слушать? Можно ведь сразу в процедуру расшифровки «руками» передать смещение на нужную строку и ее размер! (почему сразу в голову не пришло…)Указатели на зашифрованные строки и их размеры сохранялись сразу после старта процесса, за EntryPoint (тогда это было еще не понятно). Теперь же, выше, на скриншоте стека видны указатели на URL, а под каждым из них размер строки. Вот и смотрим — указатель на оставшийся зашифрованный URL находится по смещению 0×00401708, а размер строки — 0×24 (36 байт). Учитываем, что размер указан для ASCII, а у нас UNICODE, поэтому умножаем на 2 и получаем 0×48 (72 байта). Меняем значения регистров EDI (указатель на строку) и ESI (размер строки в байтах) на вычисленные значения и передаем управление процедуре расшифровки. Получаем профит — все ресурсы, с которых данный семпл Downloader’а может загрузить CTB-Locker: Все это абсолютно нормальные сайты, предварительно взломанные для использования их как плацдарма для распространения вредоносного ПО. Данные ресурсы справедливы только для данного семпла Downloader’а. Ко мне в руки попал еще один экземпляр Trojan-Downloader.Win32.Cabby.cfeu (по классификации KAV), в нем URL’ы другие. Активность его была замечена спустя пару дней после отлова и появления сигнатур на первый.Кто-то скажет, что проще и быстрее снять трассу каким-либо пакетным анализатором и проанализировать DNS запросы — и будет прав. Но цель статьи не в простоте, а в познании.Расшифровка JPG Итак, получили зловредный .jpg: После чего попадаем в процедуру расшифровки. В самом начале файла четыре байта по смещению 0×4 — это размер зашифрованных данных, которые начинаются со смещения 0×8 и будут расшифрованы: Сама процедура расшифровки похожа на ту, что работала со строками — тот же ключ, та же логика — поэтому ее разбирать смысла нет. Кстати, сам 16 байтный ключ: «CA 95 02 43 17 46 67 E4 FF 6E 8E D1 4E 7A BE 86».После расшифровки получаем ожидаемый результат: Сюрприз Как оказалось, принятый и расшифрованный .jpg — не просто исполняемый файл, а контейнер с исполняемыми файлами. Как говорилось выше, четыре байта по смещению 0×4 — размер всех данных в контейнере. Далее идут payload’ы, перед каждым из которых четыре байта — размер payload’а. В нашем случае, в контейнере был не только CTB-Locker…После расшифровки, по смещению первого payload’а и его размеру находится смещение на второй, которое передается довольно большой процедуре 0×00402AC9. Ее описывать не буду, т.к. это может растянуться еще на целую статью. По сути это самописный PE Loader, который проецирует в свой процесс DLL из расшифрованного контейнера и передает управление функции «Grab_Psw». Как уже можно догадаться по названию экспортируемой функции, эта DLL ничто иное, как Password Stealer, ворующий учетные данные из различных приложений. Спектр приложений довольно широкий.Пароли уходят через HTTP POST в таком же шифрованном JPG. Вот пример: На момент анализа на всех целевых ресурсах принимающий 3858850926.php уже был удален. И вот незадача — вредонос замирал в бесконечном цикле перебора ресурсов для отправки украденных учетных данных.Хм…, но это ведь не конец, файлы-то пользователям шифровались.После каждой попытки ответ от сервера проверяется на наличие строки «Confirmed» с помощью API SHLWAPI.StrStrA: Условный переход осуществляется по результату, возвращенному SHLWAPI.StrStrA: Ну что ж, сделаем из него JNZ: Тем самым обманули приложение, дав ему понять, что пароли успешно отправлены — можно продолжать.CTB-Locker Сразу после того, как вредонос «отправил» на сервер украденные учетные данные, происходит переход к процедуре 0×004028CC, которая создает новый .exe файл с рандомным названием в директории %Temp%. После чего пишет в него первый payload из расшифрованного контейнера (JPG, который был принят ранее), выдерживает timeout перед запуском, запускает созданный .exe, снова выдерживает timeout и удаляет файл.Процесс Downloader’а после этого завершается.Достаем файл из %Temp% до запуска на исполнение и отправляем его на Virustotal. Ожидаемый вердикт: Ссылка на отчет.Заключение Общий сценарий Downloader’а: Извлекает из секции ресурсов .rtf и открывает его для обмана пользователя; Через 7 минут скачивает зашифрованный контейнер под видом .jpg; Расшифровывает контейнер и проецирует из него библиотеку DLL в собственную память с помощью самописного PE Loader’а; Вызывает из DLL функцию «Grab_Psw», которая крадет учетные данные из различных приложений; Отправляет украденные учетные данные в шифрованном контейнере под видом .jpg файла в интернет; Извлекает из полученного в п.2 контейнера CTB-Locker в директорию %Temp% и запускает его. В ходе анализа выяснилось, что CTB-Locker — не единственная угроза, которую несет с собой данный семпл Trojan-Downloader.Win32.Cabby.cemx. Вместе с шифровальщиком, в сеть утекают учетные данные широкого спектра приложений, о которых злоумышленники никого не предупреждают, прося заплатить за расшифровку пользовательских данных.