Урок 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 — «сверх нормы»: она не обязательна для прохождения урока, но если вы её берёте — вы точно готовы к следующему модулю.
Итоговая памятка модуля
Держите эту схему в голове перед любой крипто-задачей начального и среднего уровня:
- Посмотри на данные. Текст, байты, числа, файл, сервис?
- Определи представление по алфавиту:
0–9a–f→ hex; смешанный регистр и=→ base64; заглавные и2–7→ base32; числа через разделитель → байты. - Снимай слои по одному, каждый раз печатая начало промежутка. Снова кодировка — снимай дальше.
- Дошёл до «скачущих» байт — это шифр. На этом уровне курса думай про XOR.
- Ломай XOR: однобайтовый — перебор с фильтром по
vsosh{; известен префикс — вычисляй ключ как $c \oplus m$; ключ повторяется — восстанови период по префиксу. - Проверь флаг: получилось
vsosh{...}с закрывающей скобкой — сдавай.
Что дальше в курсе
Вы прошли фундамент и уже решаете настоящие задачи. Дальше приёмы усложняются, но цикл остаётся тем же:
- Модуль 2. Симметричные шифры и openssl/AES. Вы научитесь узнавать
openssl-шифрование (меткаSalted__), расшифровывать файлы по паролю и перебирать пароль по словарю — самый частый тип «крипто-СЗИ» задач. - Модуль 3. Модульная арифметика и RSA.
int.from_bytesиз урока 2 превратит текст в число, а вы научитесь факторизовать малые модули и восстанавливать закрытый ключ. - Модуль 4. Affine, LCG и линейные оракулы. Здесь
vsosh{снова станет ключом к решению — known plaintext ломает не только XOR. - Модуль 5. Восстановление собственных шифров. Вы будете читать чужой алгоритм и писать к нему дешифратор — тот же навык «пойми и обрати», что и с XOR.
Главное, что вы унесёте из первого модуля: крипто-задача решается не знанием сотни шифров, а спокойным разбором «в каком виде лежат данные и что с ними сделать». Этот навык дальше только растёт.
Смешанная задача
Боевая задача модуля: несколько слоёв кодировок, под ними числа, под числами XOR. Дойди до флага.
Контрольная
Итоговая проверка: слой кодировки + повторяющийся ключ + известный префикс. Собери все приёмы модуля.