PPC
Автоматизация и скриптинг
Автоматизация и скриптинг — это когда вместо того, чтобы вручную кликать, копировать и вставлять тысячи раз, ты пишешь короткую программу, которая делает всю грязную работу за тебя. В CTF эта тема в первую очередь относится к Pwn, Crypto, Web и Misc — почти ко всем категориям, где нужно много повторяющихся действий. Чаще всего скрипты требуются в задачах с удалённым сервером (pwntools), крипто с большими числами (sympy/gmpy2), веб-атаках (requests), brute-force паролей/ключей и генерации хитрых payload'ов. Новичку это критически важно, потому что без автоматизации ты просто физически не успеешь решить большинство задач уровня medium и выше — руками это займёт часы или дни. Когда ты научишься быстро писать маленькие скрипты — ты начинаешь решать в 5–10 раз больше задач и получаешь удовольствие вместо выгорания.
Словарь терминов
payload
Готовые данные, которые ты отправляешь программе/серверу для эксплуатации
brute-force
Перебор всех возможных вариантов, пока не найдёшь правильный
pwntools
Библиотека Python, которая сильно упрощает написание эксплойтов
requests
Библиотека Python для отправки HTTP-запросов (как браузер, но в коде)
sympy
Библиотека Python для символьной математики и теории чисел
gmpy2
Библиотека Python для очень быстрых операций с большими числами
socket
Низкоуровневое соединение с сервером по TCP
remote
Функция в pwntools для подключения к удалённому серверу
interactive
Режим в pwntools, когда ты можешь общаться с процессом вручную
shellcode
Байты машинного кода, которые мы хотим выполнить на сервере
ROP
Цепочка готовых кусочков кода из программы для управления
packing
Преобразование чисел в байты в нужном порядке (endianness)
unpacking
Преобразование байтов обратно в числа
Python (pwntools, sympy, gmpy2, requests)
Python — главный язык в CTF, потому что он простой, быстрый для написания и имеет самые удобные библиотеки.
pwntools Библиотека номер 1 для pwn-задач. Позволяет в 5 строк подключиться к серверу, отправить payload, получить ответ, упаковать/распаковать адреса, работать с shellcode. Без неё писать эксплойты на чистом socket — это мучение.
requests Для всех веб-задач: отправить GET/POST, передать куки, заголовки, файлы, перехватить редиректы. Очень часто используется в связке с сессиями (requests.Session()).
sympy Когда в крипто-задаче нужно решить уравнение, факторизовать большое число, найти дискретный логарифм, работать с полиномами. sympy делает то, что вручную считать невозможно.
gmpy2 Когда число 1000+ бит и sympy слишком медленный — gmpy2 делает операции с большими числами в десятки раз быстрее (особенно next_prime, is_prime, powmod).
В CTF ты почти всегда начинаешь с импорта pwntools или requests — это сигнал, что задача требует автоматизации.
Bash и shell-скрипты для автоматизации
Bash — это когда тебе нужно быстро сделать что-то одноразовое:
перебрать 1000 файлов и найти в каком флаг
запустить одну и ту же команду с разными параметрами
скачать архив → распаковать → grep флаг
мониторить вывод программы и реагировать на определённые строки
Типичные конструкции в CTF:
for i in {1..1000}; do ./vuln $i | grep flag; done
while read line; do curl -d "pass=$line" http://site/login; done < rockyou.txt
binwalk -e image.png && strings _image.png.extracted/* | grep -i flag
Bash хорош для быстрых одноразовых скриптов и когда Python кажется избыточным.
Perl, Ruby, Java для специфических задач
Эти языки встречаются реже, но иногда бывают незаменимы.
Perl Очень мощный для работы с текстом, регулярными выражениями и одноразовых парсеров. В старых CTF иногда дают задачу именно под Perl (особенно в forensics с логами).
Ruby Удобный синтаксис, отличные библиотеки для крипто (openssl). Иногда быстрее писать ROP-цепочки или payload в Ruby, чем в Python.
Java Редко, но бывает в reverse-задачах (нужно декомпилировать .jar) или когда сервер написан на Java и нужно точно повторить поведение BigInteger.
Новичку достаточно знать: 95% времени хватит Python + pwntools/requests, остальные языки — это бонус для специфических случаев.
Генерация payload и brute-force скрипты
Генерация payload Самая частая задача в pwn и crypto:
cyclic(200) → найти offset до return address
p64(address) / u64(байты) → упаковка/распаковка адресов
flat([junk, pop_rdi, binsh, system]) → сборка ROP-цепочки
xor шифрование с ключом длиной 1–4 байта
создание специально отформатированной строки для format string bug
Brute-force Когда вариантов не слишком много:
перебор короткого ключа XOR (1–4 байта)
перебор seed для псевдослучайного генератора
перебор пароля длиной 4–6 символов из маленького алфавита
подбор последнего байта/блоков в padding oracle
Главное правило: если перебор ≤ 10⁶–10⁷ вариантов — пиши скрипт и запускай. Если больше — ищи математический способ или слабость.
Итог
Главное, что нужно запомнить: в CTF побеждает не тот, кто умнее всех, а тот, кто быстрее автоматизирует рутину. Без скриптов ты просто не успеешь перебрать варианты, сгенерировать payload или пообщаться с сервером тысячу раз.
Ключевые слова и термины для запоминания: pwntools, requests, sympy, gmpy2, payload, brute-force, packing, unpacking, remote, interactive, cyclic, flat, ROP.
Эти знания позволяют:
подключаться к удалённому процессу и получать shell за 10 строк кода
перебирать тысячи вариантов пароля/ключа за секунды
быстро генерировать и отправлять сложные ROP-цепочки
решать крипто-задачи с огромными числами, которые вручную не посчитать
автоматизировать веб-атаки (перебор сессий, файлов, параметров)
Научишься писать 10–20-строчные скрипты за 2–3 минуты — и уровень решаемых задач вырастет с beginner до solid intermediate буквально за месяц.
Криптография в PPC-задачах
Простые примитивы и типичные атаки
В PPC-задачах (Programming & Pwnable Crypto) тебе почти всегда дают зашифрованные данные и просят найти флаг или ключ. Чаще всего шифрование сделано очень просто или с очевидной ошибкой — именно поэтому задача и решаема за разумное время. Эта тема — сердце большинства крипто-задач для новичков и intermediate-уровня. Понимание нескольких базовых примитивов и самых популярных ошибок позволяет решать 60–70% всех крипто-задач на платформах типа CTFtime. Без этих знаний ты будешь видеть только набор непонятных байтов и быстро сдашься.
Словарь терминов
XOR
Побитовая операция: одинаковые биты дают 0, разные — 1
keystream
Последовательность байтов, которую XOR'ят с открытым текстом
Vigenère
Шифр замены, где каждый символ сдвигается на разное значение из ключа
RC4
Потоковый шифр, который генерирует keystream из короткого ключа
padding oracle
Ситуация, когда сервер сообщает, правильный ли padding
length extension
Атака, позволяющая добавить данные к сообщению, не зная ключа
HMAC
Способ сделать хеш "привязанным" к секретному ключу
MD5 collision
Два разных сообщения с одинаковым MD5-хешем
ECB
Режим шифрования, где каждый блок шифруется отдельно
CBC
Режим шифрования, где каждый блок зависит от предыдущего
IV
Случайный начальный вектор, который мешает одинаковым блокам
PKCS#7 padding
Самый популярный способ дополнения данных до размера блока
nonce
Одноразовое случайное число, используется в потоковых шифрах
malleability
Свойство шифротекста, когда его можно менять предсказуемо
Простые криптографические примитивы (XOR, Vigenère, RC4)
XOR Самый простой и самый частый примитив в CTF. Если plaintext XOR ключ = ciphertext, то plaintext = ciphertext XOR ключ. Если ключ повторяется (много одинаковых блоков), то можно найти ключ по повторяющимся кускам шифротекста. Очень часто ключ — это строка флага, которую можно угадать по длине и содержимому.
Vigenère Классический шифр. Каждую букву текста сдвигают на значение из ключа (ключ повторяется). В CTF почти всегда дают подсказку: либо ключ короткий, либо есть известная часть открытого текста. Часто просят найти ключ по шифротексту + известному началу флага ("ctf{" или "flag{").
RC4 Потоковый шифр: из ключа генерируется длинная последовательность псевдослучайных байтов (keystream), потом идёт XOR с текстом. В CTF чаще всего встречаются две ошибки:
очень короткий ключ (можно brute-force)
повторное использование одного и того же ключа для разных сообщений (XOR двух шифротекстов даёт XOR двух plaintext'ов)
В CTF эти примитивы почти никогда не используют "правильно" — всегда есть слабое место: повтор ключа, известный plaintext, короткий ключ.
Атаки на слабые реализации (padding oracle, length extension)
Padding oracle Блоковые шифры (AES и др.) требуют, чтобы данные были кратны размеру блока (16 байт). Для этого добавляют padding (например PKCS#7). Сервер иногда отвечает по-разному: "padding неверный" или "padding нормальный, но MAC неверный". Если есть такая разница — можно расшифровывать байт за байтом, посылая тысячи запросов.
Length extension attack Касается хеш-функций типа MD5, SHA-1, SHA-256 в режиме H(message || key). Если ты знаешь H(secret || message), то можешь посчитать H(secret || message || garbage || padding || новое_сообщение) без знания secret. Очень часто используется в задачах "подделать подпись" или "добавить админ=true" к cookie.
В CTF padding oracle встречается в веб-задачах с шифрованием сессий. Length extension — в задачах с "секретным ключом в подписи" на базе MD5/SHA1.
Работа с хэшами и MAC (MD5 collisions, HMAC)
MD5 collisions MD5 сломан: можно найти два разных файла с одинаковым хешем. В CTF чаще всего просят сгенерировать второй файл, который выглядит почти как первый, но имеет тот же MD5. Это используется в задачах "обмануть проверку файла по хешу".
HMAC Правильный способ: HMAC(key, message) = H( (key ⊕ opad) || H( (key ⊕ ipad) || message ) ) Если вместо HMAC используют просто H(key || message) — можно провести length extension. Если H(key || message || known) — можно подделать подпись.
В CTF почти все задачи с хешами сводятся к одной из трёх ошибок:
использование MD5/SHA1 без защиты от коллизий
H(key || message) вместо HMAC
короткий/предсказуемый ключ
Простые задачи на RSA/ECB/CBC
ECB Каждый 16-байтный блок шифруется отдельно. Одинаковые блоки plaintext дают одинаковые блоки ciphertext. Поэтому картинки в ECB-режиме выглядят "квадратиками". В CTF часто просят расшифровать или подделать сообщение, зная, что повторяющиеся куски видны.
CBC Каждый блок XOR'ится с предыдущим шифроблоком перед шифрованием. Если IV = 0 или известен — можно делать bit-flipping атаки. Если сервер возвращает padding oracle — можно расшифровывать весь текст.
RSA (самый простой уровень) Обычно дают n и e=3 или e=65537, и просят факторизовать n. Самые частые случаи:
n состоит из двух очень близких простых чисел
n маленькое (< 2^300) — можно факторизовать за секунды
p и q имеют одинаковую старшую часть (Fermat factorization)
В CTF RSA почти никогда не бывает "сложным" — всегда есть очевидная слабость в генерации ключей.
Итог
Главное, что нужно запомнить: в 90% крипто-задач для новичков и среднего уровня шифр либо очень простой (XOR, Vigenère, RC4), либо сделан с классической ошибкой (ECB, padding oracle, length extension, слабый RSA, MD5 вместо HMAC).
Ключевые слова и термины для запоминания: XOR, keystream, Vigenère, RC4, padding oracle, length extension, HMAC, MD5 collision, ECB, CBC, IV, PKCS#7, nonce, malleability, RSA small exponents.
Если ты научишься за 2–3 минуты определять, какой примитив перед тобой, и помнить 5–6 самых популярных атак — ты начнёшь решать почти все "easy-medium" крипто-задачи на соревнованиях. Это как научиться узнавать яд в еде: один раз запомнил запах — и дальше уже не отравишься.
Математические задачи и теории чисел
Математические задачи в CTF — это когда флаг прячут за простыми (на первый взгляд) вычислениями с числами: факторизацией, остатками, полиномами или играми типа «кто последний ход — тот выиграл». В первую очередь эта тема относится к категории Crypto (особенно PPC — programming & pwnable crypto), иногда встречается в Misc и очень редко в Reverse. Чаще всего такие задачи появляются в крипто-треке на соревнованиях среднего и высокого уровня, где нужно посчитать что-то «непосчитываемое» наивно или найти закономерность в игре. Новичку важно её понять, потому что без базовой теории чисел ты просто не сможешь решить 60–70% крипто-задач выше easy-уровня. Когда освоишь модульную арифметику, факторизацию и простейшие игры — откроется совершенно новый пласт решаемых задач.
Словарь терминов
простое число
Число, которое делится только на 1 и на себя
факторизация
Разложение числа на простые множители
модульная арифметика
Все вычисления «по часам» — остаток от деления на число
модульная инверсия
Число x такое, что a × x ≡ 1 (mod m)
теорема Ферма
Если p простое, то a^(p-1) ≡ 1 (mod p) для a не кратного p
функция Эйлера φ(n)
Сколько чисел от 1 до n взаимно просты с n
алгоритм Евклида
Самый быстрый способ найти НОД двух чисел
НОД
Наибольший общий делитель двух чисел
полином
Выражение вида aₙxⁿ + aₙ₋₁xⁿ⁻¹ + … + a₀
интерполяция
Найти полином, который проходит через заданные точки
конечное поле
Множество чисел с особыми правилами сложения и умножения
игра Nim
Игра с кучками камней, где выигрывает тот, кто берёт последний
nimber / Grundy
Число, которое описывает «силу» позиции в игре
XOR
Побитовая операция, ключевая для Nim и многих игр
Факторизация, простые числа, модульная инверсия
Простые числа и факторизация Если число n небольшое (< 10¹²–10¹⁴) — его можно разложить на простые множители за разумное время. В CTF чаще всего n — это модуль RSA, и если он плохо сгенерирован, то факторизуется за секунды–минуты. Самые частые слабости:
два близких простых числа
одно из чисел очень маленькое
n — произведение многих маленьких простых
Модульная инверсия Нужна, когда надо «разделить» в модульной арифметике: найти x такой, что a × x ≡ b (mod m). Если b = 1 → это и есть инверсия a по модулю m. Существует, только если НОД(a, m) = 1. Находится через расширенный алгоритм Евклида.
В CTF это встречается везде: расшифровка RSA, подделка подписей, решение линейных сравнений.
Теория чисел (Эйлер, Ферма, Евклид)
Алгоритм Евклида НОД(a, b) = НОД(b, a mod b) → повторяем, пока не получим 0. Очень быстрый даже для огромных чисел.
Малая теорема Ферма Если p простое и a не делится на p → a^(p-1) ≡ 1 (mod p) Отсюда можно быстро считать большие степени по модулю.
Функция Эйлера φ(n) Если знаешь разложение n на простые — φ(n) = n × (1–1/p₁) × (1–1/p₂) × … Используется в RSA (e × d ≡ 1 mod φ(n)) и для проверки, взаимно ли просты числа.
В CTF эти теоремы позволяют:
быстро считать a^b mod m (когда b огромное)
находить секретный ключ в слабом RSA
решать сравнения вида x^k ≡ a (mod p)
Полиномы и интерполяция
Полином степени k однозначно определяется k+1 точками. Если у тебя есть k+1 пар (xᵢ, yᵢ) — можно восстановить весь полином.
В CTF чаще всего встречается интерполяция по Лагранжу или по Ньютону в конечном поле. Типичные задачи:
даны точки (x, secret(x) mod p) → найти secret(0)
восстановить секретный полином по нескольким значениям
Shamir Secret Sharing (секрет разбит на куски-полиномы)
Ключевой момент: все вычисления делаются по модулю большого простого числа p.
Теория игр (Nim, Grundy numbers)
Nim — самая простая и самая важная игра в CTF. Есть несколько кучек камней. За ход можно убрать любое количество камней из одной кучки. Побеждает тот, кто берёт последний камень.
Выигрышная стратегия: посчитать XOR размеров всех кучек. Если XOR = 0 → позиция проигрышная (при идеальной игре). Если XOR ≠ 0 → выигрышная, можно сделать ход в кучку, чтобы новый XOR стал 0.
Grundy number (или nimber) Для более сложных игр: каждой позиции присваивается число — mex (минимальное исключённое) всех grundy дочерних позиций. Для обычного Nim grundy(куча размера n) = n.
В CTF чаще всего:
несколько независимых игр → общий grundy = XOR всех
нужно найти выигрышный ход или доказать, что первый/второй выигрывает
Итог
Главное, что нужно запомнить: почти все математические задачи в CTF сводятся к модульной арифметике, быстрой факторизации слабых чисел, восстановлению полиномов по точкам и XOR-стратегии в играх.
Ключевые слова и термины для запоминания: факторизация, модульная инверсия, теорема Ферма, функция Эйлера, алгоритм Евклида, НОД, интерполяция, конечное поле, Nim, XOR, Grundy number, малая теорема Ферма.
Эти знания позволяют:
факторизовать слабый RSA-модуль и расшифровать флаг
найти инверсию и решить линейное сравнение
восстановить секрет по значениям полинома в Shamir-подобных задачах
мгновенно решать Nim и игры на нескольких кучках/досках
быстро считать огромные степени по модулю
Освой эти 5–6 базовых приёмов — и большинство «математических» крипто-задач начального и среднего уровня станут для тебя рутиной.
Оптимизация и производительность
Оптимизация — это умение писать код, который решает задачу быстро и с маленьким потреблением памяти, даже когда данные огромные. В CTF эта тема в первую очередь живёт в категории Programming (PPC), особенно в hard-задачах и на соревнованиях типа Codeforces-style CTF. Она встречается в задачах, где простое решение работает 10 секунд, а лимит — 1 секунда, или где нужно уместиться в 64 МБ вместо 2 ГБ. Новичку это кажется неважным, но именно из-за неоптимизированного кода 80% людей не решают последние 2–3 задачи на крупных CTF. Когда ты научишься видеть "это O(n²), умрёт" за секунду — ты перестанешь терять баллы на глупых TLE и MLE.
Словарь терминов
Big O
Как быстро растёт время работы при росте размера данных
O(1)
Время работы всегда одинаковое, не зависит от размера
O(n)
Время растёт линейно с размером данных
O(n²)
Время растёт как квадрат размера (обычно два вложенных цикла)
O(log n)
Время растёт очень медленно (делим задачу пополам)
O(n log n)
Самый частый оптимальный вариант для сортировки и многих задач
TLE
Time Limit Exceeded — код слишком медленный
MLE
Memory Limit Exceeded — код жрёт слишком много памяти
memoization
Сохраняем уже посчитанные ответы, чтобы не считать дважды
кэширование
То же самое, что memoization, только чаще про массивы/словари
битовые операции
&, |, ^, <<, >> — быстрые операции напрямую с битами
bit manipulation
Умение решать задачи через побитовые трюки вместо циклов
динамическое программирование
Разбиваем задачу на подзадачи и сохраняем ответы (часто с memo)
пространство состояний
Сколько разных ситуаций мы храним в DP или кэше
Временная и пространственная сложность (Big O)
Big O отвечает на вопрос: "если данных в 10 раз больше — во сколько раз дольше будет работать код?"
Самые важные для CTF:
O(1) — мгновенно, идеал
O(log n) — очень быстро (двоичный поиск)
O(n) — нормально для n ≤ 10⁸
O(n log n) — отлично для n ≤ 10⁷
O(n²) — проходит только если n ≤ 10⁴–10⁵
O(2ⁿ) — умрёт при n > 40
O(n!) — умрёт при n > 12
Простое правило для новичка: если в задаче n ≤ 10⁵ и у тебя два вложенных цикла по n — это O(n²) = 10¹⁰ операций → TLE гарантировано. Нужно либо сократить до O(n log n), либо использовать другой алгоритм.
В CTF почти всегда пишут в описании "n ≤ 10⁶" или "n ≤ 10¹⁸" — это прямой намёк, какое Big O нужно.
Оптимизация кода под лимиты времени/памяти
Лимиты в CTF обычно жёсткие: 1–2 секунды на Python, 0.5–1 секунда на C++, память 256–512 МБ.
Самые частые причины TLE/MLE у новичков:
два вложенных цикла вместо правильного алгоритма
рекурсия без memoization (переполнение стека или миллиарды вызовов)
создание лишних списков размером n×n
использование строк как массивов (в Python строки неизменяемые → копирование при каждом изменении)
Как ускорять в 10–100 раз:
вместо set() в Python используй массив флагов
вместо рекурсии — итеративное DP
вместо сортировки списка пар — сортируй индексы
в C++ используй fast input (читай всё сразу в строку)
В CTF-задачах оптимизация часто решает, получишь ты 100 баллов или 0 — потому что частичные баллы за медленное решение почти никогда не дают.
Memoization и кэширование результатов
Когда одна и та же подзадача считается много раз — сохраняем ответ в словаре или массиве.
Классический пример: числа Фибоначчи. Без memo — 2ⁿ операций, с memo — O(n).
В CTF это спасает в 70% задач на динамическое программирование:
игры на графах
задачи с состоянием (позиция + что-то ещё)
подсчёт путей/вариантов
задачи типа knapsack (рюкзак)
Простое правило: если видишь рекурсию с повторяющимися аргументами — сразу добавляй @lru_cache или свой массив кэша.
В Python @lru_cache(maxsize=None) — это буквально одна строка, которая превращает TLE в AC.
Bit manipulation для ускорения
Битовые операции работают в 32–64 раза быстрее обычных циклов, потому что процессор делает их аппаратно.
Самые полезные трюки в CTF:
проверка бита: if (x & (1 << i))
включить бит: x |= (1 << i)
выключить бит: x &= ~(1 << i)
количество единиц: bin(x).count('1') или x.bit_count() в Python 3.10+
x & (x-1) — убирает младший единичный бит (очень частый трюк)
x && !(x & (x-1)) — проверка, является ли x степенью двойки
Где это спасает:
задачи на множества (вместо set используешь int 64 бита)
задачи с состояниями до 20–30 элементов (2²⁰ = миллион, помещается в массив)
быстрый обход всех подмножеств (SOS DP)
задачи типа "найди уникальное число" (XOR всех чисел)
В CTF битовые трюки часто позволяют решить задачу за O(2ⁿ × n) вместо O(n!) или превратить O(n²) в O(n × 32).
Итог
Главное, что нужно запомнить: в CTF время и память — это ресурс, который кончается очень быстро, и авторы специально делают так, чтобы наивное решение не проходило. Если ты видишь n = 10⁵ и думаешь "два цикла? норм" — ты проиграешь.
Ключевые слова и термины для запоминания: Big O, O(n²), O(n log n), TLE, MLE, memoization, кэширование, bit manipulation, битовые операции, динамическое программирование, @lru_cache, 1<<i, x&(x-1).
Как только ты начнёшь автоматически считать сложность и применять memoization + биты — ты перестанешь получать TLE на задачах, которые все остальные решают. Ты будешь тем парнем, который решает "невозможно жёсткую" задачу за 15 минут, потому что просто написал O(n log n) вместо O(n²). Это и есть разница между 200 и 2000 баллами на CTF.
Основы программирования и алгоритмов
Основы программирования и алгоритмов — это базовые строительные блоки, из которых строится почти всё в CTF: от простого разбора строк до поиска флага в графе или оптимизации перебора. Алгоритм — это чёткий рецепт решения задачи, структура данных — удобный способ хранить информацию, чтобы с ней было легко работать. В категориях misc, crypto, reverse, pwn и forensics эта тема встречается практически в каждой второй задаче — флаг обычно требует либо правильно выбрать структуру, либо написать эффективный поиск/сортировку/перебор. Новичку крайне важно их понять, потому что без базовых знаний даже простые задачи превращаются в часы мучений, а с ними — решаются за минуты. Эти концепции — фундамент, который делает все остальные категории CTF в десятки раз проще и понятнее.
Словарь терминов
Структура данных
Способ удобно хранить и обрабатывать набор элементов
Стек
Структура «последний пришёл — первый ушёл» (как стопка тарелок)
Очередь
Структура «первый пришёл — первый ушёл» (как очередь в магазине)
Хэш-таблица
Супербыстрый словарь: ключ → значение за доли секунды
Дерево
Структура с ветвлением (корень → дети → внуки)
Граф
Набор точек и связей между ними (дороги между городами)
Сортировка
Упорядочивание элементов по возрастанию или убыванию
Бинарный поиск
Поиск в отсортированном массиве за логарифмическое время
BFS
Поиск в ширину (сначала все соседи, потом их соседи)
DFS
Поиск в глубину (идём до конца по одной ветке, потом назад)
Динамическое программирование
Разбиение задачи на маленькие подзадачи и сохранение ответов
Жадный алгоритм
На каждом шаге выбираем локально лучшее решение
Битовые операции
Работа с отдельными битами числа (AND, OR, XOR, сдвиги)
Структуры данных (стек, очередь, хэш-таблицы, деревья, графы)
Стек — как стопка тарелок: класть и брать можно только сверху (push/pop). Используется для обратной польской записи, парсинга скобок, отмены действий.
Очередь — как очередь в кассу: первый добавил — первый и выйдет (enqueue/dequeue). Нужна для задач по порядку, BFS, буферов.
Хэш-таблица — супербыстрый словарь: по ключу мгновенно получаешь значение. В CTF почти всегда используется для подсчёта символов, поиска дубликатов, кэширования.
Дерево — иерархия: есть корень, у него дети, у детей — свои дети. Бинарное дерево поиска — отсортированное дерево, где левое поддерево меньше, правое больше.
Граф — точки (вершины) и связи между ними (рёбра). Может быть направленным или нет, взвешенным или нет. Моделирует дороги, зависимости, соцсети.
В CTF структуры данных — основа большинства задач. Без правильного выбора ты просто не уложишься по времени или памяти.
На практике: видишь задачу на парсинг выражений — используешь стек; нужно обойти все узлы графа — выбираешь BFS или DFS; считаешь количество каждого символа — берёшь хэш-таблицу.
Сортировки и поиск (быстрая сортировка, бинарный поиск, BFS/DFS)
Сортировка — упорядочивание элементов. Быстрая сортировка (quicksort) — одна из самых быстрых на практике: выбираешь опорный элемент, всё меньше — слева, больше — справа, рекурсивно.
Бинарный поиск — поиск в уже отсортированном массиве: каждый раз смотришь середину и отбрасываешь половину. Работает за log₂(n) шагов.
BFS (поиск в ширину) — идёт уровень за уровнем: сначала все соседи, потом их соседи. Находит кратчайший путь в невзвешенном графе.
DFS (поиск в глубину) — идёт до конца по одной ветке, потом возвращается и идёт по другой. Удобен для поиска циклов, компонент связности.
В CTF сортировка и бинарный поиск — база для задач на массивы. BFS/DFS — основа для графов и лабиринтов.
На практике: видишь отсортированный массив — применяешь бинарный поиск; нужно найти кратчайший путь — запускаешь BFS; нужно проверить все варианты — используешь DFS.
Динамическое программирование и жадные алгоритмы
Динамическое программирование (DP) — разбиение сложной задачи на маленькие подзадачи и сохранение ответов, чтобы не считать их заново. Классика: рюкзак, наибольшая возрастающая подпоследовательность, числа Фибоначчи.
Жадный алгоритм — на каждом шаге выбираешь локально лучшее решение, надеясь, что оно приведёт к глобальному оптимуму. Примеры: монеты, интервальное покрытие, минимальное остовное дерево.
В CTF DP — частая тема в задачах на оптимизацию (рюкзак, строки, пути). Жадные — в задачах на расписание, монеты, графы.
На практике: видишь задачу «максимальная сумма без соседних элементов» — это классика DP; нужно выдать сдачу минимальным числом монет — пробуешь жадный подход.
Битовые операции и битовые трюки
Битовые операции — работа с отдельными битами числа: AND (&), OR (|), XOR (^), NOT (~), сдвиги (<<, >>).
Популярные трюки:
x & -x — младший установленный бит
x ^ y — биты, которые отличаются
x >> k — деление на 2^k
(x & (x-1)) == 0 — проверка, степень ли двойки
В CTF битовые операции — основа крипто, оптимизации, масок, поиска подмножеств.
На практике: видишь задачу на подсчёт битов — используешь x & (x-1); нужно перебрать все подмножества — используешь битовую маску от 0 до (1<<n)-1.
Итог
Основы программирования и алгоритмов — это фундамент, на котором строится решение почти всех задач в CTF. В любой категории без понимания структур данных, сортировок, графов и битов ты будешь тратить часы там, где другие справляются за минуты.
Главное запомнить: стек и очередь — для порядка; хэш-таблица — для быстрого поиска; графы решаются BFS/DFS; динамика — для оптимизации; биты — для компактности и скорости.
Ключевые слова/термины выучить: стек, очередь, хэш-таблица, дерево, граф, быстрая сортировка, бинарный поиск, BFS, DFS, динамическое программирование, жадный алгоритм, битовые операции.
Эти знания помогут тебе выбрать правильный способ решения. В задачах ты сможешь использовать стек для парсинга скобок, хэш-таблицу для подсчёта символов, BFS для кратчайшего пути в лабиринте, динамику для задачи на рюкзак или биты для генерации всех подмножеств — и получить флаг за минуты вместо часов.
Программирование на низком уровне
Программирование на низком уровне — это когда ты работаешь не с удобными строками и списками, а напрямую с байтами, битами, адресами памяти и машинными командами. В CTF эта тема в первую очередь относится к категориям pwn (эксплойты), reverse и иногда ppc/crypto. Чаще всего встречается в задачах, где нужно написать эксплойт на переполнение буфера, подделать указатель, обойти проверку или вставить свой код (shellcode). Новичку эти знания нужны, потому что без понимания, как устроена память и как компьютер читает числа, почти невозможно решить ни одну нормальную pwn-задачу и очень сложно понять, почему твой эксплойт падает. Когда разберёшься в байтах и указателях — уровень задач, которые ты сможешь решать, вырастет с easy до medium-hard за несколько недель.
Словарь терминов
байт
8 бит, число от 0 до 255, самая маленькая удобная единица памяти
бит
Самая маленькая единица — 0 или 1
little-endian
Младший байт числа лежит по меньшему адресу памяти
big-endian
Старший байт числа лежит по меньшему адресу памяти
endianness
Порядок, в котором байты многобайтового числа хранятся в памяти
буфер
Выделенный кусок памяти фиксированного размера для данных
переполнение буфера
Когда пишем в буфер больше байтов, чем он может вместить
off-by-one
Ошибка, когда считаем на один байт больше или меньше нужного
указатель
Число, которое хранит адрес в памяти
pointer arithmetic
Арифметика с указателями: прибавление сдвигает адрес на N элементов
stack
Память, где хранятся локальные переменные и адреса возврата
heap
Память для данных, которые выделяются динамически
shellcode
Короткий машинный код, который обычно запускает shell
return address
Адрес в стеке, куда программа вернётся после завершения функции
ASLR
Случайное расположение адресов в памяти при каждом запуске
Работа с байтами, битами, endianness (little/big)
Компьютер хранит всё в виде последовательности байтов. Один байт = 8 бит = число от 0 до 255. Когда число больше 255 (например 2025), его разбивают на несколько байтов.
Пример: число 2025 в hex = 0x07E9 В little-endian (почти все современные x86/x64) оно лежит в памяти так: E9 07 В big-endian (многие сетевые протоколы, старые системы) — 07 E9
Почему это важно в CTF:
в большинстве pwn-задач адреса и числа нужно паковать в little-endian
если перепутать порядок байтов — указатель станет совершенно другим и эксплойт упадёт
часто в крипто-задачах числа хранят big-endian, а в бинарниках — little
Запомни навсегда: на большинстве платформ CTF (linux x64) — little-endian в сетевых протоколах, некоторых крипто-форматах — big-endian всегда проверяй, откуда пришли данные
Буферные переполнения и off-by-one ошибки
Буфер — это массив фиксированного размера, например char buf[64]. Если программа позволяет записать в него больше 64 байт — лишние байты затирают то, что лежит дальше в памяти.
Что обычно затирается (в порядке частоты в CTF):
другие локальные переменные
saved frame pointer (rbp)
return address — самое вкусное, потому что можно подменить адрес возврата
Off-by-one — это когда программа разрешает записать ровно размер буфера или на один байт больше. Один байт может затереть младший байт следующей переменной или null-терминатор строки — и дальше начинается хаос.
В CTF чаще всего:
переполняем буфер → переписываем return address на адрес нашей победной функции или на shellcode
off-by-one используют, чтобы чуть-чуть подправить указатель или флаг в соседней переменной
Pointer arithmetic и memory layout
Указатель — это просто число, которое означает «адрес в памяти». Если у тебя есть указатель на начало массива int *arr, то arr+1 — это уже адрес следующего int (на x64 +8 байт).
Простые правила pointer arithmetic: char *p → p+1 = адрес +1 байт int *p → p+1 = адрес +4 байта (32-bit) или +8 байт (64-bit) struct *p → p+1 = адрес + sizeof(структуры)
Memory layout в типичной pwn-задаче (стек сверху вниз):
высокие адреса
аргументы main
локальные переменные функции
saved rbp
return address
стек фрейм вызывающей функции
…
низкие адреса
Зная смещения, можно посчитать, на сколько байт надо переполнить, чтобы достать до return address.
В CTF это ключевой навык: посчитать offset от буфера до return address и правильно упаковать адрес в байты.
Inline assembly и shellcode в PPC
Shellcode — это короткая последовательность машинных инструкций, которую мы хотим выполнить. Самый классический пример — запустить /bin/sh.
В PPC-задачах (programming pwnable crypto) shellcode часто нужно:
вставить в переполнение
закодировать определённым способом (чтобы обойти фильтры)
сделать position-independent (чтобы работал при любом адресе)
Inline assembly — когда прямо в C-коде пишешь asm("…"). В CTF это используют редко, но иногда дают исходник с asm-вставками — и нужно понять, что именно делает этот кусок.
Типичные требования к shellcode в CTF:
длина до 50–100 байт
без нулевых байтов (если strcpy)
без определённых байтов (если есть фильтр bad chars)
position-independent (без жёстких адресов)
Новичку достаточно запомнить: shellcode — это просто байты, которые процессор выполнит как команды, и их можно вставить в стек/heap через переполнение.
Итог
Главное, что нужно запомнить: компьютер работает с байтами и адресами, а не со строками и удобными типами. Перепутал endianness, не посчитал смещение, не учёл off-by-one — и эксплойт не сработает.
Ключевые слова и термины для запоминания: little-endian, big-endian, буферное переполнение, off-by-one, return address, указатель, pointer arithmetic, stack, shellcode, ASLR, байт, бит.
Эти знания позволяют:
правильно паковать адреса в payload
считать, сколько байт нужно отправить, чтобы достать до return address
понять, почему программа крашится именно на этом offset
писать простейшие эксплойты на классическое stack overflow
Освой это — и pwn-задачи перестанут быть китайской грамотой.
Работа с большими числами и арифметикой
Работа с большими числами и арифметикой — это умение считать и работать с очень длинными числами (сотни и тысячи цифр), которые не помещаются в обычные переменные типа int или long. В обычном программировании такие числа почти не нужны, но в криптографии и CTF они встречаются постоянно. В категории crypto эта тема — одна из самых базовых и частых: почти каждая задача требует либо факторизации большого числа, либо вычислений по модулю, либо перевода между системами счисления. Новичку важно понять, что обычные языки программирования (кроме Python) не умеют работать с такими числами «из коробки», и без правильных приёмов ты просто не сможешь решить задачу. Знание этих методов позволяет за минуты делать то, что без них занимает часы или вообще невозможно.
Словарь терминов
Большие целые числа
Числа, которые намного больше обычных int/long (сотни цифр)
BigInteger
Класс в Java для работы с большими числами
mpz
Тип в библиотеке GMP для очень больших целых чисел
Python int
Встроенный тип в Python, который сам умеет быть бесконечно большим
Модульная арифметика
Все вычисления делаются по модулю (остаток от деления)
Быстрое возведение в степень
Способ посчитать a^b mod m за log(b) операций
Китайская теорема об остатках
Способ найти число по его остаткам от деления на несколько чисел
CRT
Короткое название китайской теоремы об остатках
Base conversion
Перевод числа из одной системы счисления в другую
Большие целые числа (BigInteger в Java, mpz в GMP, Python int)
Обычные переменные int или long в большинстве языков умеют хранить числа только до примерно 10¹⁸–10¹⁹. В криптографии (RSA, ECC) числа имеют сотни и тысячи цифр — обычные типы просто не справляются.
Python int — встроенный тип, который автоматически становится большим, когда число перестаёт помещаться. Ты просто пишешь 123**456 и Python всё считает.
BigInteger в Java — специальный класс, который нужно явно использовать. Операции пишутся как методы: a.multiply(b), a.modPow(b, m).
mpz в GMP (библиотека C) — очень быстрая реализация больших чисел, используется в SageMath и многих крипто-библиотеках.
В CTF большие числа — основа почти всех крипто-задач. Без поддержки big int ты просто не сможешь посчитать n = p × q или расшифровать RSA.
На практике: видишь число на 200 цифр — в Python просто работаешь с ним как с обычным int; в Java или C — используешь BigInteger или mpz.
Модульная арифметика и быстрая возведение в степень
Модульная арифметика — все вычисления делаются по модулю (остаток от деления). Вместо a × b считаешь (a × b) mod m. Это позволяет работать с огромными числами, не выходя за пределы m.
Быстрое возведение в степень — обычное a^b требует b умножений. Быстрый способ (exponentiation by squaring) делает это за log₂(b) операций: a², (a²)², и так далее.
В CTF модульная арифметика — основа RSA, ECDSA, Diffie-Hellman. Без неё ты не сможешь посчитать c = m^e mod n или g^x mod p.
На практике: видишь задачу RSA — сразу считаешь всё по модулю n; нужно посчитать 123456789^987654321 mod 10^9+7 — используешь быстрое возведение, иначе будет слишком долго.
Китайская теорема об остатках (CRT)
Китайская теорема об остатках говорит: если у тебя есть несколько уравнений x ≡ a₁ (mod m₁), x ≡ a₂ (mod m₂), … и модули m₁, m₂ попарно взаимно просты — то есть ровно одно решение по модулю m₁×m₂×…
CRT позволяет собрать большое число из его остатков по маленьким модулям. Очень полезно в RSA, когда известны остатки по p и q.
В CTF CRT — классика для задач на RSA, когда известны остатки по модулям или в мультипрайм-RSA.
На практике: видишь два остатка x ≡ 123 mod 10007 и x ≡ 456 mod 10009 — применяешь CRT — получаешь x по модулю 10007×10009 — и расшифровываешь сообщение.
Операции с числами в разных системах счисления (base conversion)
Система счисления — способ записи числа: двоичная (base 2), восьмеричная (base 8), десятичная (base 10), шестнадцатеричная (base 16), base36, base58, base64.
Перевод из одной системы в другую — это деление на основание и запись остатков (для перевода в большую) или умножение на основание и перенос разряда (для перевода из большой).
В CTF переводы между базами — одна из самых частых тем в misc и crypto. Флаг часто закодирован в base58, base32 или custom base.
На практике: видишь строку из букв и цифр — пробуешь декодировать как base58 или base36 — получаешь читаемый текст или число; видишь длинное число — переводишь в hex или binary и видишь флаг в битах.
Итог
Работа с большими числами и арифметикой — это основа крипто-задач в CTF: без неё ты просто не сможешь посчитать ничего серьёзного. В crypto это встречается почти всегда — флаг требует модульных вычислений, CRT, перевода баз или работы с числами на сотни цифр.
Главное запомнить: Python сам работает с большими числами; всё в крипто считается по модулю; быстрое возведение в степень — log(b) операций; CRT собирает число из остатков; перевод между базами — частая маскировка флага.
Ключевые слова/термины выучить: большие целые числа, BigInteger, модульная арифметика, быстрое возведение в степень, китайская теорема об остатках, CRT, base conversion.
Эти знания помогут тебе сразу понять, что задача на RSA или ECC требует модульной арифметики и больших чисел. В задачах ты сможешь посчитать c = m^e mod n в Python за секунду, применить CRT к остаткам и расшифровать сообщение, быстро возвести число в огромную степень по модулю или перевести длинную строку из base58 в читаемый флаг — и решить крипто-задачу без мучений.
Работа с файлами и форматами
В большинстве задач CTF (особенно в категориях Crypto, Forensics, Reverse и даже иногда Web) тебе дают какой-то файл и просят найти флаг. Файл почти никогда не открывается обычной программой — это или картинка с секретом внутри, или архив с паролем, или программа, или вообще мусор с зашифрованными данными. Работа с файлами и форматами — это первый и самый важный шаг: понять, что тебе дали, где лежат полезные байты и как их достать. Без этих навыков ты не дойдёшь до криптографии, реверса или декодирования — просто не доберёшься до данных. Новичку эта тема кажется скучной, но именно она решает, решишь ты задачу за 20 минут или будешь сидеть неделю.
Словарь терминов
magic bytes
Первые 4–8 байтов файла, по которым понятно его тип
hex-дамп
Текстовое представление файла, где каждый байт — две hex-цифры
offset
Номер позиции (в байтах) от начала файла
chunk
Отдельный блок данных внутри файла (особенно в PNG)
CRC
Контрольная сумма в конце блока, проверяет целостность
little-endian
Числа записаны от младшего байта к старшему
big-endian
Числа записаны от старшего байта к младшему
zlib
Алгоритм сжатия, который прячется внутри PNG, ZIP, PDF
central directory
Таблица в конце ZIP-архива со списком всех файлов внутри
сигнатура
То же самое, что magic bytes — начало, по которому узнают формат
парсинг
Программа разбирает структуру файла по его правилам
кастомный формат
Формат, который автор задачи придумал специально для CTF
стеганография
Прятание данных внутри картинки или другого файла незаметно
padding
Дополнительные байты в конце, чтобы данные стали нужной длины
endianness
Порядок байтов при записи многобайтовых чисел (little или big)
Парсинг бинарных форматов (PNG, JPEG, ELF, PE, ZIP)
Каждый нормальный файл имеет чёткую структуру:
несколько байтов в начале говорят «я PNG / JPEG / ZIP / исполняемый файл»
дальше идут заголовки с информацией (размер, дата, количество файлов и т.д.)
потом сами данные, часто сжатые или разбитые на куски
PNG Начинается всегда с 89 50 4E 47 0D 0A 1A 0A Состоит из чанков: каждый чанк имеет тип (IHDR, IDAT, tEXt, zTXt и др.), длину и контрольную сумму CRC. Очень часто флаг лежит в текстовом чанке (tEXt или zTXt) — его можно достать, не открывая картинку.
JPEG Начинается с FF D8 FF Состоит из сегментов (APP0, APP1, COM и т.д.). Флаг могут спрятать в комментарии (COM) или в EXIF-данных (APP1).
ZIP Начинается с 50 4B 03 04 (каждый файл внутри) В самом конце лежит central directory — там имена файлов, их смещения и часто комментарий архива. Пароль иногда лежит именно в комментарии или в имени скрытого файла.
ELF и PE Это исполняемые файлы Linux и Windows. Внутри есть секции (.text, .data, .rodata), где хранятся строки, ключи, константы. В CTF часто нужно найти строку или массив байтов в этих секциях.
В задачах почти всегда нужно написать маленький скрипт, который находит нужный чанк/сегмент/секцию и вырезает оттуда байты.
Работа с hex-дампами и байт-кодировками
Часто вместо файла тебе дают длинный текст вида:
Это hex-дамп — каждый байт представлен двумя символами 0–9 или A–F. Левая часть — смещение (offset) в шестнадцатеричном виде.
Что обычно делают в CTF:
ищут сигнатуру (PNG → 89504E47, ZIP → 504B0304, gzip → 1F8B, JPEG → FFD8FF)
считают, сколько байт пропустить до неё
копируют нужный кусок и превращают обратно в бинарный файл
Часто встречаются ещё:
base64 внутри hex-дампа
hex внутри base64
числа в little-endian вместо big-endian
весь файл XOR-нутый одним байтом
Если видишь hex-дамп — первое, что делаешь: ищешь глазами известные сигнатуры.
Извлечение данных из повреждённых файлов
Авторы обожают ломать файлы, чтобы они не открывались в обычных программах.
Популярные поломки:
стёрты или изменены magic bytes
испорчен CRC в PNG (последние 4 байта каждого чанка)
сломан заголовок IHDR (неверная ширина/высота)
удалена/испорчена central directory в ZIP
добавлен мусор в начало или конец файла
Как чинить (основные способы):
В hex-редакторе ищешь сигнатуру дальше начала файла и вырезаешь от неё
Для PNG — исправляешь CRC вручную или скриптом (есть готовые способы)
Для ZIP — пробуешь восстановить central directory или используешь режим ремонта
Меняешь значения ширины/высоты в IHDR на те, которые выглядят правдоподобно
Самый частый случай в CTF — PNG с неправильным размером в IHDR или с битым CRC. Поправил пару байтов — картинка открылась, а в ней уже лежит флаг или зашифрованный кусок.
Генерация и анализ кастомных форматов
Иногда тебе дают файл, у которого вообще нет известной сигнатуры — автор придумал свой формат.
Как понять, что это кастомный формат:
нет ничего похожего на PNG/ZIP/JPEG в начале
много повторяющихся кусков вида [4 байта длина] [данные этой длины]
странные последовательности четырёхбайтных чисел
есть строки, но они перемешаны с непонятными байтами
Что делать:
открываешь в hex-редакторе и ищешь повторяющиеся паттерны
предполагаешь, что 4 байта — это длина следующего блока
пишешь маленький код, который идёт по файлу и читает: длина → прыгает на длину байтов → снова длина → и т.д.
если попадаются строки — сразу смотришь, нет ли среди них флага или ключа
Очень часто кастомный формат — это просто несколько зашифрованных кусков, склеенных вместе, с длинами перед каждым куском и каким-нибудь XOR-ключом в начале.
Итог
Главное, что нужно запомнить: в 80–90% задач тебе сначала нужно достать полезные байты из файла — и только потом начинается настоящая криптография, реверс или декодирование. Умение быстро находить сигнатуру, вырезать кусок и чинить простые поломки — это суперсила новичка.
Ключевые слова и термины для запоминания: magic bytes, hex-дамп, offset, chunk, CRC, zlib, little-endian, big-endian, central directory, сигнатура, парсинг, кастомный формат, стеганография.
Как только ты начнёшь за 3–5 минут определять, что за файл перед тобой и где в нём данные — количество решаемых тобой задач вырастет в разы. Это как научиться открывать дверь перед тем, как пытаться разгадать, что лежит в комнате — без первого шага второй бессмыслен.
Работа с графикой и изображениями
Работа с графикой в CTF — это умение читать, изменять и прятать информацию внутри картинок, а также понимать, как устроены сами файлы изображений. В первую очередь эта тема относится к категориям Steganography, Forensics и Crypto (PPC). Чаще всего встречается в задачах, где тебе дают картинку (PNG, GIF, BMP, JPEG) и нужно найти спрятанный флаг, ключ или зашифрованное сообщение. Новичку важно её освоить, потому что стеганография — одна из самых популярных тем на тренировочных платформах и в соревнованиях начального-среднего уровня. Когда ты научишься быстро находить и извлекать скрытые данные из изображений — ты начнёшь решать 30–50% всех «forensic» и «crypto» задач, которые раньше проходили мимо.
Словарь терминов
стеганография
Способ прятать секретные данные внутри обычной картинки
LSB
Самый младший бит каждого байта цвета — туда часто прячут данные
PNG
Формат изображения без потерь, очень удобен для стеганографии
GIF
Формат с поддержкой анимации и ограниченной палитрой цветов
BMP
Простейший формат без сжатия, данные лежат почти «как есть»
RGB
Цветовая модель: красный, зелёный, синий — основные каналы
канал
Один из компонентов цвета (красный, зелёный, синий или альфа)
пиксель
Точка на картинке, обычно состоит из 3–4 байт (RGB / RGBA)
палитра
Таблица цветов в GIF — всего 256 цветов вместо миллионов
QR-код
Двумерный штрихкод, в котором можно закодировать текст или ссылку
штрихкод
Полоски разной ширины, кодируют цифры или символы
альфа-канал
Дополнительный канал прозрачности (в PNG, иногда используется для данных)
плоскость битов
Все биты одного уровня (например все младшие биты красного канала)
Генерация и анализ изображений (PNG, GIF, BMP)
PNG Самый популярный формат в CTF. Не сжимает с потерями, поэтому данные можно прятать без заметных изменений. Состоит из чанков: IHDR (размеры), IDAT (пиксели), tEXt / zTXt (текст), iTXt. Очень часто флаг прячут именно в текстовых чанках или в альфа-канале.
GIF Поддерживает только 256 цветов (палитра). Можно прятать данные в порядке цветов в палитре или в самом маленьком бите каждого индекса. Часто используют для анимированных стеганограмм — данные в разных кадрах.
BMP Очень простой формат без сжатия. После заголовка сразу идут пиксели (обычно 3 байта на пиксель: BGR). Данные лежат почти в чистом виде — удобно для LSB-стеганографии.
В CTF чаще всего дают PNG — ищи в нём лишний текстовый чанк или странности в альфа-канале. Если картинка выглядит слишком «чистой» — скорее всего там LSB.
Математика изображений (цветовые модели RGB/HSV, фильтры)
Каждый пиксель — это набор чисел (обычно 3 или 4 байта). RGB — самый частый: 0–255 для красного, зелёного, синего.
Примеры, что можно делать:
взять только красный канал → получается чёрно-белое изображение с красными оттенками
взять младший бит каждого канала → получается почти чёрная картинка с белыми точками там, где был спрятан бит 1
сложить все каналы → примерно яркость
взять разницу между двумя картинками → видно, где что-то менялось
В CTF часто просят:
выделить один канал
посмотреть на младшие биты (LSB)
применить XOR между двумя похожими картинками
увеличить контраст / инвертировать цвета, чтобы увидеть скрытый текст
Эти операции помогают увидеть то, что не видно невооружённым глазом.
Steganography и LSB в PPC
LSB (Least Significant Bit) — самый популярный метод стеганографии. Идея: младший бит каждого байта почти не влияет на цвет. Если поменять младшие биты на 0 и 1 — человек почти не заметит разницы, а мы можем закодировать 1 бит на каждый канал.
Обычно:
1 пиксель RGB = 3 бита (по одному на канал)
1 пиксель RGBA = 4 бита
на картинке 1000×1000 пикселей можно спрятать ~375 КБ данных (3 бита на пиксель)
В CTF встречаются варианты:
данные только в красном канале
данные в альфа-канале (PNG)
данные в определённой плоскости битов (не только LSB)
данные XOR-нутые с каким-то ключом
данные спрятаны в порядке пикселей (не по строкам, а змейкой, по спирали и т.д.)
Самый простой способ проверить: вытащить все младшие биты и посмотреть, получается ли осмысленная картинка или текст.
QR-коды, штрихкоды и их декодирование
QR-код Квадратная картинка из чёрных и белых модулей. Может содержать до нескольких тысяч символов: URL, текст, флаг, Wi-Fi-пароль и т.д. Часто в CTF QR-код либо повреждён (надо починить), либо содержит зашифрованные данные, либо там несколько QR-кодов в одном.
Штрихкод Полоски разной ширины (1D barcode). Самые частые: Code 128, Code 39, EAN-13. В CTF обычно либо спрятан внутри картинки, либо нужно сгенерировать свой.
Типичные задачи:
прочитать QR-код, который не читается обычным сканером
найти QR-код, спрятанный в LSB другой картинки
восстановить повреждённый QR-код (дорисовать недостающие модули)
декодировать штрихкод, который нарисован криво или с шумом
Итог
Главное, что нужно запомнить: почти все задачи с картинками в CTF — это либо LSB-стеганография, либо спрятанные данные в структуре файла (PNG-чанк, альфа, палитра), либо QR-код/штрихкод.
Ключевые слова и термины для запоминания: LSB, стеганография, PNG, GIF, BMP, RGB, канал, пиксель, альфа-канал, QR-код, штрихкод, плоскость битов, палитра.
Эти знания позволяют:
быстро проверить картинку на наличие LSB-данных
вытащить скрытый текст или картинку из младших битов
открыть спрятанный чанк в PNG
прочитать QR-код, который другие не видят
понять, где именно автор спрятал флаг — в цветах, в структуре или в другом формате
Освой эти базовые приёмы — и большинство «картинковых» задач начального и среднего уровня перестанут быть проблемой.
Разное и необычные техники
Разное и необычные техники — это всё то, что не укладывается в классические категории CTF: странные языки программирования, файлы, которые одновременно являются несколькими форматами сразу, самодельные виртуальные машины и хитрые способы передавать данные туда, где их никто не ждёт. В CTF эта тема в первую очередь относится к Misc, Forensics, Reverse и иногда Crypto. Чаще всего такие задачи появляются на соревнованиях среднего и высокого уровня, где авторы хотят удивить и заставить думать нестандартно. Новичку важно хотя бы знать, что такие вещи существуют, потому что без понимания «это вообще возможно?» ты просто закроешь задачу и пойдёшь дальше, хотя решение было в 5 минутах. Когда ты научишься распознавать эти необычные приёмы — ты начнёшь решать те задачи, которые 90% участников даже не открывают.
Словарь терминов
эзотерический язык
Язык программирования, созданный специально, чтобы быть странным и сложным
Brainfuck
Эзотерический язык с всего 8 командами и одной лентой памяти
Malbolge
Один из самых сложных эзотерических языков, почти невозможно писать вручную
polyglot
Файл, который одновременно является корректным в нескольких форматах
ZIP/JPG polyglot
Архив, который ещё и открывается как картинка
custom VM
Виртуальная машина, которую автор написал специально для задачи
bytecode
Промежуточный код, который выполняет виртуальная машина
reverse engineering
Разбор чужого кода, чтобы понять, что он делает
data exfiltration
Тайная передача данных из системы наружу
side-channel
Передача информации через побочные эффекты (время, звук, потребление энергии)
steganography в коде
Прятание данных внутри программы или скрипта
obfuscation
Намеренное усложнение кода, чтобы его было трудно читать
Esoteric programming languages (Brainfuck, Malbolge)
Эзотерические языки (esolangs) придуманы не для удобства, а для прикола, демонстрации сложности или как вызов.
Brainfuck Самый известный. Имеет всего 8 символов: > < + - . , [ ]
— сдвиг указателя вправо < — влево
— прибавить 1 к текущей ячейке
— отнять 1 . — вывести символ , — ввести символ [ ] — цикл пока текущая ячейка не 0
В CTF часто дают программу на Brainfuck и просят:
расшифровать вывод
найти input, который даёт определённый output
модифицировать код, чтобы он вывел флаг
Malbolge Считается одним из самых сложных языков для написания. Каждая команда меняет сам код после выполнения — поэтому почти невозможно предсказать поведение. В CTF встречается редко, но если дают — обычно нужно просто запустить готовый код и посмотреть вывод.
В задачах с эзотерикой главное — не пытаться писать код вручную, а найти интерпретатор и понять логику.
Polyglot файлы и форматы (ZIP/JPG/PDF)
Polyglot — это файл, который можно открыть разными программами и в каждом случае он будет валидным.
Самые популярные комбинации в CTF:
ZIP + JPG JPG начинается с FF D8 FF, ZIP — с 50 4B 03 04. Можно сделать так, чтобы начало было JPG, а дальше — ZIP-архив. Просмотрщик картинок читает до конца JPG-данных, архиватор — игнорирует начало и читает с сигнатуры ZIP.
ZIP + PDF PDF начинается с %PDF, ZIP — вставляется после или с хитрым расположением central directory.
GIF + ZIP GIF89a + ZIP-данные.
Как это используют в CTF:
дают один файл, он открывается как картинка, но внутри ещё архив с флагом
или наоборот — архив, но если открыть как картинку, видно скрытое сообщение
иногда несколько вложенных polyglot (ZIP внутри JPG внутри PDF)
Самый простой способ проверить — попробовать открыть файл разными программами: просмотрщик изображений, архиватор, pdf-ридер.
Custom VM и bytecode reverse
Custom VM — виртуальная машина, которую автор написал специально для одной задачи. Обычно это очень простая машина с 10–30 командами, своей памятью и регистрами.
Что обычно дают:
дамп bytecode (последовательность байт или чисел)
описание команд (opcode + аргументы)
иногда дизассемблер или отладчик от автора
Типичные задачи:
понять, что делает каждая команда
перевести bytecode в читаемый вид
найти input, который заставит VM вывести флаг
модифицировать bytecode, чтобы пропустить проверку
восстановить исходный алгоритм (часто шифрование или хэш)
В CTF такие задачи учат терпению и внимательному чтению описания — почти всегда VM описана подробно.
Data exfiltration через необычные каналы
Data exfiltration — это когда программа должна тайно передать данные (флаг) наружу, но обычные способы (файлы, сеть) запрещены или мониторятся.
Необычные каналы в CTF:
через длительность сна (sleep 1 если бит 1, sleep 0.1 если 0)
через количество выделенной памяти
через разницу во времени ответа
через порядок DNS-запросов
через ICMP-пакеты (ping)
через изменение заголовков HTTP в определённом порядке
через ошибки в логах
через звуковые частоты (если есть аудио-вывод)
В задачах чаще всего нужно:
либо поймать и декодировать канал
либо написать свою программу, которая передаёт данные именно таким способом
Главное — понять, какой именно побочный эффект используется для передачи 0 и 1.
Итог
Главное, что нужно запомнить: в CTF есть задачи, которые специально сделаны странными, чтобы ты вышел за рамки привычного мышления. Если видишь что-то очень необычное — скорее всего это и есть ключ.
Ключевые слова и термины для запоминания: эзотерический язык, Brainfuck, polyglot, ZIP/JPG polyglot, custom VM, bytecode, data exfiltration, side-channel, obfuscation.
Эти знания помогают:
не закрывать задачу сразу, увидев Brainfuck или непонятный файл
пробовать открыть один и тот же файл в 3–4 разных программах
читать описание VM очень внимательно и переводить байты в команды
замечать, что время ответа или потребление памяти меняется не случайно
решать задачи, которые большинство участников считают «невозможными»
Когда освоишь эти приёмы — ты станешь тем, кто берёт первые баллы за «crazy misc», пока остальные пишут «wtf is this».