
Три первых CTF-турнира я закрывал категорию Crypto с нулём флагов. Сидел перед строками вроде U0dWc2JHOD0= и понятия не имел, с какого конца подступиться. Перелом случился, когда тиммейт в дискорде объяснил на пальцах: подавляющее большинство задач начального уровня строятся на комбинации трёх вещей — Base64, шифра Цезаря и XOR. После этого крипто-категория превратилась из кошмара в стабильный источник очков. Здесь — конкретный разбор каждого из трёх примитивов с рабочим кодом, инструментами и методологией, которую вы примените к следующей задаче.
Самая частая ошибка новичка в криптографии CTF — путать кодирование с шифрованием. Разница принципиальная, и от неё зависит весь подход к решению.
Кодирование — перевод данных из одного представления в другое. Base64 переводит бинарные данные в текстовый вид, hex переводит байты в шестнадцатеричные символы, URL-encoding заменяет спецсимволы на %XX. Здесь нет ключа, нет секрета — любой, кто знает формат, мгновенно восстановит исходные данные. Это не защита. Это способ транспортировки.
Шифрование — преобразование с использованием секретного ключа. Даже зная алгоритм (Цезарь, XOR, AES), без ключа сообщение не прочитать. Именно наличие ключа делает шифрование шифрованием.
На CTF это разграничение определяет ваш первый шаг. Кодирование — просто декодируете стандартным инструментом. Шифрование — ищете ключ, подбираете перебором или эксплуатируете уязвимость в реализации.
В реальных атаках путаница между кодированием и шифрованием бьёт больно. По OWASP Top 10, категория A02:2021 (Cryptographic Failures) включает случаи, когда разработчики используют Base64 вместо настоящего шифрования для «защиты» паролей, токенов, персональных данных. В MITRE ATT&CK техника T1132.001 (Standard Encoding) описывает, как злоумышленники кодируют C2-коммуникации в Base64, чтобы пройти через сетевые фильтры, блокирующие бинарный трафик. Техника T1027.013 (Encrypted/Encoded File) фиксирует использование XOR и подобных методов для обфускации вредоносных файлов. А T1140 (Deobfuscate/Decode Files or Information) — это ровно то, чем занимаются аналитики при разборе инцидентов: декодируют и расшифровывают артефакты. Навыки, отработанные на CTF-задачах, напрямую переносятся в эту работу.
Практический критерий: если для восстановления данных достаточно знать формат (Base64, hex, URL) и не нужен никакой ключ — это кодирование. Нужен ключ — шифрование. Держите этот вопрос в голове при каждой новой крипто-задаче.
Base64 — не шифр, но едва ли не каждая вторая крипто-задача начального уровня начинается именно с него. Организаторы CTF заворачивают флаг в Base64, иногда в несколько слоёв (матрёшка!), иногда комбинируют с hex или URL-кодированием. Как отмечают в CharCharBloggles, умение распознать тип данных на глаз — самая сложная и одновременно самая важная часть решения крипто-задач.
Согласно RFC 4648, существует целое семейство Base-кодирований с разными алфавитами. Умение отличить их за секунду экономит время на CTF-соревнованиях.
Base16 (hex) — алфавит 0-9, A-F (или строчные a-f). Паддинга не бывает. Пример: 48656C6C6F — это слово «Hello». Если строка состоит исключительно из шестнадцатеричных символов — перед вами hex. Декодирование: в Python — bytes.fromhex('48656C6C6F'), в CyberChef — блок «From Hex».
Base32 — алфавит A-Z, 2-7 и паддинг символами =. Пример: JBSWY3DPEBLW64TMMQ====== (это «Hello world»). Визуально — только заглавные буквы и цифры от 2 до 7, с «хвостом» из знаков равенства. Встречается в CTF реже Base64, но попадается в задачах-цепочках.
Base64 — алфавит A-Z, a-z, 0-9, +, / и паддинг = или ==. Пример: SGVsbG8gV29ybGQ= — это «Hello World». Главный признак — смешение верхнего и нижнего регистра, цифры и один-два = на конце. Есть ещё URL-safe вариант, где + заменяется на -, а / на _ — это важно, потому что стандартное декодирование URL-safe строки даст мусор.
Декодирование Base64 на Linux — одна команда: echo 'SGVsbG8gV29ybGQ=' | base64 -d. В Python: import base64; base64.b64decode('SGVsbG8gV29ybGQ='). В CyberChef — перетащите блок «From Base64» на рабочую область и вставьте данные. Для декодирования base64 онлайн существуют десятки сервисов, но CyberChef остаётся универсальным решением.
Типичная ловушка на CTF: результат первого декодирования — снова Base64. Или Base64 обёрнут в hex. Или URL-кодирование поверх Base64 поверх hex. Такие задачи решаются итеративным декодированием: снимаете один слой, смотрите на результат, определяете следующий.
В CyberChef для этого есть операция «Magic» — она анализирует данные и автоматически подбирает цепочку преобразований. Я запускаю Magic первым делом при любой новой задаче: загружаю шифротекст, жму кнопку — и нередко флаг выпадает без дополнительных телодвижений. Если Magic не справляется (а это случается с нестандартными кодировками), переходим к ручному анализу.
Ручной подход: после каждого шага декодирования смотрите на алфавит результата. Получили строку из 0-9a-f — hex, декодируем дальше. Получили строку с %20, %3D, %2F — URL-encoding, снимаем его. Получили строку с == на конце — ещё один слой Base64. Повторяем, пока не дойдём до plaintext или бинарных данных.
Ещё одна деталь: если стандартное Base64-декодирование выдаёт нечитаемый результат, а строка содержит - и _ вместо + и /, перед вами URL-safe Base64. Замените символы обратно перед декодированием или используйте в Python функцию base64.urlsafe_b64decode().
Шифр Цезаря — классический подстановочный шифр, в котором каждая буква сдвигается на фиксированное число позиций в алфавите. Сдвиг 3 превращает A в D, B в E, Z — в C (с переносом через конец алфавита). ROT13 — частный случай со сдвигом 13: двойное применение ROT13 возвращает исходный текст, потому что в латинском алфавите 26 букв, а 13 + 13 = 26. Поэтому ROT13 иногда используют в интернете для скрытия спойлеров — не как шифрование, а как лёгкая обфускация.
По материалам SANReN CSC, шифр Цезаря визуализируется как «колесо» (Caesar Cipher Wheel) с двумя концентрическими кольцами алфавитов, сдвинутыми друг относительно друга. При сдвиге 8 строка CAESAR превращается в KIMAIZ, потому что алфавит ABCDEFGHIJKLMNOPQRSTUVWXYZ перестраивается в IJKLMNOPQRSTUVWXYZABCDEFGH.
На CTF шифр Цезаря встречается в нескольких вариантах:
FKDJ{Fdhvdu_lv_hdvb} со сдвигом 3 декодируется в FLAG{Caesar_is_easy}. Символы за пределами алфавита (фигурные скобки, подчёркивания) остаются на месте.Взлом шифра Цезаря тривиален: всего 26 (или 33 для кириллицы) возможных ключей, перебор занимает меньше секунды. На dcode.fr достаточно вставить шифротекст и нажать «Decrypt» — сервис выведет все варианты с подсветкой наиболее вероятного. Для автоматизации — Python-скрипт в восемь строк:
ciphertext = "FKDJ{Fdhvdu_lv_hdvb}"
for shift in range(26):
result = ""
for ch in ciphertext:
if ch.isalpha():
base = ord('A') if ch.isupper() else ord('a')
result += chr((ord(ch) - base - shift) % 26 + base)
else:
result += ch
print(f"Shift {shift:2d}: {result}")
Скрипт выводит 26 строк. При Shift 3 появляется FLAG{Caesar_is_easy} — флаг найден. Символы {, }, _ не затрагиваются условием ch.isalpha(), что соответствует поведению классического шифра Цезаря.
Когда шифротекст длинный — несколько абзацев текста — вместо проверки всех 26 вариантов можно применить частотный анализ. В английском языке самая частая буква — E (около 12.7% текста), за ней T, A, O, I, N. Находите самую частую букву в шифротексте, предполагаете, что она соответствует E, вычисляете сдвиг — и проверяете гипотезу одной подстановкой.
Для русскоязычных шифротекстов принцип аналогичен: самая частая буква — О, за ней Е, А, И. На CTF кириллические шифры Цезаря встречаются реже, но если встретились — алгоритм идентичен, меняется только размер алфавита и таблица частот.
Для Цезаря частотный анализ — скорее академическое упражнение: при 26 вариантах полный перебор быстрее любого статистического расчёта. Но сам навык критически важен для более серьёзных шифров: Виженера (полиалфавитная подстановка) и других конструкций, где прямой перебор невозможен — ключей слишком много. Как отмечено в CharCharBloggles, частотный анализ — статистический метод, предполагающий, что самая частая буква шифротекста соответствует самой частой букве plaintext-языка.
XOR (исключающее ИЛИ) — побитовая операция: результат равен 1, если биты различаются, и 0, если совпадают. Ключевое свойство для криптографии: A XOR B XOR B = A. Одна и та же операция и шифрует, и расшифровывает — симметричный шифр в чистом виде. Как указано в курсе UgraCTF, алгоритм расшифровки XOR-шифра точно такой же, как алгоритм шифрования: берём XOR байта шифротекста и байта ключа — получаем байт plaintext.
В CTF задачи на XOR шифрование делятся на три уровня сложности, и каждый требует своего подхода.
Простейший случай: весь текст зашифрован одним байтом-ключом (значение от 0 до 255). Каждый байт plaintext XOR-ится с одним и тем же ключом. По курсу UgraCTF, ключ из одного байта даёт 256 возможных вариантов исходного текста — это больше 26 вариантов Цезаря, но всё ещё мгновенно перебирается.
Нюанс: результат XOR — байты, не обязательно печатные символы, поэтому нужен автоматический скоринг. Метод из Cryptopals (set 1, challenge 3), описанный также на dev.to: каждому варианту расшифровки присваиваем «оценку английскости» — считаем, сколько символов попадает в список частых (пробел, e, t, a, o, i, n, s, h, r, d, l, u). Вариант с максимальной оценкой — наш plaintext.
def xor_bruteforce(data: bytes) -> tuple:
best_score, best_key, best_text = 0, 0, b""
freq = b" etaoinshrdlu"
for key in range(256):
decoded = bytes([b ^ key for b in data])
score = sum(1 for b in decoded if b in freq)
if score > best_score:
best_score, best_key, best_text = score, key, decoded
return best_key, best_text
Передаёте массив байтов шифротекста — получаете ключ и расшифрованный текст. Работает за доли секунды. Этот подход — фундамент для более сложных XOR-задач, потому что repeating-key XOR сводится к набору однобайтовых.
Когда ключ длиннее одного байта и повторяется циклически (байт 0 текста XOR-ится с байтом 0 ключа, байт 1 — с байтом 1 ключа, после окончания ключа — снова с байта 0), задача разбивается на два этапа: определить длину ключа, затем — сам ключ.
Определение длины ключа через расстояние Хэмминга. Расстояние Хэмминга — количество различающихся битов между двумя байтовыми строками одинаковой длины. Вычисляется просто: XOR двух строк и подсчёт единичных битов в результате. По методике Cryptopals (challenge 6) и разбору на dev.to, нормализованное расстояние Хэмминга на байт для случайных данных близко к 4 битам, тогда как для ASCII-текста на одном языке оно обычно составляет ~2.5–3.5 бит на байт. Разница невелика, но статистически значима при сравнении 4+ блоков.
Как это помогает? Если разбить шифротекст на блоки размером с предполагаемую длину ключа, то при правильном размере блоки будут содержать plaintext, XOR-ированный с одними и теми же байтами ключа. Расстояние Хэмминга между такими блоками окажется заметно ниже, чем между блоками неправильного размера (которые содержат «перемешанные» куски plaintext с разными байтами ключа).
Алгоритм: перебираем длины ключа от 2 до 40, для каждой длины берём первые 4 блока шифротекста, считаем среднее нормализованное (делённое на длину блока) расстояние Хэмминга между всеми парами. Длина с минимальным значением — наиболее вероятная длина ключа.
Определение самого ключа. Зная длину N, транспонируем шифротекст: группируем все байты с позициями 0, N, 2N, 3N... — они зашифрованы первым байтом ключа. Все байты с позициями 1, N+1, 2N+1... — вторым байтом ключа. К каждой группе применяем однобайтовый перебор (функцию xor_bruteforce выше). Получаем полный ключ побайтно.
На практике этот двухэтапный процесс автоматизирует утилита xortool. Команда xortool encrypted.bin анализирует файл и выводит наиболее вероятные длины ключа. Дальше: xortool -l 7 -c 20 encrypted.bin — утилита подбирает ключ длиной 7 байтов, предполагая что наиболее частый символ в plaintext — пробел (ASCII 0x20), и сохраняет варианты расшифровки в директорию xortool_out. Среди сохранённых файлов ищем тот, что содержит читаемый текст. Этот подход описан и в курсе UgraCTF, и в SANReN CSC.
Атака известным открытым текстом. Если часть plaintext известна заранее — формат флага flag{ или CTF{, или заголовок файла (PNG всегда начинается с \x89PNG) — задача упрощается радикально. XOR шифротекста и известного фрагмента даёт соответствующий фрагмент ключа: key_part = bytes([c ^ p for c, p in zip(ciphertext[:5], b"flag{")]). Если ключ короткий (5 байтов или меньше) — задача решена полностью. Если длиннее — полученный фрагмент существенно сужает пространство перебора. На CTF формат флага почти всегда указан в правилах — используйте это.
Минимальный набор, который закрывает абсолютное большинство форматов шифрования CTF на начальном и среднем уровне.
CyberChef — браузерный инструмент от GCHQ. Перетаскиваете операции (From Base64, XOR, ROT13, From Hex, Magic) в «рецепт», подаёте данные на вход — видите результат в реальном времени. Работает полностью офлайн: достаточно скачать HTML-страницу. Для новичка — первый инструмент в арсенале, от простого декодирования base64 онлайн до построения сложных цепочек преобразований.
dcode.fr — онлайн-платформа с десятками дешифраторов: Цезарь, Виженер, Атбаш, все варианты Base-кодирований, частотный анализ. Раздел «Cipher Identifier» анализирует шифротекст и предлагает наиболее вероятный тип шифра — выручает, когда условие задачи не даёт подсказок.
Python 3 со стандартной библиотекой покрывает базовые операции через модули base64, binascii, itertools. Для CTF-специфичных задач — библиотека pwntools с встроенными функциями xor() для побайтового XOR и remote() для взаимодействия с удалёнными серверами задач. Установка: pip install pwntools (берите версию ≥ 4.14.0, в которой исправлена уязвимость SSTI — GHSA-7xc5-ggpp-g249).
xortool — утилита для анализа XOR-шифротекстов с многобайтовым ключом. Определяет длину ключа и подбирает сам ключ методом частотного анализа. Установка: pip install xortool.
Для дальнейшего роста: CryptoHack (cryptohack.org) — платформа, целиком посвящённая практическим крипто-задачам с нарастающей сложностью, а CryptoPals (cryptopals.com) — набор задач, на которых построена методология взлома XOR из этой статьи.
Для воспроизведения примеров из статьи: Python 3.8+ (любая ОС: Linux, macOS, Windows с WSL), пакеты xortool и pwntools (устанавливаются через pip install xortool 'pwntools>=4.14.0'), браузер для CyberChef (работает офлайн после скачивания), терминал с утилитой base64 (встроена в Linux и macOS; на Windows — через WSL или Git Bash). Минимальный RAM: 2 ГБ — крипто-задачи начального уровня не требуют вычислительных ресурсов.
Когда открываете новую задачу в категории Crypto, действуйте по алгоритму.
Шаг 1: определите тип данных. Посмотрите на алфавит строки. Только hex-символы без паддинга — Base16. Заглавные буквы плюс цифры 2-7 с = на конце — Base32. Смешение регистров, +, /, паддинг = — Base64. Буквы одного алфавита, выглядящие «почти как слова» — подстановочный шифр (Цезарь, ROT13, Виженер). Бинарный мусор без видимого паттерна — XOR или блочный шифр.
Шаг 2: попробуйте стандартные декодирования. Вставьте данные в CyberChef, примените Magic. Попробуйте последовательно Base64, Base32, hex, URL-decode. Получили читаемый текст с форматом флага — задача закрыта.
Шаг 3: определите тип шифра. Если после декодирования данные остаются нечитаемыми — это шифрование. На dcode.fr используйте «Cipher Identifier». Буквенный текст без цифр и спецсимволов — Цезарь, ROT13, Атбаш или Виженер. Бинарные данные — XOR или блочный шифр. Название задачи часто содержит подсказку: как отмечают в CharCharBloggles, задача «ROT and Roll» намекает на ROT13, «XOR-cise» — на XOR, «Based» — на Base-кодирования. Читайте условие внимательно.
Шаг 4: примените атаку. Цезарь — перебор 26 сдвигов (скрипт из статьи или dcode.fr). Однобайтовый XOR — перебор 256 ключей с частотным скорингом (xor_bruteforce). Repeating-key XOR — xortool. Для блочных шифров (AES, DES) — ищите ключ, IV или уязвимость в реализации: они обычно спрятаны в исходном коде сервера, метаданных файла или описании задачи.
Шаг 5: проверьте формат результата. Флаг должен соответствовать формату соревнования (указан в правилах: flag{...}, CTF{...}, picoCTF{...}). Если расшифрованный текст не содержит флаг — возможно, нужно ещё одно преобразование. Типичная ситуация: после XOR-расшифровки получаете строку в Base64, которую нужно декодировать отдельно.
Формула, которую я проверял на десятках решённых задач: основная масса easy-крипто — цепочка «декодируй N раз — получи флаг», где всё «шифрование» сводится к многослойному кодированию. Заметно меньшая часть — классические шифры (Цезарь, XOR) с коротким ключом. И только единичные задачи начального уровня требуют реальных криптографических знаний: RSA с маленьким экспонентом, AES в режиме ECB с oracle-атакой.
Три примитива из этой статьи — фундамент, на котором строится вся крипто-категория CTF. Без уверенного владения Base64, Цезарем и XOR переходить к RSA, эллиптическим кривым и паддинг-оракулам бессмысленно: будете спотыкаться на этапе декодирования входных данных, даже если понимаете математику. Формула на бумаге понятна, но навык формируется только когда решаешь задачи руками — на CryptoHack или PicoCTF есть подборки с нарастающей сложностью.
Мой подход — решать задачи сериями по 5-10 штук одного типа. Пять задач на Base64, пять на Цезаря, пять на однобайтовый XOR. После каждой серии паттерн распознавания встраивается в рефлексы. Через двадцать-тридцать решённых задач взгляд на шифротекст становится автоматическим: видишь структуру данных, определяешь тип, выбираешь инструмент. Без пауз на раздумья.
Главная ошибка, которую я наблюдаю у новичков в нашем CTF-клубе — не незнание алгоритмов, а паника перед непонятной строкой. Человек видит U0dWc2JHOD0=, решает что это «сложная криптография», пугается и переключается на другую категорию. А это просто два слоя Base64: первый декодирует в SGVsbG8=, второй — в Hello. Минута в CyberChef. Никакой математики, никакого перебора, никакого ключа.
Вторая по частоте ошибка — бросаться писать скрипт, не определив тип данных. Я видел, как человек полчаса писал XOR-брутфорс для строки, которая оказалась Base32. Шаг 1 методологии — «посмотри на алфавит» — существует не для красоты. Он экономит больше времени, чем любой инструмент.
CTF-криптография — не академическая дисциплина. Здесь не нужно доказывать теоремы или запоминать формулы. Нужно распознавать паттерны и применять правильный инструмент. Три примитива из этой статьи покрывают вход, а дальше каждый CTF crypto writeup, который вы разберёте, добавляет новый паттерн в копилку. Если хочешь не просто статьи читать, а пройти базу информационной безопасности системно — IB Basics на codeby.school закрывает фундамент за пару месяцев, без академического тона и с куратором в чате.
🚀 Хочешь закрепить на практике? Реши задачи по теме на HackerLab — категория «pentest-machines».
0 комментариев
Пожалуйста, войдите, чтобы оставить комментарий.
Загрузка комментариев...