PDA

Просмотр полной версии : Обход EDR Linux: syscall evasion, io_uring и eBPF-атаки для пентестеров


Сергей Попов
27.04.2026, 12:27
https://forum.antichat.xyz/attachments/4951828/img_b117797f11.png

Когда на engagement'е попадается Linux-хост с EDR-агентом, первый рефлекс - понять, что именно этот зверь перехватывает. На Windows ответ давно каталогизирован: ntdll-хуки, ETW-провайдеры, kernel callbacks. На Linux картина другая. Агенты разных вендоров используют принципиально разные источники телеметрии - от auditd до eBPF-сенсоров и частных kernel-модулей (проприетарных). И у каждого подхода свои слепые зоны. Вот их-то мы и будем эксплуатировать.

По данным Kaspersky Incident Response, уязвимости в публично доступных приложениях стали первопричиной 39% состоявшихся инцидентов. При этом, согласно CrowdStrike 2025 Global Threat Report (данные цитирует Vectra AI), 82% детектов приходятся на malware-free активность - credential theft, living-off-the-land и identity-based атаки, которые Linux EDR особенно плохо отслеживает. Обход EDR Linux перестал быть прерогативой APT-групп: готовые EDR bypass-инструменты продаются на подпольных форумах от 300 долларов.

Разберём три фундаментальных вектора обхода EDR на Linux для пентестеров (общий арсенал и контекст - в руководстве по Linux для пентестера (https://forum.antichat.xyz/threads/592899/)): прямые syscall'ы минуя glibc, злоупотребление io_uring и наступательное использование eBPF. Для каждого - конкретный механизм, почему он работает и что проверять на своих хостах.
Как Linux EDR собирает телеметрию и что именно хукается
Чтобы понять, как работают Linux EDR bypass методы, нужно сначала разобрать, что агент видит. Телеметрия на Linux собирается тремя способами, и у каждого характерные дыры.
Три уровня перехвата: auditd, eBPF и kernel modules
Auditd (Linux Auditing System) - самый старый и совместимый механизм. Агент подписывается на события аудита ядра: запуск процессов (

execve

), открытие файлов, сетевые подключения. Проблема в том, что auditd работает как очередь с ограниченным числом потребителей. Если на хосте уже крутится compliance-система, подписанная на audit events, EDR конкурирует за тот же поток. По данным Kaspersky, даже компании с развёрнутым EDR на серверах вынуждены прописывать широкие исключения в правилах мониторинга ради производительности. Результат - часть syscall'ов тупо не попадает в телеметрию.

https://forum.antichat.xyz/attachments/4951828/1777310522183.png

eBPF-сенсоры - современный подход, который используют Falco, Tracee и коммерческие решения вроде BI.ZONE EDR. Агент загружает eBPF-программы, которые цепляются к kprobes (точки входа в kernel-функции) и tracepoints (предопределённые точки трассировки). Например, kprobe на

__x64_sys_execve

перехватит запуск любого процесса, а tracepoint

sched:sched_process_exec

- событие планировщика. eBPF не так сильно бьёт по производительности, как auditd, но реализация различается между ядрами. По данным Cymulate, для работы BTF и CO-RE (Compile Once, Run Everywhere) целевое ядро должно быть собрано с

CONFIG_DEBUG_INFO_BTF=y

- а это есть далеко не на всех серверах. Лично я на engagement'ах регулярно встречаю RHEL 7 и CentOS 7, где BTF и не пахнет.

Проприетарные kernel-модули - отдельные вендоры идут дальше. Kaspersky внедрил технологию UKLM (Universal Linux Kernel Module), которая обрабатывает события через собственный драйвер уровня ядра и, по заявлению вендора, снижает влияние на производительность в 20 раз по сравнению с auditd. Такие модули дают максимальную видимость, но создают зависимость от конкретной версии ядра и дистрибутива.

Ключевой вывод: определите, какой механизм использует конкретный EDR-агент - от этого зависит, на каком уровне нужно работать, чтобы остаться невидимым.
Syscall hooking Linux evasion: прямые вызовы ядра минуя glibc
Большинство пользовательских программ вызывают syscall'ы не напрямую, а через обёртки glibc:

execve()



__libc_execve()

→ инструкция

syscall

. Часть EDR-агентов ставит uprobes именно на функции glibc или использует

LD_PRELOAD

для перехвата вызовов в userspace. Это первый и самый простой барьер, который можно обойти.

На Linux, в отличие от Windows, номера syscall'ов стабильны между версиями ядра одной архитектуры. Таблица определена в

arch/x86/entry/syscalls/syscall_64.tbl

и практически не меняется. Никакой SysWhispers не нужен - достаточно знать номер.

Минимальный пример вызова

execve

(syscall 59 на x86_64) напрямую, минуя glibc:

C:



#include
long
raw_execve
(
const
char
*
path
,
char
*
const
argv
[
]
,
char
*
const
envp
[
]
)
{
long
ret
;
__asm__
volatile
(
"syscall\n"
:
"=a"
(
ret
)
:
"0"
(
59
)
,
"D"
(
path
)
,
"S"
(
argv
)
,
"d"
(
envp
)
:
"rcx"
,
"r11"
,
"memory"
)
;
return
ret
;
}


Компилируйте с

gcc -nostdlib -nostartfiles -fno-stack-protector -static

(при этом нужно определить собственную точку входа

_start

, например:

void _start() { char *argv[]={"bin",NULL}; raw_execve("/bin/sh",argv,NULL); asm("mov $60,%rax; xor %rdi,%rdi; syscall"); }

) - итоговый бинарь не затронет ни одну функцию glibc. Если EDR ставил uprobe на glibc-обёртки (

__libc_execve

,

execvp

с PATH-resolution) - он этот вызов не увидит.

Что по-прежнему ловит прямой syscall: kprobes на kernel-стороне (

__x64_sys_execve

), tracepoints (

sys_enter_execve

), auditd с правилом

-a always,exit -F arch=b64 -S execve

, seccomp-BPF фильтры. Они перехватывают на уровне входа в ядро, до dispatch'а в конкретный handler.

Прямые syscall'ы - не серебряная пуля. Они обходят userspace-хуки, но не kernel-level мониторинг. Тем не менее на практике я регулярно встречаю агенты, которые полагаются исключительно на LD_PRELOAD или uprobe-перехват - для них этой техники за глаза.

Практический подход для пентеста Linux и обхода защиты: напишите свой лоадер на C или Go с прямыми syscall'ами для критических операций -

execve

,

openat

,

connect

,

mmap

,

mprotect

. Стандартные операции (чтение конфигов, вывод в stdout) оставьте через glibc - они не триггерят алерты.
io_uring - слепая зона для обхода EDR на Linux
Если прямые syscall'ы обходят userspace-хуки, но остаются видны ядерному мониторингу, то io_uring создаёт проблему другого масштаба: операции выполняются в ядре, но не через те syscall entry points, на которых стоят kprobes EDR-агента.

https://forum.antichat.xyz/attachments/4951828/1777310578911.png

io_uring - интерфейс асинхронного ввода-вывода, появившийся в ядре Linux 5.1 (2019). Работает через два кольцевых буфера в shared memory: Submission Queue (SQ), куда процесс помещает запросы, и Completion Queue (CQ), откуда забирает результаты. После начальной настройки через

io_uring_setup ('https://man7.org/linux/man-pages/man2/io_uring_setup.2.html')

дальнейшие операции не требуют отдельных syscall'ов - ядро забирает запросы из SQ автономно.

И вот тут-то начинается самое интересное для уклонения от обнаружения Linux-хостов. EDR-агенты, использующие kprobes на syscall entry points (

x64_sys_read

,

x64_sys_write

,

_x64_sys_connect

) или syscall tracepoints (

sys_enter*

), не видят аналогичные операции через io_uring. Агенты, хукающие VFS-уровень (

vfs_read

,

vfs_write

) или использующие LSM-hooks, могут перехватить и io_uring-операции, потому что внутри ядра io_uring вызывает те же функции. Но таких агентов - меньшинство. По данным Vectra AI, большинство Linux EDR-решений не мониторят io_uring, что создаёт серьёзный пробел в детектировании для серверных окружений.
RingReaper: разбор техник по MITRE ATT&CK
RingReaper - пост-эксплуатационный агент, созданный как PoC для демонстрации этой слепой зоны. По данным Picus Security, он полностью заменяет стандартные утилиты разведки io_uring-аналогами:

ЗадачаОбычный подходRingReaper (io_uring)MITRE ATT&CKСписок процессов

ps aux

через /procАсинхронное чтение /proc через SQProcess Discovery (T1057)Сетевые подключения

netstat

/

ss

Запрос kernel network tablesSystem Network Connections Discovery (T1049)Активные сессии

who

/

w

Чтение /dev/pts через io_uringSystem Owner/User Discovery (T1033)Чтение /etc/passwd

cat /etc/passwd

Асинхронное чтение через SQData from Local System (T1005)Поиск SUID-бинарей

find / -perm -4000

Проверка через io_uringExploitation for Privilege Escalation (T1068)Самоудаление

rm -f

Асинхронный unlinkIndicator Removal: File Deletion (T1070.004)

Каждая из этих операций тривиальна по отдельности. Но когда они идут через io_uring, eBPF-based EDR с kprobes на

sys_read

,

sys_openat

,

sys_unlink

их просто не видит. При этом для базовых io_uring-операций чтения root не нужен -

io_uring_setup

доступен непривилегированным пользователям на хостах без явного запрета (sysctl

kernel.io_uring_disabled

появился только в ядре 6.6). Docker default seccomp profile блокирует

io_uring_setup

начиная с Docker 20.10.10 (октябрь 2021), так что в контейнерах этот фокус обычно не пройдёт.

На современных дистрибутивах (Ubuntu 23.04+, RHEL 9, Debian 12) проверьте

cat /proc/sys/kernel/io_uring_disabled

- значение 0 разрешает всем, 1 разрешает только процессам с CAP_SYS_ADMIN при создании ring, 2 полностью запрещает. Если 0 - вам повезло, io_uring один из самых практичных методов обхода EDR на Linux при пентесте.
eBPF evasion техники: мониторинг как оружие атакующего
eBPF позволяет динамически загружать программы в ядро Linux. По данным Cymulate, через kprobe/tracepoint/LSM hooks он даёт возможность наблюдать syscall'ы, точки входа и выхода функций ядра и userspace, сетевые события. Модификация поведения ограничена:

bpf_override_return

работает только для функций с

ALLOW_ERROR_INJECTION

. Но та же мощь делает eBPF идеальным инструментом для атакующего - и тут ирония: EDR-вендоры сами приучили ядро доверять eBPF-программам.

С 2023 года появилось несколько руткитов на eBPF:

ebpfkit

,

TripleCross

,

Pamspy

. Они перехватывают учётные данные, обходят файрволы и слепят EDR-агенты. Разберём три наступательных сценария syscall hijacking Linux через eBPF.

https://forum.antichat.xyz/attachments/4951828/1777310623888.png

Ослепление телеметрии - Indicator Blocking (T1562.006, Defense Evasion). Атакующий загружает eBPF-программу, которая цепляется к тем же kprobes, что и EDR, но с более высоким приоритетом. Она модифицирует данные, которые видит агент: скрывает процессы, фильтрует сетевые события, подменяет содержимое файлов. По анализу Red Canary (цитирует windshock.github.io), однажды загруженное eBPF-вредоносное ПО, может скрытно изменять результаты

bpftool

и

debugfs

, делая пост-компрометационное обнаружение крайне затруднительным. По сути, EDR смотрит на мир через линзу, которую контролирует атакующий.

Перехват учётных данных.

Pamspy

- eBPF-программа, ставящая uprobe на функции PAM (Pluggable Authentication Modules). Перехватывает пароли в момент аутентификации. Для EDR это выглядит как легитимная eBPF-программа, потому что eBPF и есть легитимная технология ядра. Красота.

Обход файрвола и скрытый C2.

BPFDoor

, использовавшийся в реальных APT-атаках, вставлял пакетный фильтр в ядро. Хост при этом выглядел так, словно не имеет открытых сетевых портов -

nmap

показывал чистый результат. По данным windshock.github.io (со ссылкой на Trend Micro), BPFDoor внедрял packet filters в ядро для обхода правил файрвола, маскируясь под отсутствие сетевых сервисов.

Почему обход антивируса Linux через eBPF так эффективен? eBPF-программы не лежат на диске в традиционном смысле. Они работают в kernel space, недоступном для userspace-сканеров. eBPF-руткит может манипулировать данными, которые видит сам антивирус. Традиционный файловый сканер попросту не имеет точки наблюдения для обнаружения eBPF rootkit - он слепой по определению.

По данным Cymulate, добавление

CAP_PERFMON

или

CAP_NET_ADMIN

расширяет возможности программы. Исключение -

BPF_PROG_TYPE_SOCKET_FILTER

, которую может загрузить непривилегированный пользователь, если

/proc/sys/kernel/unprivileged_bpf_disabled

не установлен в 1 или 2.

Для полноценного eBPF evasion атакующему нужен root. И тут в игру вступают уязвимости повышения привилегий. В sudo до версии 1.9.17p1 опция

--chroot

позволяет использовать

/etc/nsswitch.conf

из пользовательского каталога. Атакующий подготавливает вредоносный nsswitch.conf, указывающий на подконтрольную NSS-библиотеку, и выполняет произвольный код от root. Эксплуатация требует, чтобы в sudoers пользователю было разрешено выполнение команды с

--chroot

(или

CHROOT=*

в Defaults) - на дефолтных конфигурациях многих дистрибутивов это не так. CISA добавила CVE-2025-32463 в каталог KEV (актуально эксплуатируется в дикой среде, добавлена 2025-09-29). EPSS-оценка - 0.4446 (Top 5% по вероятности эксплуатации в ближайшие 30 дней). Публичные PoC доступны -

pr0v3rbs/CVE-2025-32463_chwoot

на GitHub (521 звезда).

Цепочка для пентестера: непривилегированный доступ (при наличии sudo с --chroot в sudoers) → эксплуатация CVE-2025-32463 → root → загрузка eBPF-программы для ослепления EDR → выполнение основной задачи.

Из актуального стоит отметить CVE-2025-31161 в CrushFTP (CVSS 9.8 CRITICAL, CWE-305) - authentication bypass через race condition в AWS4-HMAC авторизации, EPSS 0.8621 (Top 1%). CISA включила эту уязвимость в каталог KEV (актуально эксплуатируется в дикой среде, добавлена 2025-04-07) с пометкой об использовании в ransomware-кампаниях.
Практический сценарий: пентест Linux с обходом защиты хоста
Требования к окружению

Целевой хост: Linux kernel 5.1+ (для io_uring), дистрибутив с eBPF-поддержкой (ядро 4.4+ с BTF для CO-RE)

EDR-агент: Falco, Tracee, CrowdStrike Falcon for Linux, BI.ZONE EDR или аналог

Привилегии: для разведки - любой пользователь; для eBPF evasion - root или CAP_BPF

Инструменты атакующего: gcc/clang с

-static

, библиотека liburing, bpftool
Пошаговый алгоритм
📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше (https://forum.antichat.xyz/threads/560728/)


Получить доступ просто — достаточно проявить активность на форуме

📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше (https://forum.antichat.xyz/threads/560728/)


Получить доступ просто — достаточно проявить активность на форуме

Обнаружение eBPF rootkit и защита Linux-хостов
Этот раздел - для blue team и для пентестеров, которые пишут рекомендации по итогам engagement'а.

Первое, что нужно проверять - загруженные eBPF-программы и их привязки к сетевым интерфейсам:

Bash:



bpftool prog show
&&
bpftool map show
for
iface
in
$(ls /sys/class/net/)
;
do
ip
link
show dev
"$iface"
|
grep
-q
"xdp"
\
&&
echo
"[!] XDP attached: $iface"
done
for
iface
in
$(ls /sys/class/net/)
;
do
tc filter show dev
"$iface"
2>
/dev/null
done


Если

bpftool prog show

показывает программы с типами kprobe, tracepoint или xdp, не принадлежащие известному EDR или мониторингу - повод копать дальше. Но помните: если eBPF-руткит уже активен, он может подменять вывод самого

bpftool

. Курица и яйцо.

Именно поэтому одного мониторинга недостаточно. По данным windshock.github.io, наиболее эффективна комбинация двух инструментов. Tracee (Aqua Security) работает как камера наблюдения - записывает аномальные eBPF-события в реальном времени. Сам он основан на eBPF и отслеживает загрузку новых программ. LKRG (Linux Kernel Runtime Guard) работает как решётка на окне - активно мониторит целостность структур ядра и предотвращает модификации syscall table, подмену callback'ов и DKOM (Direct Kernel Object Manipulation, техника Rootkit - T1014, Defense Evasion по MITRE ATT&CK).

Tracee без LKRG - записывает, но не блокирует. LKRG без Tracee - блокирует, но не оставляет forensic-следа. Оба вместе дают и детектирование, и предотвращение.

Дополнительные меры для Linux endpoint detection evasion prevention:

Установите

sysctl kernel.unprivileged_bpf_disabled=1

- запретите непривилегированным пользователям загрузку любых eBPF-программ

Обновите sudo до 1.9.17p1+ для закрытия CVE-2025-32463

Мониторьте процессы с удалёнными исполняемыми файлами, использующие BPF-сокеты: если

readlink /proc/PID/exe

возвращает строку с

(deleted)

, а

/proc/PID/net/packet

не пуст - это паттерн BPFDoor

На серверах с ядром 5.1+ проверяйте io_uring:

cat /proc/PID/fdinfo/* | grep -i uring

для подозрительных процессов

Seccomp-BPF профили для критических сервисов - они перехватывают syscall'ы на уровне входа в ядро, включая прямые вызовы
Вопрос к читателям
На engagement'ах с Falco или Tracee на целевых Linux-хостах - какие kprobes и tracepoints вы видите через

bpftool prog show

в секциях

type: kprobe

и

type: tracepoint

? Конкретно интересует: перехватывает ли ваш агент

io_uring_submit

или

__io_submit_sqe

, или io_uring остаётся полностью слепой зоной? Если писали кастомные правила Falco для детекта io_uring-операций - поделитесь фрагментом YAML-конфига с полями

rule

и

condition

, укажите версию Falco.

rafinad
09.06.2026, 03:00
Часто замечал, что io_uring действительно оставляет "слепые зоны" для многих EDR-решений — они цепляются за стандартные syscalls, а io_uring обходит их, работая напрямую в ядре. По eBPF в основном только "стандартные" точки ловят, кастомных правил для io_uring не встречал, потому что это редкость. Так что если ищешь обходы, стоит попробовать именно через io_uring, но без рута там особо не разгонишься.