Рад снова тебя встретить на страницах нашего журнала, мой друг! Мы продолжаем прокачивать скиллы в реверсинге и познавать нелегкое ремесло malware-аналитика. В сегодняшнем выпуске мы поговорим о двух интересных фичах, которые довольно часто встречаются в «живых образцах» вредоносного ПО: шифровании (encoding) и внедрении shellcode, позволяющего в дальнейшем получить командную оболочку ОС потенциальной жертвы.

Ну что, ты готов попробовать свои силы и ринуться в бой? Тогда смело приступаем к делу!

 

Четыре предыдущих урока

Перед прочтением этой статьи рекомендуем освежить в памяти предыдущие материалы: нулевой, первый, второй, третий.


WARNING

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

В нашем сегодняшнем выпуске мы разберем две интересные фичи современного поколения malware: обфускацию кода вредоноса при помощи шифрования и внедрение шелл-кода (англ. shellcode) после инфицирования — чтобы, например, выполнить какой-нибудь эксплоит или получить командную оболочку ОС.

 

Data Encoding, или шифрование как искусство

 

Теоретическая часть

Современные антивирусные движки и эвристические анализаторы с высокой долей вероятности позволяют обнаруживать еще неизвестные или малоизученные вирусы. Для того чтобы «расколоть» вредонос, антивирусное ПО сначала прогоняет по сигнатурной базе, затем, если не удается ничего обнаружить, выполняет код программы в собственной песочнице и, наконец, запускает поведенческий анализатор, рассматривая под лупой каждое действие вредоноса, будь то обращение к реестру, системным файлам, сторонним приложениям или проявление сетевой активности. Поэтому для скрытия присутствия вредоноса в системе применяются различные техники и методы, к примеру использование rootkits или bootkits, которые мы рассматривали в прошлой статье.

Другая задача состоит в том, чтобы максимально усложнить вирусному аналитику ручной анализ образца малвари, когда он уже попал в антивирусную лабораторию. Это, в свою очередь, позволит оттянуть время до того, как сигнатуру малвари добавят в антивирусные базы или будет выпущена тулза для лечения инфекции.

Один из вариантов — шифрование собственного кода малвари (англ. encoding), часто также называемое обфускацией. «Запутывать» код возможно на уровне алгоритма, заложенного во вредонос, исходника (source code) и/или ассемблерного текста. Для создания запутанного ассемблерного кода (того, который мы видим в IDA Pro) могут применяться и специализированные компиляторы, использующие неочевидные или недокументированные возможности. Отдельная песня — класс специальных программ, выполняющих обфускацию (обфускаторов). В качестве примера такого софта для программ на платформе .NET приведу вот эту софтину, для Java — эту. Будет полезна и старая добрая статья Криса Касперски «Обфускация и ее преодоление». Вот тут еще одна неплохая статья с теорией. Подробный рассказ про использование LLVM в качестве обфускатора. И обязательно прочитай статью «Учимся распознавать полиморфизм и обфускацию кода на примере известного вируса» в одном из прошлых выпусков нашего журнала.

Для тех же, кому лень разбираться в премудростях обфускаторов и писать свой запутанный код, есть готовые программы, которые работают по принципу «загрузил — выбрал опции — зашифровал». Найти их можно в кладовке легендарного VX Heaven. Однако помни, что все эти тулзы давно уже изучены современными антивирусами и внесены в сигнатурные базы, так что халявы не будет. 🙂

При шифровании кода малвари вирусописатель выбирает конкретный метод, который наилучшим образом отвечает его целям. Иногда могут использоваться простые шифры, к примеру логические побитовые операции — OR или XOR, реализующие битовые сдвиги в машинных инструкциях, или же сложные алгоритмы, к примеру Base64, изначально разработанный для кодирования сообщений электронной почты.

Часто используемый шифр, базирующийся на операции XOR, — это самый простой шифр, который весьма похож на всем известный шифр Цезаря. XOR, или исключающее OR, — логическая, или, как еще называют, битовая, операция, которая может быть использована для изменения оригинального порядка битов в ассемблерном коде. Операция XOR для шифрования использует значение статического байта. Каждый байт текста последовательно изменяется. Для тех, кто не понял, хорошим подспорьем будет вот этот пример, там наглядно показывают, как текст шифруется, причем правило сдвига букв можно выбрать самому.

Существует еще несколько простых алгоритмов шифрования, основанных на использовании рассмотренных инструкций:

  • Алгоритмы ADD и SUB позволяют производить кодирование операциями ADD и SUB для отдельных байтов блока аналогично операции XOR. ADD и SUB — нереверсивные операции, поэтому их необходимо использовать совместно, то есть одну для шифрования, а другую для расшифровки.
  • ROR- и ROL-инструкции позволяют перевернуть несколько битов в байте справа или слева. Точно так же, как ADD и SUB, они должны использоваться вместе, поскольку они необратимы, то есть выполняются только в одну сторону.
  • ROT — это оригинальный шифр Цезаря. Обычно используется латинский алфавит (A–Z и a–z), начиная с любой буквы, или 94 печатных символа в стандартной кодировке символов ASCII.
  • Многобайтовые (Multibyte Instead) преобразования заключаются в том, что заменяется не один байт, данный алгоритм позволяет использовать больше ключевых значений (к примеру, часто берутся цепочки 4 или 8 байт длиной). В этом случае ради удобства применяют операции XOR для каждого блока.

Чуть более подробно о приемах обфускации, построенных на использовании простых операций, можно почитать в статье Malware Monday: Obfuscation.

 

Специализированный инструментарий

  • IDA Pro имеет очень полезный плагин под названием FindCrypt2, также идущий в пакете для разработчиков IDA Pro SDK. Плагин ищет в теле дизассемблированной программы специфические константы, связанные с криптографическими алгоритмами. И нужно сказать, хорошо справляется со своей задачей, так как большинство алгоритмов шифрования давно известны и изучены и используют сигнатурные элементы, по которым можно вычислить алгоритм.
  • Krypto ANALyzer, он же просто KANAL, тоже весьма полезный инструмент, который использует те же принципы, что и плагин FindCrypt2 для IDA Pro. Однако Krypto ANALyzer предназначен для PE-анализатора, в нашем случае это неутомимый PEiD. Помимо констант и алгоритмов шифрования, Krypto ANALyzer распознает также таблицы Base64 и связанные с шифрованием функции из таблицы импорта.
  • IDA Entropy Plugin — один из инструментов, который позволяет искать признаки энтропии, в нашем случае шифрования в PE-файлах. Он выручит, когда первые два со своей задачей не справились, но у нас есть подозрение, что криптография в коде точно используется. Достаточно просто загрузить данный плагин в IDA Pro, поместив ida-ent.plw в каталог IDA, где лежат все плагины.

INFO

Шифрование кода malware с целью обфускации во многом зависит от компетенции вирусописателя. Для шифрования могут использоваться в самом простом случае логические побитовые операции, например OR или XOR, реализующие битовые сдвиги в машинных инструкциях, или сложные алгоритмы, к примеру Base64, изначально разработанный для кодирования сообщений электронной почты.


 

Внедрение shellcode, или как получить удаленный доступ к командному шеллу

 

Теоретическая часть

Шелл-код (англ. shellcode) — это часть кода, встроенного в малварь и позволяющего после инфицирования целевой системы жертвы получить код командной оболочки, например /bin/bash в UNIX-подобных ОС, command.com в черноэкранной MS-DOS и cmd.exe в современных операционных системах Microsoft Windows. Очень часто шелл-код используется как полезная нагрузка эксплоита, но это выходит за рамки нашего материала. Зачем все это нужно? Как ты понимаешь, мало просто инфицировать систему, проэксплуатировать уязвимость или положить какую-нибудь системную службу. Все эти действия хакеров во многих случаях нацелены на получение админского доступа к зараженной машине. Так что малварь — это всего лишь способ попасть на машину и получить shell, то есть управление. А это уже прямой путь к сливу конфиденциальной информации, созданию ботнет-сетей, превращающих целевую систему в зомби, или просто выполнению иных деструктивных функций на взломанной машине.

Шелл-код обычно внедряется в память эксплуатируемой программы, после чего на него передается управление при помощи использования программных ошибок, таких как переполнение стека или переполнение буфера в куче, или использования атак форматной строки. Пока не забыл: хорошая статья на Хабре на эту тему. Управление шелл-коду передается перезаписью адреса возврата в стеке адресом внедренного шелл-кода, перезаписью адресов вызываемых функций или изменением обработчиков прерываний. Кстати, не припоминаешь ли чего из прошлого урока про инжекты в процессы? 🙂 Результатом всего этого и будет выполнение шелл-кода, который открывает командную строку для использования взломщиком.

Для тех, кто готов погружаться в дебри шелл-кода и пробовать свои силы в разработке, отличная статья из нашего журнала «Многоразрядные шелл-коды. Пишем Ring0-shellcode под Windows x64».

При эксплуатации удаленной уязвимости (то есть эксплоита) шелл-код может открывать на уязвимом компьютере заранее заданный порт TCP для дальнейшего удаленного доступа к командной оболочке. Такой код называется привязывающим к порту (англ. port binding shellcode). Если же шелл-код подключается к порту компьютера атакующего (с целью обхода брандмауэра или просачивания через NAT), то такой код называется обратной оболочкой (reverse shell shellcode).

Если ты хочешь побаловаться использованием эксплоитов, дорога тебе к Metasploit Framework, однако это выходит за рамки нашей статьи, поэтому я приведу лишь несколько ссылок на интересные статьи, которые ты можешь изучить самостоятельно.

Существуют два способа запуска шелл-кода в память на исполнение:

  • Метод position-independent code (PIC, позиционно независимый код) — это код, который использует жесткую привязку бинарного кода (то есть кода, который выполнится в памяти) к определенному адресу или данным. Шелл-код — это по сути PIC. Почему жесткая привязка так важна? Шелл не может знать, в каком именно месте оперативной памяти будет располагаться, поскольку во время выполнения различных версий скомпрометированной программы или малвари они могут загрузить шелл-код в разные ячейки памяти.
  • Метод Identifying Execution Location («Определяй свое место выполнения») заключается в том, что шелл-код должен разыменовать базовый указатель при доступе к данным в позиционно независимой структуре памяти. Добавление (ADD) или вычитание (Reduce) значений от базового указателя позволяет безопасно получить доступ к данным, которые входят в состав шелл-кода.
 

Обнаружение шелл-кода на взломанной машине

Хакеры, дорожащие своей свободой и репутацией, пишут шелл-коды, используя техники, скрывающие их атаку. Так, типичная система обнаружения вторжений (англ. IDS) обычно просматривает весь входящий сетевой трафик в поисках структуры, специфичной для шелл-кода. Если IDS находит такую структуру, то пакет, содержащий эту сигнатуру, уничтожается до того, как он еще достигнет своей цели. Однако слабая позиция IDS состоит в данном случае в том, что если трафик закодирован, то распознать его не удастся. Теперь ты улавливаешь, почему так ценно шифрование?

WARNING

Будь осторожен при скачивании и распаковке архивов с образцами malware на компьютер. Все исследования выполняй только в изолированной виртуальной среде! Не выполняй действий, в которых на 100% не уверен! И не забывай делать регулярные snapshot системы для быстрого отката в случае поломки.

 

Анализ семпла malware01

Инструменты:

  1. IDA Pro (with plugins).
  2. OllyDbg.
  3. PEiD (with Krypto ANALyzer).

Ну что же, начнем! Первым делом открываем PEiD и грузим туда наш семпл. Все как и ожидалось, никаких сюрпризов. Однако мы помним, что имеем дело с криптографией в коде малвари, поэтому попробуем запустить плагин Krypto ANALyzer (должен быть предварительно подгружен в PEiD). И вот что мы видим: сигнатуры обнаружены.

Результат анализа файла в программе PEiD
Результат анализа файла в программе PEiD

Идем дальше. Открываем IDA Pro и загружаем туда семпл, минуя множество окон и малоинформативных сведений, обращаем внимание на таблицу ресурсов... Да, и здесь тоже нет ничего бросающегося в глаза.

Отображение окна String в IDA Pro
Отображение окна String в IDA Pro

Быть может, попытаем счастья в поиске сетевой активности? Хм... Запускаем Process Explorer, далее выделяем процесс, запущенный нашим вредоносом, переходим в «Свойства», жмем вкладку Strings и параллельно запускаем сетевую акулу Wireshark, в окне анализа пакетов можно обнаружить GET-запрос на веб-ресурс http://www.practicalmalwareanalysis.com. Данные на вкладке Strings утилиты Process Explorer и выдернутые из пакета Wireshark совпали.

Сравнение данных String в Process Explorer и Wireshark
Сравнение данных String в Process Explorer и Wireshark

Вернемся к дизассемблеру IDA Pro. На графической диаграмме замечаем любопытные строки: подпрограмма @0x00401300 загружает некий ресурс в двоичном виде и применяет операцию XOR для некоторого значения ';'. На следующем скриншоте это весьма явно заметно.

Данные из IDA Pro
Данные из IDA Pro

Ниже скриншот окна из IDA Pro, где желтым подсвечены инструкции шифрования с помощью операции XOR.

Текст кода с инструкциями шифрования с помощью операции XOR
Текст кода с инструкциями шифрования с помощью операции XOR

И у нас возникает закономерный вопрос: какой ключ (шифр) используется для кодирования и что конкретно он кодирует? Вспоминая то, что мы нашли раньше, можно сделать вывод, что ключ ';' призван декодировать строку, содержащую URL http://www.practicalmalwareanalysis.com.

Итак, мы определили, какой алгоритм шифрования используется и какие данные он шифрует. Пора подключать плагины, которые помогут нам в декодировании. Мы будем использовать инструменты поиска сигнатур FindCrypt2, Krypto ANALyzer и IDA Entropy Plugin, чтобы определить другие механизмы кодирования.

Окно с результатами парсинга семпла в Krypto ANALyzer
Окно с результатами парсинга семпла в Krypto ANALyzer

KANAL plugin обнаружил четыре адреса, использующих символы из строки ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/. Как думаешь, на что это похоже? Да-да, мой друг, ты правильно смекаешь, что этот набор символов представляет собой алфавит, из которого потом делаются перестановки. А что же с сетевым трафиком? Для его кодирования используется алгоритм Base64. Ниже представлен скриншот из отладчика OllyDbg, иллюстрирующий закодированные строки.

Закодированные строки Base64 в OllyDbg
Закодированные строки Base64 в OllyDbg

А вот скриншот все из того же отладчика, содержащий инструкцию, которая отвечает за сам процесс кодирования.

Где-то в коде есть функция, отвечающая за декодирование информации по алгоритму Base64, и находится она по адресу 0x004010B1.

Функция, отвечающая за декодирование информации по алгоритму Base64
Функция, отвечающая за декодирование информации по алгоритму Base64

Посмотрим этот код на диаграмме из IDA Pro, желтым подсвечены ключевые характеристики кодирования, а именно: максимальная длина сообщения — 12 символов. В описании алгоритма максимальная длина в Base64 составляет 16 байт.

Просмотр кода в IDA Pro
Просмотр кода в IDA Pro

А вот тут мы и подходим к главному вопросу: что же малварь делает после своего запуска? Код малвари сканирует имя компьютера, на котором он запустился, шифрует его и посылает на веб-ресурс (максимум 12 байт) http://www.practicalmalwareanalysis.com каждые 30 секунд, пока не получит строку со значением 0x6F в качестве первого символа в ответе. Так сказать, мини-реализация RAT, то есть управляющего сервера, посылающего команды, и зараженной машины, получающей и исполняющей эти команды.

 

Анализ семпла malware02

Инструменты:

  1. IDA Pro.
  2. OllyDbg.

Наш семпл будет содержать шелл-код, который позволит после запуска на зараженной машине получить удаленное управление по TCP/IP и доступ к командной оболочке ОС. Ну, поехали! Грузим файл в IDA Pro и в строках кода видим, что некая функция в коде вызывается, чтобы создать новый процесс, а затем инжектит (внедряет) в него необходимый для получения удаленного доступа шелл-код.

Окно IDA Pro c инструкциями по созданию нового процесса
Окно IDA Pro c инструкциями по созданию нового процесса

Переходим к OllyDbg, чтобы увидеть аргументы, передаваемые в функцию создания процесса GetProcessID (см. 0x4013DE). Мы можем установить точку останова на месте этой инструкции. На следующем скриншоте мы видим, что путь к запуску iexplore.exe передается в функцию, а она, в свою очередь, использует его для реализации CreateProcess, то есть создания процесса, в который внедряется шелл-код.

Окно OllyDbg c точкой останова на 0x4013DE
Окно OllyDbg c точкой останова на 0x4013DE

Это верное направление, продолжаем копать в эту сторону. Чтобы найти шелл-код, я бы сначала попробовал поискать вызов функции, ответственной за внедрение шелл-кода в удаленный процесс. Поиск WriteProcessMemory будет весьма хорошим направлением для этого.

Окно IDA Pro c функцией WriteProcessMemory
Окно IDA Pro c функцией WriteProcessMemory

Как видим из скриншота, по адресу 0x00401230 вызывается функция с аргументом lpbuffer, который передается вместе с такими параметрами, как размер буфера и идентификатор процесса (PID). Нетрудно догадаться, что эта функция отвечает за открытие дескриптора удаленного процесса и в конечном счете позволяет записать в него какие-то данные. Чтобы разобраться с этим, мы просто должны проследить, кто вызвал эту функцию, и таким образом выяснить, где находится шелл-код.

Шелл-код, расположенный по адресу 0x407030
Шелл-код, расположенный по адресу 0x407030

Идем дальше... Так-так-так, вот, кажется, мы и нашли шелл-код по адресу @0x407030. Смотрим на него (скриншот ниже), а затем нажимаем клавишу C, чтобы преобразовать данные в байт-код.

Содержимое шелл-кода после преобразования в байт-код в IDA Pro
Содержимое шелл-кода после преобразования в байт-код в IDA Pro

Глядя на найденный шелл-код на следующем скриншоте из дизассемблера, мы видим, что автор малвари использует трюк с вызовом, как это было описано чуть ранее, чтобы получить адрес шелл-кода. Анализируя коды, мы можем предположить, что шелл-код, начиная с адреса 0x407048, декодируется с помощью операции XOR с 0xE7.

Шелл-код использует вызов инструкций и преобразования XOR
Шелл-код использует вызов инструкций и преобразования XOR

Для анализа шелл-кода мы можем извлечь его из процесса и запустить, используя sctest.

Для этого на функции WriteProcessMemory ставим первый брейк-пойнт. До того как этот код будет записан в удаленный процесс, мы меняем первый байт шелл-кода со значения 0x407030 на другое значение 0xCC (наша точка останова). Запускаем под отладчиком iexplore.exe, после его запуска сработает точка останова, и шелл-код не будет внедрен в процесс.

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

Просмотр импорта в OllyDbg
Просмотр импорта в OllyDbg

Теперь мы ставим брейк-пойнт @ при инициации удаленной связи с параметром SockAddr, который передается шелл-коду, то есть, грубо говоря, передается IP-адрес машины, которую нужно подцепить. Ниже на скриншоте показаны преобразования машинных данных в понятные человеку параметры (IP-адрес и TCP-порт).

Структура SockAddr в окне OllyDbg
Структура SockAddr в окне OllyDbg

Преобразование Hex to IP Address
Преобразование Hex to IP Address

В итоге мы видим, что reverse shell (cmd.exe) подключается на инфицированной машине по адресу 192.168.200.2:13330. Шелл-код создает процесс командной оболочки CreateProcessA после подключения к удаленному IP.

А вот так выглядит терминал Linux, с которого мы атаковали удаленную машину. В выводе терминала мы видим получение приглашения cmd.exe на инфицированной машине с адресом в сети 192.168.200.2:13330.

Вывод терминала Linux после эксплуатации малвари на машине жертвы
Вывод терминала Linux после эксплуатации малвари на машине жертвы
 

Заключение

Вот и прошли мы вместе с тобой, мой друг, тернистый путь по дебрям malware-кода. Ты молодец, если дочитал эту статью до конца, и очень крут, если теперь сможешь повторить все лабораторные работы, не подглядывая. Наш цикл статей по реверсингу для начинающих на этом заканчивается. Безусловно, мы рассмотрели только самые базовые и ключевые аспекты анализа малвари, и осталось очень много тем, о которых стоило бы рассказать. Можно продолжать эту тему до бесконечности и, наверное, написать даже целую книгу. Надеюсь, тебе было интересно, ты узнал хотя бы что-то новое для себя и теперь представляешь, что такое работа вирусного аналитика. Если есть вопросы, жалобы или предложения — смело пиши в комменты :).

Всем удачи в исследованиях!

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    7 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии