Последние два года я собирал солверы для CTF на pwntools и angr - ручная работа, скрипт за скриптом. А потом на одном университетском CTF LLM-агент набрал больше очков, чем большинство студенческих команд. Не потому что задания были простые. Потому что агент действовал быстрее, не уставал и не зависал эмоционально после трёх часов без прогресса. Разберу, как AI-агенты устроены изнутри, где они реально обгоняют людей, где проваливаются - и как собрать своего CTF-агента на Python уже сейчас.
Что вообще такое AI-агент для CTF и чем он отличается от «спросить ChatGPT»
Когда говорят «LLM хакинг CTF», обычно представляют чат с GPT, куда вставляют условие задачи. Это не агент. Агент - автономная система: получает задачу, сама решает, какой инструмент дёрнуть, выполняет команду, читает вывод и принимает следующее решение. Цикл крутится, пока флаг не найден или не исчерпан лимит итераций. Подробнее - в нашем подробном разборе
безопасность LLM и атаки на языковые модели.
Разница принципиальная. Человек, копирующий вывод из терминала в чат и обратно - человек с ассистентом. Агент - замкнутый цикл:
Observe → Think → Act → Observe. Без участия человека между шагами.
По данным исследования «Understanding Human-AI Collaboration in Cybersecurity Competitions» (arxiv, 2025), агенты, работающие автономно на живом университетском CTF, обошли по очкам большинство студенческих команд. Но дьявол в деталях - речь об участниках начального и среднего уровня. Топ-команды агентов всё ещё обгоняли.
Архитектура CTF-солвера на базе LLM: что внутри
Агентный цикл (Agent Loop)
Стандартная архитектура CTF-агента строится вокруг трёх компонентов:
- LLM-ядро - языковая модель (GPT-4, Claude, открытые модели через Ollama), которая принимает решения
- Набор инструментов (tools) - обёртки над реальными утилитами: запуск shell-команд, работа с файлами, отправка HTTP-запросов, взаимодействие с бинарниками через pwntools
- Память и контекст - промежуточные результаты, которые агент накапливает между итерациями
Цикл выглядит так:
Код:
Код:
[Задание CTF] → LLM анализирует → выбирает tool → выполняет команду
↑ ↓
└──────────── читает stdout/stderr ←────────────────┘
В упомянутом исследовании для экспериментов использовался
CTFriend - специально спроектированный агент с поддержкой нескольких LLM-бэкендов и интеграцией стандартных CTF-инструментов. Агент получал описание задачи, файлы и доступ к shell-окружению.
Минимальный стек для CTF-агента
Вот что реально нужно, чтобы агент мог решать задачи категорий web, crypto и forensics:
ВНИМАНИЕ: запускайте агента ТОЛЬКО в изолированной среде (Docker-контейнер, VM). Агент имеет неограниченный доступ к shell и может выполнить деструктивные команды. LLM подвержены prompt injection (OWASP LLM Top 10 - LLM01), и злонамеренное задание CTF может заставить агента выполнить произвольный код на хост-машине. Используйте nsjail, firejail или Docker с ограниченными capabilities.
Python:
Код:
# Пример концептуальной архитектуры CTF-агента
# Демонстрация принципа - не production-код
# Запускать ТОЛЬКО в изолированном окружении (Docker/VM)
from
langchain
.
agents
import
initialize_agent
,
Tool
from
langchain
.
chat_models
import
ChatOpenAI
import
subprocess
def
run_shell
(
command
:
str
)
-
>
str
:
"""Выполняет shell-команду и возвращает вывод"""
try
:
result
=
subprocess
.
run
(
command
,
shell
=
True
,
capture_output
=
True
,
text
=
True
,
timeout
=
30
)
return
result
.
stdout
+
result
.
stderr
except
subprocess
.
TimeoutExpired
:
return
"TIMEOUT: команда выполнялась дольше 30 секунд"
def
analyze_binary
(
filepath
:
str
)
-
>
str
:
"""Базовый анализ бинарника через file + strings"""
info
=
run_shell
(
f"file{filepath}"
)
strings_out
=
run_shell
(
f"strings{filepath}| head -50"
)
checksec
=
run_shell
(
f"checksec --file={filepath}"
)
return
f"File info:\n{info}\nStrings:\n{strings_out}\nChecksec:\n{checksec}"
tools
=
[
Tool
(
name
=
"shell"
,
func
=
run_shell
,
description
=
"Выполняет shell-команду. Используй для nmap, curl, python-скриптов"
)
,
Tool
(
name
=
"analyze_binary"
,
func
=
analyze_binary
,
description
=
"Анализ бинарного файла: тип, строки, защиты"
)
,
]
llm
=
ChatOpenAI
(
model
=
"gpt-4"
,
temperature
=
0
)
agent
=
initialize_agent
(
tools
,
llm
,
agent
=
"zero-shot-react-description"
,
verbose
=
True
,
max_iterations
=
25
# лимит на число шагов
)
# Запуск на задаче
agent
.
run
(
"""
CTF Challenge: Web exploitation
URL: http://target:8080
Description: Simple login form. Find the flag.
Hint: The developer left something in the source code.
"""
)
Это демонстрация концепции. В боевом агенте добавляются: парсинг файлов задания, автоматическое определение категории, специализированные инструменты для каждой категории (pwntools для pwn, z3/sage для crypto) и механизм отката при тупике.
Агенты побеждают большинство студентов: данные исследований
Самый интересный кусок из свежих исследований - раздел «Agents beat most humans» из работы «Understanding Human-AI Collaboration in Cybersecurity Competitions». Эксперимент проводился на живом университетском CTF, где автономные AI-агенты соревновались параллельно с человеческими командами. Контекст: участники - студенты начального и среднего уровня, не профессиональные CTF-игроки.
Что показали результаты
Агенты уверенно обходили по очкам большинство студенческих команд. Не все - но большинство. Топ-команды с опытными участниками сохраняли преимущество. Результаты зависели от сложности:
- На простых задачах (easy/medium) агенты решали быстрее и стабильнее, чем средний участник
- На сложных задачах (hard) человеческие топ-команды сохраняли преимущество, а агенты чаще зависали в циклах бесплодных попыток
Другая работа с arxiv - «The World's Top AI Agent for Security Capture-the-Flag» - формулирует это точно: доминирование в CTF -
узкая оптимизация. Системы, натренированные на захват флагов, преуспевают в сопоставлении паттернов и эксплуатации известных уязвимостей. Это не универсальный интеллект хакера. Это grep с логикой - и я считаю, что это определение стоит запомнить.
Почему агенты быстрее на стандартных задачах
CTF автоматизация работает, потому что огромная часть задач начального и среднего уровня - комбинации известных техник:
- SQL-инъекция в форме логина → агент сразу пробует
и варианты
- Base64-закодированный флаг в cookies → мгновенное распознавание и декодирование
- Классический buffer overflow с NX disabled → шаблонный ret2shellcode
AI-агент для CTF не изобретает атаку. Он перебирает паттерны из обучающих данных (включая тысячи CTF-райтапов) со скоростью, недоступной человеку. Проект
CRAKEN (OpenReview) создал открытый датасет CTF-райтапов с реальными процедурами обнаружения уязвимостей, реализации эксплойтов и attack payloads - именно такие данные питают knowledge base агентов.
Где AI-агенты проваливаются: анализ неудач
В том же исследовании есть Appendix F - «Agent failure reason analysis». Из моего опыта возни с LLM-агентами через LangChain и AutoGPT-подобные фреймворки, а также по данным исследований, вот основные категории провалов.
Зацикливание (Loop Traps)
Агент пробует одну и ту же технику с минимальными вариациями и не может распознать, что подход принципиально неверный. Лично наблюдал, как на задаче с кастомным шифрованием агент 20 итераций подряд долбил стандартными крипто-атаками, вместо того чтобы просто прочитать исходный код шифра. Как человек, который ищет ключи под фонарём, потому что там светлее.
Многоступенчатая логика
Задача, требующая последовательной эксплуатации 3-4 разных уязвимостей (SSRF → file read → password leak → RCE), ломает агента. Каждый отдельный шаг он может выполнить, но удержать в контексте всю цепочку и принять решение о переходе к следующему этапу - тут LLM теряет нить. Контекстное окно вроде бы большое, а толку мало.
Нестандартные бинарники
В обсуждении на Reddit про применение LLM для решения CTF показательный вывод: попытки автоматической эксплуатации бинарных уязвимостей были
полностью безуспешны, как и пост-эксплуатация для закрепления доступа. Pwn-категория остаётся крепостью людей - особенно задачи с нестандартными аллокаторами, kernel exploitation и race conditions.
Задачи на творческое мышление
Если таск требует «догадаться», что файл - это на самом деле перевёрнутая BMP-картинка с XOR-шифрованием по ключу из названия задания - агент проиграет. У него нет интуиции. Он не считывает «вайб» задания. Grep с логикой, и точка.
Практика: собираем CTF-агента за 30 минут
Пошаговая инструкция для сборки минимального, но рабочего CTF-агента. Проверено на задачах категории web и misc.
Весь код ниже предназначен для запуска ТОЛЬКО в изолированной среде. Минимум - Docker-контейнер без доступа к хост-сети и файловой системе. Dockerfile приведён после инструкции.
Шаг 1: Окружение
Bash:
Код:
# Создаём изолированную среду
python3 -m venv ctf-agent
source
ctf-agent/bin/activate
# Основные зависимости (актуально для LangChain 0.2+)
pip
install
langchain langchain-openai langchain-community pwntools requests beautifulsoup4
# CTF-инструменты (должны быть в системе)
# apt install nmap gobuster binwalk foremost steghide
Шаг 2: Определяем инструменты агента
Python:
Код:
# tools.py - обёртки над CTF-утилитами
# Пример для демонстрации концепции
# ЗАПУСКАТЬ ТОЛЬКО В ИЗОЛИРОВАННОЙ СРЕДЕ (Docker/VM)
import
subprocess
def
run_shell
(
command
:
str
)
-
>
str
:
"""Выполняет shell-команду и возвращает вывод"""
try
:
result
=
subprocess
.
run
(
command
,
shell
=
True
,
capture_output
=
True
,
text
=
True
,
timeout
=
30
)
return
result
.
stdout
+
result
.
stderr
except
subprocess
.
TimeoutExpired
:
return
"TIMEOUT: команда выполнялась дольше 30 секунд"
def
web_recon
(
url
:
str
)
-
>
str
:
"""Разведка веб-приложения"""
results
=
[
]
# Получаем заголовки
try
:
import
requests
resp
=
requests
.
get
(
url
,
timeout
=
10
)
results
.
append
(
f"Status:{resp.status_code}"
)
results
.
append
(
f"Headers:{dict(resp.headers)}"
)
results
.
append
(
f"Body length:{len(resp.text)}"
)
# Ищем подозрительное в HTML
if
'flag'
in
resp
.
text
.
lower
(
)
:
results
.
append
(
f"[!] 'flag' found in response body"
)
if
''
,
resp
.
text
,
re
.
DOTALL
)
results
.
append
(
f"HTML comments:{comments}"
)
except
Exception
as
e
:
results
.
append
(
f"Error:{e}"
)
return
"\n"
.
join
(
results
)
def
try_sqli
(
url
:
str
,
param
:
str
=
"username"
)
-
>
str
:
"""Пробует базовые SQL-инъекции"""
payloads
=
[
"' OR '1'='1"
,
"' OR 1=1--"
,
"admin'--"
,
"' UNION SELECT null,null--"
]
results
=
[
]
import
requests
for
payload
in
payloads
:
try
:
resp
=
requests
.
post
(
url
,
data
=
{
param
:
payload
,
"password"
:
"x"
}
,
timeout
=
10
)
if
len
(
resp
.
text
)
>
500
or
'flag'
in
resp
.
text
.
lower
(
)
or
'welcome'
in
resp
.
text
.
lower
(
)
:
results
.
append
(
f"[!] Interesting response with payload:{payload}"
)
results
.
append
(
f" Response snippet:{resp.text[:300]}"
)
except
:
pass
return
"\n"
.
join
(
results
)
if
results
else
"No SQLi found with basic payloads"
Примечание: pwntools не импортируется в tools.py, так как здесь определены только web-инструменты. Для pwn-задач лучше создать отдельный модуль
с
- pwntools при импорте перехватывает argv и меняет поведение logging, что конфликтует с остальным кодом.
Шаг 3: Промпт агента - самая важная часть
Python:
Код:
# agent_prompt.py
SYSTEM_PROMPT
=
"""Ты - опытный CTF-игрок. Твоя задача - найти флаг.
СТРАТЕГИЯ:
1. Сначала разведка: изучи что дано, определи категорию задачи
2. Для web: проверь исходный код, cookies, заголовки, скрытые пути
3. Для crypto: определи алгоритм, ищи слабости в реализации
4. Для forensics: проверь метаданные, binwalk, strings
5. Для misc: думай нестандартно, проверяй encoding
ПРАВИЛА:
- Каждый шаг объясняй КРАТКО: что делаешь и зачем
- Если подход не работает 3 попытки подряд - СМЕНИ СТРАТЕГИЮ
- Флаг обычно в формате flag{...} или CTF{...}
- Не пытайся брутфорсить - это CTF, тут думать надо
Когда найдёшь флаг, ответь: FOUND FLAG:
"""
Шаг 4: Запуск и тестирование
Python:
Код:
# solve.py - точка входа
# Импорты для LangChain 0.2+ (актуальный API)
from
langchain
.
agents
import
initialize_agent
,
Tool
from
langchain_openai
import
ChatOpenAI
from
tools
import
web_recon
,
try_sqli
,
run_shell
tools
=
[
Tool
(
"web_recon"
,
web_recon
,
"Разведка веб-приложения по URL"
)
,
Tool
(
"sqli_test"
,
try_sqli
,
"Тест SQL-инъекций на URL"
)
,
Tool
(
"shell"
,
run_shell
,
"Выполнение произвольной shell-команды"
)
,
]
agent
=
initialize_agent
(
tools
,
ChatOpenAI
(
model
=
"gpt-4"
,
temperature
=
0
)
,
agent
=
"zero-shot-react-description"
,
verbose
=
True
,
max_iterations
=
20
,
handle_parsing_errors
=
True
,
)
# Пример запуска на web-таске
result
=
agent
.
run
(
"""
Challenge: Baby Web
Category: Web
URL: http://ctf.example.com:5000/login
Description: Can you login as admin?
Files: None
"""
)
print
(
result
)
Примечание:
помечен как deprecated в LangChain 0.2+ в пользу
и LangGraph. Для боевого использования рекомендуется миграция - см. LangChain migration guide. Приведённый код работает, но при обновлении LangChain может потребовать адаптации.
Dockerfile для изолированного запуска
Код:
Код:
FROM python:3.11-slim
RUN apt-get update && apt-get install -y \
nmap binwalk foremost steghide \
&& rm -rf /var/lib/apt/lists/*
RUN useradd -m ctfagent
WORKDIR /home/ctfagent
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY tools.py agent_prompt.py solve.py ./
USER ctfagent
CMD ["python", "solve.py"]
На простых web-задачах вроде «найди флаг в комментариях HTML» или «SQL-инъекция в форме логина» такой агент справляется за 2-5 итераций. На чём-то серьёзнее - начинает буксовать, и тут вступает человек.
Парный хакинг: человек + AI как суперкоманда
Исследование на arxiv выделяет отдельный феномен -
«the power of pair hacking». Не автономный агент и не человек с чатботом. Симбиоз, где каждый делает то, что умеет лучше.
Как это работает на практике
Мой workflow на последних CTF:
- Первые 5 минут задачи - AI. Агент делает разведку, собирает артефакты, пробует стандартные подходы. Я в это время читаю описание и думаю.
- Если агент решил - отлично. Следующая задача. Это работает для 30-40% тасков начального уровня.
- Если застрял - беру управление. Читаю его лог, часто нахожу зацепку, которую агент не смог развить. Например, он нашёл необычный заголовок в HTTP-ответе, но не понял, что это hint на конкретную CVE.
- Формулирую гипотезу - отдаю обратно. «Попробуй SSTI через Jinja2 в параметре name» - и агент быстро перебирает payload'ы, пока я думаю над следующей задачей.
Этот подход описан в исследовании как наиболее результативный: команды «человек + AI» показывали результаты лучше, чем чисто человеческие команды сопоставимого уровня. Автоматизированный пентест AI не заменяет думающего человека - он убирает рутину.
Конкретные категории: где какой подход
КатегорияAI автономноЧеловек + AIТолько человекWeb (easy)Да--Web (hard, multi-step)НетДаДаCrypto (стандартные)ЧастичноДаДаCr ypto (кастомные)НетЧастичноДаPwn (stack overflow)Нет*ДаДаPwn (heap, kernel)НетНетДаForensicsЧастичноД аДаMisc/GuessingНетНетДаRev (simple)ЧастичноДаДаRev (obfuscated)НетЧастичноДа
Даже простые pwn-задачи (stack overflow) требуют многоступенчатой логики - определение offset, анализ защит, построение ROP-цепочки - а это слабое место агентов. По данным обсуждений и исследований, автоматическая эксплуатация бинарных уязвимостей остаётся полностью безуспешной для текущих LLM-агентов.
AI-платформы для тренировки offensive-навыков
Отдельная история - CTF-соревнования, где целью является атака на саму AI-систему. Платформа
Agent 0DIN (0din.ai) предлагает геймифицированный CTF для взлома AI-систем, где участники тренируют:
- Prompt injection chaining - цепочки инъекций в промпты
- Role confusion attacks - атаки на ролевые модели
- Authority escalation - повышение привилегий в контексте GenAI
Зеркальная сторона медали: пока одни строят AI-агентов для атаки, другие учатся атаковать сами AI-системы. Оба навыка скоро станут обязательными для любого offensive-специалиста.
На российском рынке AI CTF-ивенты пока фокусируются на другом - задачи, связанные с ML-пайплайнами, атаками на модели и манипуляцией данными (как на Positive Hack Days). Полезно, но автоматизацию наступательных операций не покрывает.
Будущее автоматизированного хакинга: три горизонта
Горизонт 1: текущий год - агенты-ассистенты
AI red team инструменты уже используются на реальных пентестах как ассистенты. Автоматический поиск уязвимостей через LLM-агентов работает для типовых задач: SQL-инъекции, XSS, directory traversal, простые misconfigurations. По уровню - junior пентестер, который пашет 24/7 без перерывов и не просит отпуск.
Горизонт 2: 2-3 года - специализированные агенты
Проекты вроде
CRAKEN (открытый датасет CTF-райтапов с процедурами обнаружения уязвимостей и реализации эксплойтов) создают knowledge base для следующего поколения. Ожидаю появление LLM-агентов, заточенных под конкретные категории:
- Web-agent с интеграцией Burp Suite и знанием OWASP Top 10
- Pwn-agent с pwntools + символьное выполнение через angr
- Crypto-agent с SageMath и библиотекой известных атак
Команда
Shellphish и проект
Mayhem от ForAllSecure уже годами работают на стыке символьного выполнения и фаззинга - прикрутить LLM-оркестратор поверх этого стека выглядит логичным следующим шагом.
Горизонт 3: 5+ лет - автономный наступательный AI
Это спекуляция, но траектория понятна. Если агент уже побеждает большинство студенческих команд на университетском CTF, через несколько поколений моделей и инструментов он будет конкурентоспособен на уровне DEF CON Finals. Вопрос не «если», а «когда» и «как это регулировать».
Для нас, CTF-игроков, из этого следует одно: навыки, которые невозможно автоматизировать - креативность, нестандартное мышление, понимание контекста - становятся главным конкурентным преимуществом. Человек, который умеет и думать, и управлять AI-агентом, будет доминировать и на соревнованиях, и на реальных пентестах. Подробнее о карьерных перспективах в этой области - в материале про
карьеру в red team.
Что делать прямо сейчас
Если вы CTF-игрок и ещё не экспериментировали с LLM-агентами - начните сегодня. Не потому что «AI заменит хакеров» (не заменит, не на нашем веку). А потому что человек с AI-агентом решает больше задач, чем человек без него. По данным исследований, парный хакинг - человек плюс искусственный интеллект в кибербезопасности - бьёт каждого по отдельности.
Три конкретных действия:
- Соберите базового агента по инструкции выше и прогоните его на picoCTF - задачи начального уровня. Увидите, где он тащит, а где нет.
- Заведите привычку на каждом CTF первые 5 минут задачи отдавать агенту, пока сами читаете условие.
- Копайте промпт-инжиниринг для CTF-контекста - правильный системный промпт агента важнее, чем модель. Разница между «решил» и «зациклился» часто в одной строке инструкции.
Автоматизированный хакинг уже здесь. Вопрос в том, вы используете этот инструмент - или проигрываете тем, кто использует.