Главная / Блог / Regex и grep для поиска флагов CTF в дампах

11 мин.01

Regex и grep для поиска флагов CTF в дампах

Regex и grep для поиска флагов CTF в дампах

На прошлом jeopardy-CTF организаторы выдали дамп в 1.8 ГБ — системные логи, перемешанные с base64-мусором и обрывками бинарных данных. Из двухсот участников первый флаг за 40 секунд сдали четверо. Все использовали одну команду: grep -Eo с правильным regex-паттерном. Остальные открывали файл в less или nano, которые благополучно зависали, пытаясь отрисовать два миллиона строк.

Разница между «сдал таск» и «потерял час» на CTF часто сводится к одной строке в терминале. Ниже — пошаговый разбор regex и grep для поиска флагов CTF: от простейшего текстового совпадения до PCRE-паттернов, конвейеров декодирования и оптимизации на файлах размером в гигабайты.

Как устроены CTF-флаги и почему grep "flag" не работает

Перед тем как что-то запускать, разберёмся с форматом того, что ищем. Подавляющее большинство CTF-соревнований используют шаблон PREFIX{содержимое}, где PREFIX — имя платформы или стандартный маркер: Подробнее — в нашем материале про создание ctf заданий.

  • flag{some_text_here} — самый распространённый формат на jeopardy-CTF
  • CTF{...}, picoCTF{...}, HTB{...}, codeby{...} — привязка к конкретной платформе
  • FLAG{...} или Flag{...} — вариации регистра, иногда намеренные
  • Нестандартные префиксы: key{...}, secret{...}, иногда просто хеш-строка без скобок

Первая ошибка новичка — команда grep "flag" dump.txt. В двухгигабайтном логе слово «flag» встретится тысячи раз: в аргументах командной строки (--flag), в именах переменных, в комментариях. Получите страницы мусора. Поиск флага в дампе CTF требует regex-паттерна, который точно описывает формат флага — с фигурными скобками, с конкретным содержимым.

Базовая логика: нам нужно регулярное выражение для flag{}, которое матчит слово flag, за ним открывающую фигурную скобку, затем произвольное содержимое и закрывающую скобку. На языке regex это flag\{[^}]+\} — буквальные символы flag, экранированная \{ (потому что { — метасимвол в regex), один или более символов кроме } ([^}]+) и закрывающая \}. Экранирование обязательно: без обратных слешей grep интерпретирует фигурные скобки как квантификатор повторения, а не как часть искомого текста.

grep -E -o: примеры использования для извлечения флагов

Два флага утилиты grep, которые решают 70% CTF-тасков — -E и -o. Без них работать можно, но заметно больнее.

Флаг -E переключает grep в режим Extended Regular Expressions (ERE). В ERE метасимволы +, ?, | и группирующие скобки () работают напрямую, без экранирования обратным слешем. Без -E пришлось бы писать grep 'flag\{[^}]\+\}' — обратите внимание на \+ вместо +. С -E паттерн чище: grep -E 'flag\{[^}]+\}'.

Флаг -o выводит только совпавшую часть строки, а не всю строку целиком. Без -o grep покажет строку лога длиной в тысячу символов, внутри которой где-то спрятан флаг. С -o получаете ровно flag{ваш_ответ} — и ничего лишнего. На CTF это экономит нервы.

Команда grep -Eo 'flag\{[^}]+\}' dump.txt — базовая рабочая лошадка. Её стоит запускать первой на любом CTF-таске, где дан текстовый файл.

Если формат флага заранее неизвестен, паттерн расширяется: grep -Eoi '[a-zA-Z0-9_]+\{[^}]+\}' dump.txt. Здесь [a-zA-Z0-9_]+ матчит любое «слово» перед фигурными скобками, а флаг -i добавляет нечувствительность к регистру. Такая команда поймает FLAG{}, CTF{}, Key{} и любой другой формат с фигурными скобками.

regex паттерны для CTF: от flag{} до нестандартных форматов

На практике regex-паттерны приходится адаптировать под конкретное соревнование. Вот набор, который покрывает большинство сценариев:

grep -Eo 'flag\{[^}]+\}' dump.txt
grep -Eo 'picoCTF\{[^}]+\}' dump.txt
grep -Eoi '(flag|ctf|key|secret|hack)\{[^}]+\}' dump.txt
grep -Eo '[A-Fa-f0-9]{32}' dump.txt
grep -Eo '[A-Fa-f0-9]{64}' dump.txt
grep -Po 'flag\{.+?\}' dump.txt

Первые три строки — поиск по конкретному или обобщённому формату PREFIX{...}. Четвёртая и пятая — поиск MD5 и SHA-256 хешей, когда флаг — голый хеш без скобок (32 или 64 шестнадцатеричных символа). Шестая использует -P (PCRE) с нежадным квантификатором .+? — об этом ниже.

Чередование через | позволяет искать несколько форматов за один проход по файлу. Команда grep -Eoi '(flag|ctf|key|secret)\{[^}]+\}' dump.txt найдёт flag{...}, CTF{...}, key{...} и secret{...} одновременно. Вместо четырёх проходов grep делает один — на файле в гигабайт это ощутимо.

Отдельная ловушка — жадные квантификаторы. Если в строке лога встречается flag{abc} мусор flag{real_answer}, паттерн с жадным .+ захватит всё от первой открывающей до последней закрывающей скобки: flag{abc} мусор flag{real_answer}. Нежадный .+? (доступен только с флагом -P) вернёт два отдельных результата: flag{abc} и flag{real_answer}. Мелочь, а на CTF может стоить 15 минут.

Парсинг логов Linux регулярными выражениями через PCRE

Флаг -P в GNU grep открывает доступ к Perl-Compatible Regular Expressions. Для CTF тут два ключевых инструмента:

Нежадные квантификаторы. Уже упомянутый .+? вместо .+. В ERE (режим -E) нежадных квантификаторов нет — это главная причина переключаться на -P для сложных тасков.

Lookahead/lookbehind. Если нужно вытащить только содержимое флага без скобок, пригодится конструкция grep -Po '(?<=flag\{)[^}]+(?=\})' dump.txt. Ретроспективная проверка (?<=flag\{) означает «перед совпадением должно стоять flag{», опережающая (?=\}) — «после совпадения должно стоять }». Результат — только текст между скобками. Удобно, когда платформа принимает ответ без обрамления flag{...}.

Ограничение, о котором забывают: -P — расширение GNU grep. На macOS стоит BSD grep, где -P не поддерживается. Варианты: поставить GNU grep через brew install grep (команда станет ggrep -P) или использовать pcregrep, который умеет PCRE нативно.

Парсинг логов Linux регулярными выражениями в CTF-контексте выходит за рамки простого flag{}. Организаторы прячут флаги в HTTP-заголовках, cookie, в base64-строках внутри JSON. Для таких случаев конвейерный подход работает лучше монолитного regex: сначала grep вычленяет подозрительные строки, потом cut или awk извлекает нужное поле, потом base64 -d декодирует. Об этом — в разделе про кодировки.

Как найти флаг в большом текстовом файле

CTF-дампы бывают большими. 500 МБ — обычное дело для forensics. 2 ГБ и больше — встречается на продвинутых соревнованиях. Обработка больших логов командной строкой требует нескольких трюков, и вот какие реально работают:

LC_ALL=C — переключает grep в однобайтовую локаль вместо UTF-8. На файлах без кириллицы (а большинство CTF-дампов на английском) это даёт ускорение в 5-10 раз. Причина простая: в UTF-8 grep проверяет валидность многобайтовых последовательностей на каждом символе. В локали C каждый байт — отдельный символ, проверка не нужна. Используется так: LC_ALL=C grep -Eo 'flag\{[^}]+\}' huge_dump.txt. Я всегда начинаю с этого.

-m 1 — остановиться после первого совпадения. Если знаете, что флаг в файле один (а в большинстве CTF-тасков так и есть), grep -Eom1 'flag\{[^}]+\}' dump.txt прекратит чтение файла сразу после первого матча. На файле в 2 ГБ разница — минуты, потому что grep не дочитывает оставшийся хвост.

-a (он же --binary-files=text) — заставляет grep обрабатывать бинарные файлы как текстовые. Без этого grep выдаст Binary file matches и остановится, не показав совпадение. В CTF-дампах часто попадаются бинарные вкрапления — забытые заголовки, обрывки изображений.

strings перед grep — утилита strings извлекает из файла только печатные последовательности (по умолчанию от 4 символов). Конвейер strings dump.bin | grep -Eo 'flag\{[^}]+\}' работает быстрее и чище, чем grep -a по бинарному файлу, потому что grep получает на вход только текстовые фрагменты.

ripgrep и strings для ускорения поиска в дампах

ripgrep (команда rg) — написан на Rust, и для CTF у него три козыря: автоматический пропуск бинарных файлов, рекурсивный поиск по умолчанию и скорость — на файлах свыше 1 ГБ ripgrep стабильно обгоняет GNU grep в 2-5 раз за счёт параллельного чтения.

Синтаксис почти идентичен: rg -o 'flag\{[^}]+\}' dump.txt. Для PCRE-паттернов: rg -Po '(?<=flag\{)[^}]+(?=\})' dump.txt (требуется сборка ripgrep с поддержкой PCRE2, в большинстве пакетных менеджеров она включена по умолчанию).

Установка: apt install ripgrep на Debian/Ubuntu, brew install ripgrep на macOS. На CTF-машинах ripgrep часто не стоит — поэтому владеть GNU grep обязательно, а ripgrep держать как ускоритель на своей рабочей станции.

Комбинация strings и rg особенно хороша для бинарных дампов: strings -n 8 firmware.bin | rg -o 'flag\{[^}]+\}'. Параметр -n 8 у strings поднимает минимальную длину извлекаемых строк до 8 символов, отсекая мусорные короткие фрагменты.

Извлечение данных из текстовых дампов: Base64 и hex

Организаторы CTF прячут флаги в кодировках — и это напрямую пересекается с реальной практикой ИБ. Техника Deobfuscate/Decode Files or Information (T1140) по классификации MITRE ATT&CK описывает тот же сценарий: злоумышленники обфусцируют данные для обхода детектирования, аналитики — декодируют обратно.

Base64. Строка flag{hello_world} в Base64 превращается в ZmxhZ3toZWxsb193b3JsZH0=. Глазами не распознать. Стратегия: найти все base64-подобные строки в дампе, декодировать массово, искать паттерн уже в декодированном тексте.

grep -Eo '[A-Za-z0-9+/]{20,}={0,2}' dump.txt \
  | base64 -d 2>/dev/null \
  | grep -Eo 'flag\{[^}]+\}'

Первый grep находит кандидатов — строки из base64-алфавита длиной от 20 символов с опциональным padding (=). Порог {20,} отсекает слишком короткие совпадения. base64 -d декодирует каждую строку (ошибки подавляются через 2>/dev/null). Второй grep ищет флаг в декодированном тексте.

Hex-кодировка. Флаг flag{abc} в hex — 666c61677b6162637d. Конвейер аналогичен: grep -Eo '[0-9a-fA-F]{20,}' dump.txt | xxd -r -p 2>/dev/null | grep -Eo 'flag\{[^}]+\}'. Утилита xxd -r -p выполняет обратное преобразование из hex в ASCII.

ROT13. Классический шифр подстановки. Строка flag после ROT13 — synt. Ищем напрямую: grep -Eo 'synt\{[^}]+\}' dump.txt | tr 'A-Za-z' 'N-ZA-Mn-za-m'. Команда tr применяет обратную ROT13-подстановку (ROT13 симметричен — двойное применение возвращает оригинал).

Извлечение данных из текстовых дампов часто требует комбинации нескольких декодирований. Встречаются задачи с двойным base64 (base64 от base64), hex-encoded base64 и другие вложенные кодировки — этакая матрёшка. Подход один: строить конвейер из pipe-символов, пропуская данные через цепочку декодеров.

grep команды для CTF: практический workflow от дампа до флага

Теория без практики — пустой звук. Разберём полный workflow: таск категории forensics, файл challenge.log размером 800 МБ.

file challenge.log
wc -l challenge.log
LC_ALL=C grep -Eom1 '[a-zA-Z0-9_]+\{[^}]+\}' challenge.log
grep -Eo '[A-Za-z0-9+/]{20,}={0,2}' challenge.log | head -20
grep -rEo 'flag\{[^}]+\}' ./extracted/ --include='*.txt'
grep -n -C 3 'подозрительная_строка' challenge.log
strings -n 6 challenge.log | grep -Eoi 'flag'

Шаг 1 — разведка. file покажет тип файла (ASCII text, UTF-8 Unicode text, data), wc -l — количество строк. Две секунды, но сразу понимаешь масштаб: текстовый или бинарный, тысяча строк или два миллиона.

Шаг 2 — быстрый grep. Универсальный паттерн с LC_ALL=C и -m1: если флаг лежит в открытом виде, ответ появится за доли секунды. Этот шаг решает примерно половину тасков. Серьёзно — половину.

Шаг 3 — проверка кодировок. Прямой поиск ничего не дал? Ищем base64-блоки. head -20 показывает первых 20 кандидатов — оцениваем глазами, похоже ли на base64 или это случайный набор символов. Потом пропускаем через base64 -d и ищем паттерн.

Шаг 4 — рекурсивный поиск. Если таск дал архив с множеством файлов: grep -rEo 'flag\{[^}]+\}' ./extracted/. Опция --include='*.txt' ограничивает поиск текстовыми файлами — grep не тратит время на картинки и бинарники.

Шаг 5 — контекст. Нашли подозрительную строку, но не уверены? Флаг -C 3 покажет по три строки до и после совпадения, -n добавит номера строк. Потом можно открыть файл точно на нужной строке: vim +номер challenge.log.

Шаг 6 — strings для бинарных вкраплений. Если file показал data вместо text, предварительно прогоняем через strings.

Этот workflow покрывает примерно 70-80% задач на jeopardy-CTF в категориях misc, forensics и crypto. Кстати, picoCTF прямо включает задачу «First Grep» для новичков — она устроена ровно так: дан файл, найди строку picoCTF{...} одной командой.

awk и sed для CTF-дампов: когда grep не справляется

Grep работает построчно — это его сильная сторона и одновременно ограничение. Если флаг разбит на несколько строк (hex-дампы, многострочные логи), grep его не увидит.

awk для извлечения полей. Допустим, лог имеет формат timestamp | level | message, и флаг спрятан в поле message. Конвейер awk -F'|' '{print $3}' access.log | grep -Eo 'flag\{[^}]+\}' сначала через awk вырежет третье поле (разделитель |), потом grep найдёт в нём флаг.

sed для предобработки. Иногда организаторы разбивают флаг пробелами: f l a g { h e l l o }. Убрать пробелы перед поиском: sed 's/ //g' dump.txt | grep -Eo 'flag\{[^}]+\}'. Другой вариант — склеить все строки файла в одну: tr -d '\n' < dump.txt | grep -Eo 'flag\{[^}]+\}'. Команда tr -d '\n' удалит переносы строк. Осторожно с большими файлами — вся строка загружается в память.

pcregrep для многострочного поиска. pcregrep поддерживает флаг -M (multiline): pcregrep -Mo 'flag\{[^}]+\}' dump.txt. Единственный вариант без предварительной склейки строк — pcregrep сам обработает совпадения, пересекающие границу строки.

Связь навыков grep с реальной практикой ИБ

Всё, что описано выше, применяется за пределами CTF без изменений. В incident response аналитик ищет индикаторы компрометации в логах теми же конвейерами. Техника Credentials In Files (T1552.001) по MITRE ATT&CK — это буквально grep по паттернам password=, api_key=, secret= в файловой системе. Data from Local System (T1005) — сбор данных из локальных файлов, тот же рекурсивный grep -r по директориям. Shell History (T1552.003) — поиск утечек credentials в .bash_history.

Команда grep -rEi '(password|passwd|api_key|secret|token)=' /var/log/ — рабочий инструмент и для CTF-таска, и для аудита конфигурации продакшн-сервера. Разница только в паттерне: на CTF ищем flag{}, в жизни — утечки данных.

На собеседованиях в SOC дают задачу «вот лог, найдите аномалию» — и ждут осмысленный grep, а не ручной скролл в текстовом редакторе. Навык быстрого парсинга текстовых данных регулярными выражениями — то, что отделяет специалиста от человека, прочитавшего книгу.

Есть мнение, что CTF — это игрушки, не имеющие отношения к реальной работе. Я с этим категорически не согласен. Каждый решённый таск на поиск флага в дампе тренирует ровно тот мышечный рефлекс, который нужен при разборе инцидента: увидел артефакт — сформулировал паттерн — нашёл в данных. Проблема в том, что большинство новичков распыляются: учат десятки инструментов поверхностно вместо того, чтобы довести до автоматизма три базовых — grep, awk и strings. Один точный grep-конвейер решает задачу быстрее, чем десять минут в GUI-анализаторе. На сотне задач это разница в десятки часов. Если хочется пройти этот фундамент системно, а не собирать по кускам — на IB Basics от Codeby как раз упор на практические навыки, а не на запоминание терминологии.

🚀 Хочешь закрепить на практике? Реши задачи по теме на HackerLab — категория «pentest-machines».

Поделиться

0 комментариев

Пожалуйста, войдите, чтобы оставить комментарий.

Загрузка комментариев...

Читайте также

GTFOBins повышение привилегий Linux: практика

13 мин.

1

GTFOBins повышение привилегий Linux: практика

Пошаговый чейн повышения привилегий через GTFOBins: sudo -l, SUID, capabilities. Готовые one-liner'ы для 9 бинарников, связка с LinPEAS, обход ограничений sudo.

13 НОЯБРЬ, 2026

Настройка лаборатории для CTF: Docker и VM

12 мин.

5

Настройка лаборатории для CTF: Docker и VM

Пошаговая настройка лаборатории для CTF: VirtualBox, Kali Linux, Docker, сетевая изоляция. Проверено на 8 ГБ RAM — от нуля до первого флага.

13 НОЯБРЬ, 2026

Insecure Deserialization в CTF: эксплуатация PHP и Python

13 мин.

25

Insecure Deserialization в CTF: эксплуатация PHP и Python

PHP gadget chains, Python pickle opcodes, CVE-2020-15148 (EPSS Top 1%). Практическое руководство по insecure deserialization для CTF — от формата до обхода фильтров.

12 НОЯБРЬ, 2026