Урок 6. Смешанная задача: от строки до флага

Пришло время собрать всё вместе. По отдельности вы уже умеете снимать кодировки, готовить байты, ломать XOR и вычислять ключ по vsosh{. Но на реальном этапе ВСОШ эти приёмы почти никогда не встречаются поодиночке — их складывают в один «слоёный пирог». Снаружи задача выглядит как одна непонятная строка, а внутри — несколько уровней, и на каждом надо принять решение «что это и что дальше». В этом уроке мы пройдём такую задачу целиком, а потом вы решите похожую сами.

Именно этот тип задач и есть настоящий вход в олимпиадную крипту. Например, в задаче «Снежный ком» · муниципальный этап, 2025–2026 флаг сначала ксорили одним байтом, потом записывали числами, потом заворачивали в base32, а сверху ещё в base64. Ровно такой пирог мы сейчас и разберём — на своём, учебном примере с теми же слоями.

Разбор: слоёный пирог по шагам

Допустим, нам выдали вот такую строку в файле:

R1UyQ0FOSlJFQTJET0lCVkdFUURJTUJBR1U0U0FNWldFQVpUT0lCVUdVUURJTlpBR01ZU0FOQllFQTJEQ0lCVUhBUURHTlpBR1EyQ0FOQlJFQTJETUlCVEc0UURNTUk9

Ничего не «расшифровываем». Работаем по циклу из урока 1: смотрим на данные, определяем представление, снимаем слой, смотрим снова.

Шаг 1. На что похоже? Большие и маленькие буквы вперемешку, цифры, на конце =. Это признаки base64. Снимаем первый слой и — обязательно — печатаем начало результата:

import base64

s = open("task.txt").read().strip()

b = base64.b64decode(s)
print(b[:40])

Видим:

b'GU2CANJREA2DOIBVGEQDIMBAGU4SAMZWEAZTOIBU'

Снова строка. И заметьте — она другая по алфавиту: сплошные заглавные и цифры. Не паникуем: как и обещали в уроке 2, это просто следующий слой.

Шаг 2. На что похоже теперь? Только заглавные A–Z и цифры (из диапазона 2–7). Это портрет base32. Снимаем:

b = base64.b32decode(b)
print(b[:40])

Видим:

b'54 51 47 51 40 59 36 37 45 47 31 48 41 4'

Шаг 3. Это уже не кодировка — это числа. Строка десятичных чисел через пробел. Из урока 3 мы знаем, что это байты, записанные «в лоб». Собираем из них байты:

ints = b.decode()                       # строка чисел
ct = bytes(int(x) for x in ints.split())
print(ct)

Теперь у нас в руках ct — последовательность байт. Кодировки кончились, начинается собственно шифр. Байты «скачут», текста не видно — значит, это шифртекст, а не готовый ответ.

Шаг 4. Что за шифр? Мы в самом начале курса, инструментов у нас пока немного: скорее всего это XOR. Проверяем гипотезу «однобайтовый XOR» перебором с фильтром по якорю vsosh{ (урок 4):

for k in range(256):
    m = bytes(x ^ k for x in ct)
    if m.startswith(b"vsosh{"):
        print(k, m.decode())

И получаем флаг:

64 vsosh{demo_pipeline}

Ключ оказался 64 (это 0x40), и текст начинается ровно с vsosh{. Задача решена.

Соберём весь решатель целиком — вот так он и выглядит в боевом виде, десяток строк:

import base64

s = open("task.txt").read().strip()
b = base64.b64decode(s)
b = base64.b32decode(b)
ct = bytes(int(x) for x in b.decode().split())

for k in range(256):
    m = bytes(x ^ k for x in ct)
    if m.startswith(b"vsosh{"):
        print(m.decode())

Обратите внимание, чего здесь нет: угадывания шифра, паники от «страшной» строки, лишних абстракций. Есть только цикл «посмотрел → определил → снял слой → посмотрел снова» и в конце — знакомый перебор XOR. Ровно этому вы учились пять уроков.

Обратный конвейер от многослойной строки до флага

Где здесь можно ошибиться

  • Попытаться XOR-ить до снятия кодировок. XOR имеет смысл только над сырыми байтами шифртекста. Пока сверху висят base64/base32 — XOR даст бессмыслицу. Сначала слои, потом шифр.
  • Не распознать числа как байты. После base32 получилась строка чисел — легко принять её за «ещё какой-то код» и застрять. Числа 0–255 через пробел — это байты.
  • Перепутать порядок слоёв. Если снять слои не в том порядке, декодирование упадёт или выдаст мусор. Порядок подсказывает алфавит: смотрите, на что похож промежуток.
  • Забыть про якорь. Перебор без фильтра по vsosh{ заставит вас глазами просматривать 256 вариантов. С фильтром ответ выпадает сразу.

Практика урока

  • C8 «Смешанная задача». Ваша боевая задача этого модуля — такой же пирог, как разобранный, но со своими значениями. Пройдите его сами по шагам. Всё, что нужно, вы уже умеете.
  • C9 «Контрольная». Задача чуть сложнее: в ней встречаются и слой кодировки, и повторяющийся ключ, и известный префикс. Это проверка того, что вы владеете всем модулем, а не отдельными приёмами. C9 — «сверх нормы»: она не обязательна для прохождения урока, но если вы её берёте — вы точно готовы к следующему модулю.

Итоговая памятка модуля

Держите эту схему в голове перед любой крипто-задачей начального и среднего уровня:

  1. Посмотри на данные. Текст, байты, числа, файл, сервис?
  2. Определи представление по алфавиту: 0–9a–f → hex; смешанный регистр и = → base64; заглавные и 2–7 → base32; числа через разделитель → байты.
  3. Снимай слои по одному, каждый раз печатая начало промежутка. Снова кодировка — снимай дальше.
  4. Дошёл до «скачущих» байт — это шифр. На этом уровне курса думай про XOR.
  5. Ломай XOR: однобайтовый — перебор с фильтром по vsosh{; известен префикс — вычисляй ключ как $c \oplus m$; ключ повторяется — восстанови период по префиксу.
  6. Проверь флаг: получилось vsosh{...} с закрывающей скобкой — сдавай.

Памятка по распознаванию форматов данных в криптографических задачах

Что дальше в курсе

Вы прошли фундамент и уже решаете настоящие задачи. Дальше приёмы усложняются, но цикл остаётся тем же:

  • Модуль 2. Симметричные шифры и openssl/AES. Вы научитесь узнавать openssl-шифрование (метка Salted__), расшифровывать файлы по паролю и перебирать пароль по словарю — самый частый тип «крипто-СЗИ» задач.
  • Модуль 3. Модульная арифметика и RSA. int.from_bytes из урока 2 превратит текст в число, а вы научитесь факторизовать малые модули и восстанавливать закрытый ключ.
  • Модуль 4. Affine, LCG и линейные оракулы. Здесь vsosh{ снова станет ключом к решению — known plaintext ломает не только XOR.
  • Модуль 5. Восстановление собственных шифров. Вы будете читать чужой алгоритм и писать к нему дешифратор — тот же навык «пойми и обрати», что и с XOR.

Главное, что вы унесёте из первого модуля: крипто-задача решается не знанием сотни шифров, а спокойным разбором «в каком виде лежат данные и что с ними сделать». Этот навык дальше только растёт.

Что почти всегда является первым слоем крипто-задачи ВСОШ? · 4 б.
Скачать c8_mixed.txt
C8

Смешанная задача

18 б.

Боевая задача модуля: несколько слоёв кодировок, под ними числа, под числами XOR. Дойди до флага.

Скачать c9_control.txt
C9

Контрольная

22 б.

Итоговая проверка: слой кодировки + повторяющийся ключ + известный префикс. Собери все приёмы модуля.