Злоумышленники, атакующие Linux-системы, часто используют “бесфайловое” выполнение, чтобы избежать загрузки вредоносного ПО на диск. Это помогает обойти традиционные системы детектирования и механизмы безопасности, а также оставляет значительно меньше следов для форензики.
Системный вызов memfd_create() играет важную роль в таких атаках. Этот механизм, появившийся в ядре Linux 3.17, предназначен для создания анонимных файлов, которые существуют только в оперативной памяти. Согласно руководству memfd_create(2), эти файлы ведут себя как обычные файлы — у них есть размер и отображение в памяти, их можно изменять — но они не сохраняются на физическом носителе. Вызов memfd_create() возвращает файловый дескриптор, который может быть использован вызовом fexecve(3) — это позволяет процессу выполнять бинарный файл через файловый дескриптор (FD), в отличие от вызова execve(2), где в качестве аргумента требуется путь в реальной файловой системе.
Типичная цепочка эксплуатации этого механизма состоит из трёх этапов:
Загрузчик вызывает
memfd_create(name, flags), этот вызов возвращает файловый дескриптор. Имя (name) здесь нужно только для отладки, оно не появляется в дереве каталогов.Загрузчик записывает вредоносную нагрузку (часто полученную по сети) в этот FD.
Загрузчик вызывает
fexecve(fd, argv, envp). Ядро заменяет текущий образ процесса бинарным файлом, хранящимся в анонимном сегменте памяти.
Такой подход гарантирует, что вредоносная нагрузка не попадает на диск, и таким образом она обходит:
— системы детектирования на основе сигнатур, которые сканируют диск;
— запрет на выполнение: во многих системах каталоги с правами на запись для всех (такие, как /tmp или /dev/shm) монтируют с флагом noexec, поскольку такие каталоги часто используются злоумышленниками для выполнения вредоносного ПО.
Пример атаки:
Рассмотрим каталог, который смонтирован с флагом noexec. Попытка выполнить бинарный файл id из этой точки монтирования не сработает, даже если он запускается с высшими привилегиями и сам бинарный файл является исполняемым:

Это ограничение можно обойти, если бинарный файл загружен в оперативную память и выполнен напрямую из памяти. Для демонстрации мы создали веб-сервер, который хостит бинарный файл id (он может быть вредоносным в реальных атаках), и написали простой скрипт на Python, который скачивает этот бинарный файл, загружает его в память и выполняет его в памяти, обходя все защиты. Результат можно увидеть на скриншоте ниже. Обратите внимание, что системный вызов 319 — это и есть memfd_create().

Детектирование:
Хотя файла нет на диске, ядро Linux показывает метаданные о запущенных процессах. Нужно смотреть:
— Пути в файловой системе /proc. Даже анонимные файлы отслеживаются в таких метаданных. /proc/[PID]/exe обычно указывает на путь бинарного файла, такой как /usr/bin/python3. Процесс memfd будет указывать на виртуальный путь, часто помеченный как memfd: (deleted).

— Карты памяти (memory maps). Анализ /proc/[PID]/maps или smaps показывает следы атаки. Ищите сегменты памяти с правами на выполнение (r-xp), которые сопоставлены с объектом memfd, а не с общедоступной библиотекой или известным бинарным файлом на диске.

