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

Обфускация payload — это техника маскировки машинного кода под безобидные данные, чтобы обойти статический анализ и сигнатурное обнаружение. Вместо того чтобы хранить shellcode как последовательность байтов в памяти или на диске, атакующий кодирует его в строки, которые выглядят как IP-адреса, MAC-адреса или UUID. При исполнении программа декодирует эти строки обратно в бинарный код и выполняет его.

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

Как работает обфускация через сетевые форматы​


Идея проста: взять массив байтов shellcode и разбить его на группы, которые можно представить как строки в знакомом формате. Например, каждые 4 байта становятся IPv4-адресом вида 192.168.1.1, каждые 6 байтов — MAC-адресом вида 00-1A-2B-3C-4D-5E, каждые 16 байтов — IPv6-адресом или UUID.

При запуске вредоносная программа вызывает системные функции Windows для обратного преобразования строк в бинарные данные. Для IPv4 используется RtlIpv4StringToAddressA из ntdll.dll, для IPv6 — RtlIpv6StringToAddressA, для MAC — RtlEthernetStringToAddressA. Эти функции легитимны и используются в сетевом стеке Windows, поэтому их вызов сам по себе не вызывает подозрений.

Пример: обфускация через IPv4​


Допустим, shellcode начинается с байтов 0xFC, 0x48, 0x83, 0xE4. В обфусцированном виде они будут храниться как строка "252.72.131.228". При декодировании функция RtlIpv4StringToAddressA преобразует эту строку обратно в 4 байта и записывает их в буфер.

Процесс декодирования выглядит так:

  1. Программа получает адрес функции RtlIpv4StringToAddressA через GetProcAddress и GetModuleHandle.
  2. Выделяет буфер размером количество IPv4-адресов * 4 байта.
  3. В цикле вызывает RtlIpv4StringToAddressA для каждой строки, записывая результат в буфер со смещением.
  4. После завершения цикла в буфере находится исходный shellcode.

Аналогично работает обфускация через IPv6 (16 байтов на адрес) и MAC (6 байтов на адрес). Разница только в размере группы и используемой функции.

Пример: обфускация через UUID​


UUID — это 16-байтовый идентификатор, который обычно записывается в виде строки xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. Для обфускации shellcode разбивается на группы по 16 байтов, каждая группа преобразуется в UUID-строку с учётом порядка байтов (little-endian для первых трёх полей).

При декодировании используется функция UuidFromStringA из rpcrt4.dll, которая преобразует UUID-строку обратно в 16 байтов. Этот метод популярен, потому что UUID-строки часто встречаются в легитимном ПО и не вызывают подозрений при статическом анализе.

Что обфускация скрывает​


Обфускация payload решает несколько задач:

  • Обход статического анализа. Сигнатурные антивирусы ищут известные последовательности байтов в файле. Если shellcode закодирован в строки, сигнатура не сработает.
  • Обход YARA-правил. YARA-правила часто ищут характерные паттерны shellcode или строки, связанные с вредоносным ПО. Обфусцированные данные не содержат этих паттернов.
  • Скрытие от сканирования памяти. Если payload хранится в памяти в обфусцированном виде до момента исполнения, сканеры памяти не найдут в нём распознаваемых инструкций.
  • Усложнение reverse engineering. Аналитик, открывший файл в дизассемблере, увидит массив строк, а не машинный код. Чтобы понять, что делает программа, ему нужно сначала найти и обратить алгоритм декодирования.

Чего обфускация не скрывает: поведенческий анализ​


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

Цепочка API-вызовов как индикатор​


Когда программа вызывает RtlIpv4StringToAddressA в цикле, записывает результат в исполняемую память и затем передаёт туда управление, это создаёт поведенческую цепочку, которую можно отследить:

Код:
GetModuleHandle("ntdll.dll")
→ GetProcAddress("RtlIpv4StringToAddressA")
→ HeapAlloc / VirtualAlloc
→ RtlIpv4StringToAddressA (в цикле)
→ VirtualProtect(PAGE_EXECUTE_READ)
→ переход на адрес буфера

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

Анализ памяти после декодирования​


Если EDR или песочница делает снимок памяти после завершения цикла декодирования, но до передачи управления, в памяти будет находиться исходный shellcode. На этом этапе сигнатурный анализ и эвристика работают так же, как если бы payload не был обфусцирован.

Сетевой трафик и поведение после исполнения​


Если shellcode устанавливает сетевое соединение, анализ трафика может выявить характерные паттерны: обращение к известным C2-серверам, использование определённых протоколов или структур данных. Обфускация payload не влияет на то, что происходит после его исполнения. Создание процессов, модификация реестра, запись файлов — все эти действия видны поведенческому анализу независимо от того, как был замаскирован исходный код.

Ограничения обфускации​


Обфускация payload — это не серебряная пуля. У неё есть несколько фундаментальных ограничений:

  • Декодирование должно произойти. Чтобы shellcode исполнился, он должен быть декодирован в исходный вид. В этот момент он становится уязвим для анализа памяти.
  • API-вызовы видны. Функции декодирования (RtlIpv4StringToAddressA, UuidFromStringA и т. д.) вызываются через стандартные механизмы Windows, которые могут мониториться EDR.
  • Поведение после исполнения не обфусцировано. Что бы shellcode ни делал после запуска — создание процессов, сетевые соединения, модификация файлов — эти действия видны поведенческому анализу.
  • Обфускация не защищает от динамического анализа. Если аналитик запускает образец в отладчике или песочнице, он увидит момент декодирования и сможет извлечь исходный shellcode.

Практические рекомендации для защитников​


  • Мониторьте вызовы функций преобразования строк. RtlIpv4StringToAddressA, RtlIpv6StringToAddressA, RtlEthernetStringToAddressA, UuidFromStringA в контексте, не связанном с сетевым ПО, — индикатор обфускации.
  • Отслеживайте цепочки API-вызовов. Последовательность GetProcAddress → VirtualAlloc → функция декодирования → VirtualProtect → переход на буфер должна вызывать подозрение.
  • Анализируйте память после декодирования. Если EDR делает снимок памяти в момент, когда буфер уже заполнен, но управление ещё не передано, сигнатурный анализ может сработать.
  • Используйте песочницы. Динамический анализ в изолированной среде позволяет увидеть поведение payload независимо от обфускации.
  • Не полагайтесь только на статику. Обфускация payload специально рассчитана на обход статического анализа. Эффективная защита требует комбинации статических, динамических и поведенческих методов.

Типичные ошибки при анализе обфусцированных payload​


  • Игнорирование строк в файле. Если в бинарном файле присутствует массив строк, похожих на IP-адреса, MAC-адреса или UUID, это может быть обфусцированный shellcode. Стоит проверить, есть ли в коде вызовы функций декодирования.
  • Анализ только до декодирования. Если аналитик останавливается на этапе, когда payload ещё обфусцирован, он не увидит реального содержимого. Нужно дождаться момента декодирования или обратить алгоритм вручную.
  • Недооценка поведенческих индикаторов. Даже если статический анализ не дал результатов, поведенческий анализ может выявить подозрительную цепочку API-вызовов.
  • Предположение, что обфускация делает payload невидимым. Обфускация усложняет обнаружение, но не делает его невозможным. Поведенческий анализ, мониторинг API и динамический анализ остаются эффективными.

Проверка результата при анализе подозрительного файла​


Если вы анализируете подозрительный файл и подозреваете обфускацию payload:

  1. Откройте файл в дизассемблере или декомпиляторе.
  2. Найдите массивы строк, похожих на IP-адреса, MAC-адреса или UUID.
  3. Найдите вызовы функций RtlIpv4StringToAddressA, RtlIpv6StringToAddressA, RtlEthernetStringToAddressA или UuidFromStringA.
  4. Определите, куда записывается результат декодирования.
  5. Проверьте, передаётся ли управление на адрес буфера с декодированными данными.
  6. Если да — извлеките декодированный shellcode из памяти или обратите алгоритм декодирования вручную.
  7. Проанализируйте извлечённый shellcode на предмет известных паттернов, API-вызовов и сетевого поведения.

Этот подход позволяет обойти обфускацию и получить доступ к исходному payload для дальнейшего анализа.

Источники​


 
Назад
Верх Низ