В операционной системе существует множество механизмов мониторинга, сбора данных, которые позволяют отследить состояние жизнеспособности основных компонентов, защищенности и производительности. В большой информационно вычислительной сети, сбор такого типа данных является необходимостью для своевременного реагирования на различного рода события и инциденты.
Архитектурно данную задачу можно реализовать по разному, в Linux существует низкоуровневый механизм ядра BPF, который позволяет имплементировать произвольный код в привилегированное пространство. Им пользуются модули Snort/Suricata для фильтрации проходящего трафика, tcpdump для снятия его же до попадания на стек TCP/IP. Рассмотрим алгоритм работы и основные преимущества данного решения!
Что такое BPF и eBPF?
BPF или же Berkley Packet Filter представляет собой виртуальную машину внутри ядра ОС, которая позволяет загружать в нее произвольный код. Алгоритм работы данного решения завязан на событиях системы. Любая BPF-программа будет запущена, только после того как произойдет событие, к которому она привязана.
Программы обычно пишутся на языке C с использованием специальных библиотек и заголовочных файлов, предоставляемых проектом LLVM и сообществом eBPF. После чего файл компилируется в файл формата program.o и загружается в ядро через системный вызов bpf().

Важно подчеркнуть, что основная цель BPF-программы это мониторинг и трассировка, данных на вход/выход из функции библиотек/приложений и трассировка системных хуков. Для сбора статистики, оценки производительности, разработки подсистем безопасности.
Его расширенной версией является eBPF, который имеет схожий функционал, однако, представлен в более поздних версиях ядра.
Как работают программы и bpf-обьекты?
Предустановим необходимые инструменты, которые позволят формировать системные вызовы по отношение к bpf-стеку. Для этого введем в строку команду:
dnf install bpftool bpftrace -y
После просмотрим доступный нам функционал и синтаксис инcтрумента:
bpftool 
Доступно управление обьектами, такими как BPF-программы, BPF-карты, линки и net.
BPF-программы
Для мониторинга и трассировки используется несколько типов программ с различными механизмами:
- uprobe – позволяет создать точки останова в любом процессе пользовательского простанства, без изменения исходного кода;
- kprobe – используется для отслеживания событий в ядре и модулях, не требует наличия специальных точек в коде;
- tracepoints – используется для отслеживания событий в ядре и модулях, требует наличия специальных точек в коде;
- perf_event – позволяет собирать различные метрики, такие как время выполнения функций, использование ресурсов (CPU, память и т. д.), и анализировать их для оптимизации производительности.
Рассмотрим подробнее механизм в практическом примере по мониторингу процесса аутентификации пользователей. Будем использовать uprobe, который позволит прикрепиться к функции библиотеки и считать передаваемые данные. Просмотрим полный путь к sshd:
nano /usr/lib/systemd/system/sshd.service 
Для демона найдем загружаемые им библиотеки, классически многие решения используют PAM в Linux:
ldd /usr/sbin/sshd 
PAM так же присутсвует и в sshd, поэтому будем использовать его для снятия дампа кредов. Просмотрим внутренние функции, которые могут содержать процесс аутентифкации:
readelf -Ws /lib64/libpam.so.0 | grep auth 
Среди представленных функций интересна pam_get_authtok, которая работает с токеном пользователя. С помощью bpftrace загрузим программу и проверим корректность найденной функции:
bpftrace -e 'uprobe:/lib64/libpam.so.0:pam_get_authtok { printf("target call execute\n"); }' 
Отлично, BPF программа выполнилась, так как была вызвана функция pam_get_authtok и ее контекст был доступен! А это значит, что программа могла сдампить креды из функции и положить в хранилище.
BPF-карты
Здесь они называются BPF-картами, хранятся все данные в виде ключ:значение. Просмотреть их можно командой:
bpftool map show 
А после PID может обратиться с помощью системного вызова к ячейкам и экспортировать креды! Так же с помощью карт могут общатсья разные BPF-программы. Поэтому важно понимать, что доступ к подобного рода механизмам должен быть ограничен для обычных пользователей.
Link обьекты
Коммуникация между программой и точкой мониторинга возможна благодаря обьекту Link, просмотреть существующие связи программ и точек мониторинга можно командой:
bpftool link show
Attach type говорит, о том что значения могут быть модифицированы программой в процессе передачи, а tracing prog 2 указывает на, то что трассировка принадлежит программе с id 2. Просмотрим ее командой:
bpftools prog show id 2 
Предположительно она модифицирует запросы от Human Interface Device, ее можно сдампить командой:
bpftool dump xlated id 2
В итоге на вывод мы получаем дизассемблированные инструкции, которые используются в программе. Подобного рода анализ полезен для поиска вредоносных решений и понимания работы низкоуровневых механизмов мониторинга, таких как tcpdump и прочих!