× Install ThecoreGrid App
Tap below and select "Add to Home Screen" for full-screen experience.
B2B Engineering Insights & Architectural Teardowns

Symbolic execution для анализа BPF malware

Symbolic execution упрощает анализ BPF malware и устраняет узкое место в reverse engineering. Подход позволяет автоматически восстанавливать “магические” пакеты для триггера бэкдоров.

Проблема проявляется не сразу — до момента, когда анализ BPF malware упирается в сложность самих фильтров. Классический Berkeley Packet Filter работает как компактная виртуальная машина внутри ядра Linux. Он обрабатывает трафик на уровне байткода и может скрывать поведение от user-space инструментов. Это делает его удобной площадкой для скрытых бэкдоров. Когда фильтр содержит десятки или сотни инструкций с ветвлениями, ручной reverse engineering превращается в узкое место: аналитик вынужден восстанавливать условия срабатывания по шагам, что занимает часы или дни.

Ситуация осложняется тем, что вредоносные программы используют “магические” пакеты. Они не активны, пока не получат строго определённую последовательность байтов. Такие условия часто закодированы через цепочки проверок со смещениями и значениями. Даже при наличии контекста, например через LLM, задача сводится к перебору возможных путей исполнения. С ростом числа инструкций сложность растёт не линейно, а экспоненциально.

Решение строится вокруг symbolic execution и формализации задачи как системы ограничений (constraints). Вместо исполнения кода с конкретными значениями входа, вход представляется как переменные. Далее система отслеживает, какие условия должны быть выполнены, чтобы достичь состояния ACCEPT. Здесь используется Z3 — theorem prover, который умеет находить значения, удовлетворяющие заданным ограничениям. Это переводит задачу из “понять весь код” в “решить систему условий”.

Компромисс здесь очевиден. Мы теряем интуитивное понимание потока исполнения, но выигрываем в скорости и автоматизации. Такой подход особенно эффективен для детерминированных систем, где результат полностью зависит от входных данных — как в случае BPF фильтров.

Реализация начинается с декомпозиции BPF программы. Каждый фильтр — это последовательность инструкций с переходами. Система строит граф путей и ищет те, которые приводят к ACCEPT. Для этого используется очередь состояний, где хранится:

  • текущая инструкция
  • путь исполнения
  • накопленные условия (boolean constraints)

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

Далее включается symbolic execution. Создаётся упрощённая модель машины с регистрами (в классическом BPF их два) и состоянием. Каждая инструкция транслируется в эквивалентное выражение Z3. Например, арифметические операции становятся выражениями над bitvector. Условия переходов превращаются в логические ограничения.

После этого Z3 решает задачу: находит значения байтов пакета, которые удовлетворяют всем ограничениям пути. На практике это даёт конкретные смещения и значения. Например:

  • проверка версии IP (IPv4 или IPv6)
  • проверка протокола (например, UDP)
  • проверка порта назначения

Эти данные затем конвертируются в реальные сетевые пакеты с помощью scapy. В результате получается не просто путь исполнения, а готовый “магический” пакет, который активирует бэкдор.

Сложности реализации в основном связаны с корректным моделированием инструкций и состояний. Хотя набор инструкций BPF ограничен, нужно аккуратно учитывать побочные эффекты, регистры и порядок выполнения. Также важно правильно обрабатывать ветвления, чтобы не потерять валидные пути.

Результат — радикальное сокращение времени анализа. Задачи, которые раньше занимали часы ручного разбора, теперь решаются за секунды. При этом система не только находит путь, но и генерирует воспроизводимый артефакт — сетевой пакет. В исходных данных нет точных метрик производительности, но качественный эффект очевиден: устранение bottleneck в анализе.

В более широком контексте это отражает тренд на автоматизацию reverse engineering через формальные методы. Symbolic execution уже давно применяется в анализе бинарников, но его применение к BPF — прагматичное расширение в сторону kernel-level логики. Особенно в условиях, где скрытность и минимальный footprint делают традиционные методы менее эффективными.

Подход также открывает возможность для проактивного обнаружения. Сгенерированные пакеты можно использовать для сканирования сети и выявления имплантов, которые иначе остаются пассивными. Это смещает анализ от реактивного к исследовательскому.

Читать

×

🚀 Deploy the Blocks

Controls: ← → to move, ↑ to rotate, ↓ to drop.
Mobile: use buttons below.