
На DEF CON CTF 2024 задача Rotisserie продержала сотни команд более шести часов — и не из-за экзотического алгоритма. Народ тянулся к lattice-атакам и Coppersmith, а решение оказалось в шифре Цезаря и одном base64-декоде. Типичная история. По данным hackerxone.com, такая картина повторяется раз за разом: crypto CTF задания уровня easy-medium решаются тремя приёмами — распознаванием классического шифра, brute-force XOR и факторизацией слабого RSA-модуля. Разберём каждый из приёмов руками, с рабочими командами и кодом.
В формате Jeopardy crypto-задачи стоят отдельной категорией, но на практике криптография всплывает как слой внутри задач web, forensics и reverse. Типичная цепочка решения crypto CTF задач:
Снятие слоёв кодировок — это, по сути, техника MITRE ATT&CK Deobfuscate/Decode Files or Information (T1140). В реальных атаках злоумышленники используют Standard Encoding (T1132.001) и Non-Standard Encoding (T1132.002) для маскировки C2-трафика, и навык распознавания кодировок с CTF напрямую переносится в blue team-работу. Для справки: техники Weaken Encryption (T1600) и Reduce Key Space (T1600.001) описывают действия атакующего на уже скомпрометированной системе (например, downgrade TLS) и не соответствуют CTF-сценарию, где криптосистема изначально слабая по замыслу организаторов.
На площадках CryptoHack, picoCTF и Cryptopals задачи расположены по нарастающей сложности. Начальный уровень — кодировки и классические шифры. Средний — XOR шифрование CTF и слабый RSA. Продвинутый — эллиптические кривые, lattice-атаки, padding oracle. Криптография в CTF для начинающих покрывает первые два уровня, и на них нарабатывается фундамент для всего остального.
По данным HackTricks Crypto CTF Workflow, первый шаг — классификация: перед тобой кодировка, шифрование, хэш или подпись. Ошибка на этом этапе стоит десятков минут впустую. Видел, как люди пишут RSA-факторизатор, а у них на входе — base64 в три слоя.
Вот triage-чеклист, который работает на любом соревновании:
A-Za-z0-9+/= с паддингом = в конце. Base32 — A-Z2-7= (много паддинга). Hex — только 0-9a-f. Группы из двух символов (A/B или точки/тире) — Бэкон или Морзе.n, e, c в задании — RSA. Если n меньше 512 бит — модуль слабый. Если e = 3 — атака низким показателем степени RSA.Этот чеклист закрывает подавляющее большинство easy-задач. Дальше — предметная работа с конкретным алгоритмом.
Предусловия и ограничения workflow: чеклист предполагает, что задача — чистая криптография. Если crypto-слой спрятан внутри стеганографии или бинарного реверса, сначала нужно извлечь данные из контейнера. Определить наличие сжатия можно по magic bytes: gzip (1f 8b), zlib (часто 78 9c), zip (50 4b 03 04). CyberChef имеет операции Raw Inflate / Gunzip для быстрой распаковки.
Шифр Цезаря — сдвиг каждого символа алфавита на фиксированное число позиций. ROT13 — частный случай со сдвигом 13. Криптоанализ классических шифров такого типа тривиален, но новички регулярно тратят на них 15-20 минут из-за одной ошибки: пытаются угадать сдвиг вместо перебора всех вариантов. Не надо так.
В CyberChef для CTF используй операцию ROT13 Brute Force — она показывает все 25 сдвигов одновременно. Ищи осмысленный текст или формат флага (FLAG{...}, CTF{...}, picoCTF{...}). Если префикс флага известен — посчитай разницу между первым символом шифротекста и первой буквой префикса. Это и есть ключ.
Для автоматизации по-английски: Nayuki Caesar cipher breaker (nayuki.io) — частотный анализ и наиболее вероятный сдвиг. Работает прямо в браузере.
Когда не работает: кириллический алфавит, кастомная таблица подстановки, аффинный шифр (сдвиг + умножение). На аффинный шифр CyberChef из коробки не рассчитан — используй dCode.fr, там есть специализированный солвер с перебором по всем допустимым коэффициентам.
Моноалфавитная подстановка заменяет каждую букву другой буквой по фиксированной таблице. Ключевое пространство — 26! (порядка 4 * 10^26 вариантов), brute-force невозможен. Зато частотный анализ шифротекста ломает этот шифр за минуты.
Принцип прост: в английском тексте E встречается примерно 12.7%, T — 9.1%, A — 8.2%. Если в шифротексте символ B появляется в 18% позиций — вероятнее всего это E. Подсчёт частот делается в несколько строк на Python: модуль collections.Counter по шифротексту, потом сопоставление топ-8 символов с таблицей частот английского алфавита (или русского, если plaintext на кириллице).
Для практической работы два онлайн-инструмента закрывают 90% случаев: - quipqiup.com — вставляешь шифротекст, получаешь варианты расшифровки с ранжированием по вероятности - Boxentriq Cryptogram Solver (boxentriq.com/code-breaking/cryptogram) — визуальный интерфейс с интерактивной подстановкой
Предусловия: частотный анализ работает на текстах от 50-100 символов. На коротких строках (менее 30 символов) распределение частот не успевает стабилизироваться, и метод даёт ложные маппинги. Тут уже приходится угадывать, а не анализировать.
Лайфхак для CTF: если формат флага известен — ищи в шифротексте 4-5-символьный кластер с паттерном, совпадающим с FLAG{ или CTF{. Четыре-пять подстановок получаешь мгновенно, и остаток решается по контексту слов. На соревнованиях этот приём экономит 10-15 минут на задачу. Проверено.
XOR — самая частая криптографическая операция в CTF-задачах. Организаторы её любят, потому что hex-строка шифротекста выглядит устрашающе, но ломается элементарно — если знаешь ключевое свойство: операция обратима. plaintext ^ key = ciphertext, значит ciphertext ^ key = plaintext и ciphertext ^ plaintext = key. На этом свойстве строятся все атаки на XOR. По сути XOR — это не шифрование, а остаток от деления на здравый смысл.
Если весь plaintext зашифрован одним байтом (0x00–0xFF), задача сводится к перебору 256 вариантов. Оценочная функция — подсчёт частых английских букв в каждом кандидате на plaintext. Ключ, дающий максимум читаемых символов, почти наверняка правильный.
import binascii
ct = binascii.unhexlify(
"1b37373331363f78151b7f2b783431333d"
"78397828372d363c78373e783a393b3736")
best, key_found = 0, 0
for k in range(256):
pt = bytes([b ^ k for b in ct])
score = sum(pt.lower().count(c) for c in b"etaoinshrdlu")
if score > best:
best, key_found = score, k
print(f"Key: 0x{key_found:02x}")
print(bytes([b ^ key_found for b in ct]).decode("ascii"))
Классика из Cryptopals Set 1 Challenge 3 — задача, через которую прошёл каждый, кто серьёзно занимается crypto в CTF. Ключ 0x58 полностью вскрывает шифротекст, выдавая фразу Cooking MC's like a pound of bacon. Скрипт пишется за две минуты и решает любую single-byte XOR задачу.
Когда scoring по буквам не работает: если plaintext — бинарные данные (PNG, ZIP, ELF). В таком случае ищи magic bytes. PNG начинается с 89 50 4E 47, ZIP — с 50 4B 03 04. XOR-и первые 4 байта шифротекста с известными magic bytes — получишь однобайтовый ключ. Этот приём часто встречается в forensics-задачах, где crypto — один из слоёв матрёшки.
Multi-byte (repeating-key) XOR — CTF-аналог шифра Виженера. Ключ повторяется циклически: KEYKEYKEYKEY... и XOR-ится с plaintext посимвольно. Сложнее single-byte? Да, но не принципиально.
Алгоритм атаки в три шага:
Вручную — 15-20 минут. Автоматически — одна команда. Если входной файл содержит hex-строку: xortool -x encrypted.hex. Флаг -x указывает, что вход в hex-формате. По умолчанию xortool считает наиболее частым байтом plaintext 0x00; флаг -c 20 переключает на пробел (0x20), что лучше подходит для текстовых данных: xortool -x -c 20 encrypted.hex. Результаты сохраняются в директорию xortool_out/. Флаг -l N принудительно задаёт длину ключа, если автодетект ошибся.
Предусловия и ограничения: шифротекст должен быть минимум в 5-6 раз длиннее ключа. На коротких текстах Hamming distance даёт шум, и определение длины ключа становится ненадёжным. Если plaintext не на английском — нужно указать xortool другой частый символ через -c.
По данным ctf101.org, XOR шифрование CTF «экспоненциально сложнее с ростом длины ключа», но на практике ключи в задачах редко превышают 20-30 байт, и xortool справляется за секунды.
RSA в CTF — почти всегда с преднамеренной слабостью. Настоящий RSA с модулем 2048+ бит факторизовать невозможно (ну, пока квантовые компьютеры не подвезли). Но CTF-задачи специально делают модуль маленьким, используют близкие простые числа или ставят экспоненту e = 3. Такие ошибки OWASP классифицирует как Cryptographic Failures (A02:2021) — и именно их мы учимся эксплуатировать.
Требования к окружению для RSA-атак:
- Python 3.8+ (для pow(e, -1, phi) — модулярный обратный без gmpy2; на практике часто встречается 3.10+)
- pip install "pycryptodome>=3.21.0" sympy (дополнительно gmpy2 — для iroot, атак Wiener/Boneh-Durfee и работы с большими числами)
- RAM: 512 МБ минимум (для SageMath-атак рекомендуется 2+ ГБ)
- Режим: offline, интернет нужен только для FactorDB lookup
Задача даёт n, e, c. Первый рефлекс — оценить размер n. Если модуль помещается в 64-битное число или имеет менее 256 бит — факторизация тривиальна. В примере из hackerxone.com, n = 2461182143756758461 раскладывается на p = 1230926867 и q = 2000003303 мгновенно:
from sympy import factorint
from Crypto.Util.number import long_to_bytes
n, e = 2461182143756758461, 65537
c = 2155617055038674401 # пример для демонстрации
p, q = list(factorint(n).keys())
assert p * q == n, "p*q != n — проверьте входные данные"
phi = (p - 1) * (q - 1)
d = pow(e, -1, phi)
print(long_to_bytes(pow(c, d, n)))
Если sympy.factorint не справляется за пару секунд — проверь FactorDB (factordb.com). Это краудсорсинговая база факторизаций: многие CTF-модули уже кем-то разложены и лежат в базе. Факторизация RSA онлайн через FactorDB — первое, что стоит попробовать, прежде чем запускать тяжёлые инструменты. Зачем тратить CPU, если кто-то уже всё посчитал?
| Слабость | Как распознать | Метод атаки |
|---|---|---|
| Малый модуль (< 256 бит) | n помещается в несколько десятков цифр |
sympy.factorint(n) или FactorDB |
| Близкие простые (p ≈ q) | n большой, но isqrt(n) близок к делителю |
Метод Ферма: инкремент a = isqrt(n) пока a^2 - n не станет полным квадратом |
| Малая экспонента e = 3 | e = 3 в условии, сообщение короткое | Кубический корень от c: gmpy2.iroot(c, 3) без модуля (только если m^e < n; иначе — атака Håstad: ≥e шифротекстов одного сообщения, зашифрованных разными модулями, восстановление через CRT) |
| Общий делитель двух ключей | Даны два публичных ключа (n1, n2) | math.gcd(n1, n2) — общий простой p за микросекунды |
| Большой e (Wiener) | e ≈ n по порядку | Атака Винера через разложение в непрерывную дробь |
| Общий модуль (common modulus) | Одно сообщение, два ключа с одинаковым n | Расширенный алгоритм Евклида для двух экспонент |
RsaCtfTool (github.com/Ganapati/RsaCtfTool) — основной инструмент для решения RSA-задач на CTF. Он последовательно прогоняет более дюжины атак: Wiener, Fermat, Hastad, Boneh-Durfee, small q, common modulus и другие. По сути — швейцарский нож для слабого RSA.
Установка: git clone https://github.com/Ganapati/RsaCtfTool && cd RsaCtfTool && pip install -r requirements.txt. Для полного набора атак нужны системные пакеты libgmp-dev и libmpc-dev (Ubuntu/Debian: apt install libgmp-dev libmpc-dev).
Базовый вызов: python3 RsaCtfTool.py -n <modulus> -e <exponent> --uncipher <ciphertext>. Инструмент сам определяет подходящую атаку и выводит расшифрованный текст.
Если задача даёт PEM-файл публичного ключа: python3 RsaCtfTool.py --publickey pub.pem --uncipherfile cipher.enc. RsaCtfTool извлечёт n и e из PEM, попробует факторизовать модуль всеми доступными методами, и при успехе — расшифрует.
Для двух ключей с предполагаемым общим делителем: python3 RsaCtfTool.py --publickey key1.pem --publickey key2.pem --uncipherfile cipher.enc.
Когда RsaCtfTool не справляется:
- Модуль действительно большой (2048+ бит) без известных слабостей — ищи другой вектор: padding oracle, related messages, fault injection
- Задача требует lattice-атак (Coppersmith) — переходи в SageMath с методом small_roots()
- Нестандартная криптосистема (Paillier, ElGamal, ECC) — RsaCtfTool бесполезен, нужны специфичные скрипты
| Инструмент | Задачи | Преимущества | Ограничения | Когда использовать | Когда не использовать |
|---|---|---|---|---|---|
| CyberChef | Кодировки, классика, AES, XOR | Визуальный, без установки, Magic-автодетект | Нет RSA-атак, нет lattice | Первый шаг — снять слои кодировок | RSA, ECC, oracle-атаки |
| xortool | Repeating-key XOR | Автоопределение длины ключа, CLI | Только XOR | Длинный шифротекст с повторяющимся ключом | Single-byte XOR (проще руками) |
| RsaCtfTool | RSA со слабыми ключами | 12+ автоматических атак | Медленно на больших n, бесполезен на сильных ключах | Любая RSA-задача — запусти первым | Non-RSA криптосистемы |
| SageMath | Lattice, ECC, advanced RSA | Полный математический стек | 2+ ГБ RAM, крутая кривая обучения | Coppersmith, small_roots, ECC | Простые задачи — overkill |
| dCode.fr | Классические шифры, нестандартные | Огромная коллекция, онлайн | Нет программного API | Неизвестный классический шифр | Современная криптография |
| pycryptodome (≥ 3.21.0) | AES, RSA, DES и все стандартные примитивы | Полные реализации в Python | Нет автоатак, нужно писать код; в старых версиях есть CVE | Расшифровка после получения ключа | Факторизация, взлом |
| Ciphey | Автодетект и декодирование | Пробует тысячи вариантов | Нестабилен на нестандартных кодировках | Первичная разведка — вдруг повезёт | Oracle, нетривиальная логика |
Рекомендуемый набор для локальной машины (по рекомендации HackTricks): pip install "pycryptodome>=3.21.0" gmpy2 sympy pwntools z3-solver. Этот стек покрывает абсолютное большинство crypto CTF заданий без необходимости ставить SageMath. Z3 нужен для задач, где криптография сводится к системе ограничений (constraint-based challenges).
nc host port).xortool для repeating-key.n. Маленький: sympy.factorint. Средний: RsaCtfTool. Большой: искать специфическую слабость (Wiener, Hastad, common modulus).Большинство crypto-тасков ломаются не высшей математикой, а распознаванием паттерна. После полусотни решённых задач взгляд начинает цепляться за характерные признаки — маленький e, повторяющийся XOR-ключ, подозрительно короткий n — и руки тянутся к нужному инструменту автоматически. Проблема новичков не в отсутствии знаний теории чисел, а в попытке решить задачу «в лоб» вместо того, чтобы потратить 30 секунд на классификацию. Видел команды, которые писали собственный факторизатор с нуля, когда sympy.factorint(n) выдал бы ответ за 0.3 секунды. Зачем?
80% crypto-задач на CTF — про pattern matching, а не про математику. Кто разобрался с тремя базовыми векторами из этой статьи — закрывает easy-уровень на любом соревновании. Но эти же три вектора формируют ложное чувство уверенности. На medium и hard задачах — padding oracle, elliptic curve discrete log, lattice reduction — начинается другая игра, где без понимания алгебры и теории чисел вообще не продвинуться. Cryptopals (cryptopals.com) и CryptoHack (cryptohack.org) дают задачи от simple XOR до lattice-атак с нарастающей сложностью, и на них нарабатывается переход от «умею brute-force» к «понимаю, почему работает». После того как easy-таски щёлкаются за минуту — не оставайся в зоне комфорта, переходи на CryptoHack Introduction to RSA и Cryptopals Set 4. Там и начинается настоящая криптография в CTF для начинающих, которые хотят перестать быть начинающими.
🚀 Хочешь закрепить на практике? Реши задачи по теме на HackerLab — категория «pentest-machines».
0 комментариев
Пожалуйста, войдите, чтобы оставить комментарий.
Загрузка комментариев...