В предыдущей части разобрали и сняли первый слой обороны зловреда. Сделали дамп процесса после расшифровки основного кода, сохранив его в отдельном исполняемом файле.
Настало время разобраться с логикой и смысловой нагрузкой самого Downloader'а.
Сетевая активность
Экспресс анализ сетевой активности показал, что зловред перебирает по списку несколько ресурсов и скачивает с первого доступного некий «efax.jpg». Вот пример запроса:
Скачаем .jpg и посмотрим внутренности данного файла — беспорядочный набор байтов. Ни сигнатуры JPG «FF D8», ни каких-либо строк. Снова шифрованные данные? Разберемся позже.
Восстановление API
Практически в самом начале листинга утыкаемся в процедуру 0x0040214C. Она восстанавливает адреса API функций, необходимых для исполнения кода Downloader'а.
Весь листинг процедуры приводить смысла нет — слишком громоздкий и однотипный. В самом начале расшифровываются строки с именами DLL, после чего эти DLL подключаются с помощью LoadLibrary, а указатели на них сохраняются в стек:
Далее, используя полученные указатели и расшифрованные имена необходимых API, с помощью GetProcAddress находятся адреса необходимых API и сохраняются в переменных.
Это вся смысловая нагрузка данной процедуры.
Единственное, что можно рассмотреть подробнее — процедуру расшифровки строковых переменных.
Пример ее использования:
Внутренности самой процедуры:
Расшифровка побайтная, ключ 16 байт. Если строка больше 16 байт, ключ циклически повторяется.
Обманка для пользователя
Сразу после восстановления необходимых API идет выделение трех 512 байтовых буферов. Будем следить за ними.
Далее один из буферов используется для сохранения пути к директории %Temp% полученного с помощью GetTempPath. Возьмем на заметку…
Немного ниже расшифровывается строка имени ресурса с помощью разобранной выше процедуры 0x00402F4F, находится его смещение и сохраняется в директорию %Temp%, как архив .cab. Имя архива генерируется случайным образом процедурой 0x00401EE8.
Пример создания файла:
Запись данных из ресурсов в новый файл:
Из созданного в %Temp% .cab архива извлекается файл .rtf с именем файла, как у исполняемого модуля, после чего запускается для показа пользователю:
Антиэвристика?
После распаковки и запуска .rtf отмечаем относительно приятное открытие — данную процедуру:
Вызов находится по смещению 0x00401D04.
В самом начале GetTickCount возвращает количество миллисекунд с момента старта системы, после чего идет цикл со Sleep и вторым запросом GetTickCount. Далее из последнего результата вычитается самый первый, а полученная дельта сравнивается с константой 0x668A0. Переводим константу в десятичную, получаем 420000, или 7 минут. Почему открытие приятное? Да потому, что после открытия .rtf можно просто завершить процесс в течении 7 минут и забыть про CTB-Locker (хотя, наверно, кто может заподозрить процесс в подозрительных действиях и завершить его просто не будет даже запускать неизвестное вложение). Возможно это time-атака на эвристики некоторых антивирусов.
Для реверсинга это не особо приятный момент, т.к. не очень хочется ждать 7 минут каждый раз, когда приходится рестартовать процесс. Поэтому поменяем константу на 1 секунду и забудем про этот таймер, вот так:
Загрузка JPG
Подошли к фрагменту, который загружает из сети упомянутый в самом начале .jpg. Существует цикл, который рандомно выбирает указатель на зашифрованную строковую переменную (URL), расшифровывает разобранной выше процедурой, передает URL в процедуру загрузки (ее разбирать не будем, ничего интересного — стандартное формирование запроса на web-сервер), снова шифрует URL той же процедурой. После описанных действий ответ от web-сервера передается в процедуру 0x00402019, в самом начале которой по объему принятых данных определяется был ли получен файл или пустой ответ от сервера, после чего принимается решение продолжить цикл перебора URL или расшифровать принятый файл.
Первый запрос всегда идет на «sintjoep.nl/images/efax.jpg», причем никак не проверяется ответ от сервера и сразу начинается цикл перебора остальных URL. Непонятно, зачем…
Как же вычислить все ресурсы, с которых может загрузиться поддельный .jpg? Ведь после каждого запроса URL снова шифруется, а при успешной загрузке происходит выход из цикла перебора ресурсов… Небольшие манипуляции с кодом и BP на ключевых точках:
Здесь мы затерли NOP'ами (No OPeration) процедуры обратного шифрования URL. Не стоит забывать и про выход из цикла перебора. Там тоже затрем условный переход после проверки ответа от сервера, что приведет к бесконечному циклу:
В итоге вот чего удалось добиться:
Так-как в цикле случайно выбирается URL, то шанс, что с первого раза расшифруются все строки по порядку как-то маловат… Что как раз можно заметить на скриншоте — один URL так и не расшифровался при довольно длительных попытках перебора. «Корейский рандом!» Неее, так не интересно… Есть же процедура 0x00401FF3, которая генерирует данный рандом, но зачем ее слушать? Можно ведь сразу в процедуру расшифровки «руками» передать смещение на нужную строку и ее размер! (почему сразу в голову не пришло…)
Указатели на зашифрованные строки и их размеры сохранялись сразу после старта процесса, за EntryPoint (тогда это было еще не понятно). Теперь же, выше, на скриншоте стека видны указатели на URL, а под каждым из них размер строки. Вот и смотрим — указатель на оставшийся зашифрованный URL находится по смещению 0x00401708, а размер строки — 0x24 (36 байт). Учитываем, что размер указан для ASCII, а у нас UNICODE, поэтому умножаем на 2 и получаем 0x48 (72 байта). Меняем значения регистров EDI (указатель на строку) и ESI (размер строки в байтах) на вычисленные значения и передаем управление процедуре расшифровки. Получаем профит — все ресурсы, с которых данный семпл Downloader'а может загрузить CTB-Locker:
Все это абсолютно нормальные сайты, предварительно взломанные для использования их как плацдарма для распространения вредоносного ПО. Данные ресурсы справедливы только для данного семпла Downloader'а. Ко мне в руки попал еще один экземпляр Trojan-Downloader.Win32.Cabby.cfeu (по классификации KAV), в нем URL'ы другие. Активность его была замечена спустя пару дней после отлова и появления сигнатур на первый.
Кто-то скажет, что проще и быстрее снять трассу каким-либо пакетным анализатором и проанализировать DNS запросы — и будет прав. Но цель статьи не в простоте, а в познании.
Расшифровка JPG
Итак, получили зловредный .jpg:
После чего попадаем в процедуру расшифровки. В самом начале файла четыре байта по смещению 0x4 — это размер зашифрованных данных, которые начинаются со смещения 0x8 и будут расшифрованы:
Сама процедура расшифровки похожа на ту, что работала со строками — тот же ключ, та же логика — поэтому ее разбирать смысла нет. Кстати, сам 16 байтный ключ: «CA 95 02 43 17 46 67 E4 FF 6E 8E D1 4E 7A BE 86».
После расшифровки получаем ожидаемый результат:
Сюрприз
Как оказалось, принятый и расшифрованный .jpg — не просто исполняемый файл, а контейнер с исполняемыми файлами. Как говорилось выше, четыре байта по смещению 0x4 — размер всех данных в контейнере. Далее идут payload'ы, перед каждым из которых четыре байта — размер payload'а. В нашем случае, в контейнере был не только CTB-Locker…
После расшифровки, по смещению первого payload'а и его размеру находится смещение на второй, которое передается довольно большой процедуре 0x00402AC9. Ее описывать не буду, т.к. это может растянуться еще на целую статью. По сути это самописный PE Loader, который проецирует в свой процесс DLL из расшифрованного контейнера и передает управление функции «Grab_Psw». Как уже можно догадаться по названию экспортируемой функции, эта DLL ничто иное, как Password Stealer, ворующий учетные данные из различных приложений. Спектр приложений довольно широкий.
Пароли уходят через HTTP POST в таком же шифрованном JPG. Вот пример:
На момент анализа на всех целевых ресурсах принимающий 3858850926.php уже был удален. И вот незадача — вредонос замирал в бесконечном цикле перебора ресурсов для отправки украденных учетных данных.
Хм… но это ведь не конец, файлы-то пользователям шифровались.
После каждой попытки ответ от сервера проверяется на наличие строки «Confirmed» с помощью API SHLWAPI.StrStrA:
Условный переход осуществляется по результату, возвращенному SHLWAPI.StrStrA:
Ну что ж, сделаем из него JNZ:
Тем самым обманули приложение, дав ему понять, что пароли успешно отправлены — можно продолжать.
CTB-Locker
Сразу после того, как вредонос «отправил» на сервер украденные учетные данные, происходит переход к процедуре 0x004028CC, которая создает новый .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. Вместе с шифровальщиком, в сеть утекают учетные данные широкого спектра приложений, о которых злоумышленники никого не предупреждают, прося заплатить за расшифровку пользовательских данных.
Комментарии (11)
milex Автор
12.05.2015 13:46Кстати, вытащил корректный дамп Password Stealer'а. Нигде не нашел более менее нормального описания, какие учетные данные он крадет. Может напишу небольшую заметку по этому поводу. Отчет на Virustotal.
akirsanov
12.05.2015 15:28+1Да скорее всего этот граббер, он сейчас в каждой второй малваре сидит, ну и сигнатурки Pony/FareIt подходят.
milex Автор
12.05.2015 15:42Да, по описанию точно оно, спасибо. Думаю тогда нет смысла его разбирать.
Dywar
12.05.2015 21:01У AV VM не все хорошо со временем, об этом написано в других местах.
Но рассказывать об этом в подробностях в паблике не лучший способ защитить пользователей, т.к. они ничего не изменят, а те кто пишет малварь изменят очень многое.
Если вас интересует как работают AV, и не спрашивать одно и тоже несколько лет подряд, пройдите бесплатный курс www.intuit.ru/studies/courses/1042/154/info.
Сигнатуры хороший способ, но как говорил Евгений, будущее за другими системами.
Статья хорошая, в копилку, спасибо!milex Автор
12.05.2015 23:31За ссылку спасибо, но технологии AV мне известны гораздо больше, чем преподается в данном курсе. Думаю в нем не рассматривается под скальпелем самые сокровенные технологии, которые реализованы в KAV, ибо это хлеб создателя (и это логично). Вопрос не в том, какие методики используются для обхода эмуляции (о них много где можно почитать), а в том, как распознать применение данных методик в уже существующем примере.
Про «другие системы»… Не помню точную цитату и кто автор, но примерно так: «Я на 99% уверен, что данные, зашифрованные ключем N на жестком диске, находящемся на Нептуне не будут взломаны за время t. При t стремящемся к нулю, а N к бесконечности.»Dywar
13.05.2015 07:43Не рассмотрены и думаю, лучше один раз бегло прочитать.
Сокровенные технологии, интересно что бы это могло быть. Таблица импортов которую спрашивали у тех поддержки (видео на Youtube) :)?
Шифрование:
«Второй закон Шамира: криптографию не сломают, ее обойдут.»
Вот с распознанием проблемы, и у тех кто уже десятилетия работает в этой сфере, иначе зачем нам постоянные обновления если и так все работало.
Oldster
Читаешь как детектив!
Все же не понятно, почему антивирусы молчат. Про увод паролей — сюрприз. И еще, правильно ли я понял, что efax.jpg может содержать любое кол-во исполняемых файлов?
milex Автор
Антивирусы молчат из-за протектора, который был разобран в первой статье. На данный семпл добавлена сигнатура (естественно разная для каждого антивируса), которая ничто иное, как просто «уникальная» последовательность байт для данного исполняемого файла. Если изменить хоть один байт из данной последовательности, то антивирусы снова замолчат. Чтобы покрыть все сигнатуры от всех антивирусов необходимо зашифровать всю секцию кода. Для обхода эвристиков шифруют строки и «прячут» таблицу импорта. Есть еще один механизм у антивирусов в контексте эвристики — эмулятор. Он имитирует исполнение файла на встроенной VM и одновременно проводит анализ сигнатур в процессе эмуляции, чтобы вскрыть неизвестные протекторы. Для обхода эмулятора используют неизвестные ему инструкции процессора и механизмы системы (общий подход, а так это отдельная тема). Про антиэмуляцию я упомянул в первой статье, но так и не смог найти участок кода, отвечающий за это. Поэтому, если кто подскажет, как это можно сделать (по каким принципам и методикам), буду очень признателен.
По поводу шифрованного контейнера — да. Структура его такова, что можно добавить любое количество исполняемых файлов. Я предполагаю, что в конструкторе данного Downloader'а предусмотрена возможность добавления DLL и EXE с выбором метода запуска на исполнение.
MaxFactor
«Для обхода эмулятора используют неизвестные ему инструкции процессора и механизмы системы (общий подход, а так это отдельная тема) „
Тоже очень интересная тема, будем надеяться, что Вы в будущем по ней напишете статью.