Главная / Блог / Bash для CTF: grep, awk, sed и пайплайны для быстрого поиска флагов

13 мин.037

Bash для CTF: grep, awk, sed и пайплайны для быстрого поиска флагов

Bash для CTF: grep, awk, sed и пайплайны для быстрого поиска флагов

На прошлогоднем jeopardy-CTF мне попался forensics-таск: архив на 47 МБ, внутри — 14 тысяч строк логов, конфигов и мусорных файлов. Флаг формата CTF{...} спрятан где-то в этой куче. Один grep -rnoP с правильным паттерном — и через две секунды флаг на экране. Коллега из команды листал файлы через less, потратил двадцать минут и сдался. Разница не в таланте, а в умении собрать правильный пайплайн из трёх-четырёх базовых утилит. Дальше разберём bash для CTF на практике: как grep, awk, sed и пайплайны экономят часы на соревнованиях.

Место в цепочке CTF-решения

Текстовые утилиты linux для пентеста и CTF — не самостоятельное оружие, а клей между этапами решения таска. По аналогии с MITRE ATT&CK (маппинг условный, для обучения) цепочка выглядит так:

  1. Получение файлов — скачиваем архив, подключаемся по SSH, получаем дамп. Bash-утилиты пока не нужны.
  2. Обнаружение — find, ls -la, file помогают понять, что перед нами: бинарник, лог, картинка со вшитыми данными. Это File and Directory Discovery (T1083, Discovery).
  3. Извлечение данных — strings, cat, grep вытаскивают читаемый текст из файлов. Это Data from Local System (T1005, Collection). На реальном пентесте тот же приём используется для поиска учётных данных — Credentials In Files (T1552.001, Credential Access).
  4. Декодирование — base64 -d, трансформации через sed. Это Deobfuscate/Decode Files or Information (T1140).
  5. Получение флага — результат пайплайна.

Без предыдущего шага следующий бесполезен: нет смысла запускать grep по бинарнику, если перед этим не вытащили текст через strings. Понимание этой последовательности — и есть скорость на CTF.

Требования к окружению

  • ОС: любой Linux-дистрибутив — Kali, Ubuntu, Parrot. macOS подойдёт, но grep -P (Perl-regex) недоступен без установки GNU grep через brew install grep (после установки вызывается как ggrep -P, а не grep -P)
  • RAM: 512 МБ для текстовых тасков. Для дампов памяти от 4 ГБ — минимум 4 ГБ RAM
  • Утилиты: grep, awk, sed, find, strings, sort, uniq, cut, base64 — все входят в любой дистрибутив. Проверка: which grep awk sed
  • Версия grep: для Perl-совместимых regex нужен GNU grep 2.5+. Узнаётся через grep --version
  • Сеть: не требуется — всё работает офлайн

grep для поиска флагов: регулярные выражения на практике

grep — первое, что запускаешь на любом CTF-таске с файлами. Задача простая: выцепить строку с флагом среди потока текста.

Базовый поиск по формату флага

Формат флага почти всегда известен заранее: CTF{...}, flag{...}, picoCTF{...}, codeby{...}. Поэтому достаточно одного вызова grep -rn 'CTF{' . по текущей директории. Флаг -r включает рекурсию по поддиректориям, а -n покажет номер строки — пригодится, чтобы понять контекст находки.

Если формат флага неизвестен, берите обобщённый паттерн: grep -rnoP '[A-Za-z0-9_]+\{[^\}]+\}' .. Разбор по частям: -o выводит только совпавший фрагмент (не всю строку целиком), -P включает Perl-совместимые регулярные выражения grep, [A-Za-z0-9_]+ ловит одно или более буквенно-цифровых символов перед фигурной скобкой, а \{[^\}]+\} захватывает содержимое в фигурных скобках. Паттерн подходит для любого формата вида WORD{содержимое} — универсальная стартовая точка.

Регулярные выражения grep для типичных задач

На соревнованиях встречаются флаги с конкретным набором символов. Если известно, что внутри скобок только hex: grep -oP 'flag\{[0-9a-f]+\}' файл. Если флаг может содержать base64-подобную строку: grep -oP 'flag\{[A-Za-z0-9+/=]+\}' файл. Для UUID-подобных флагов: grep -oP 'flag\{[0-9a-f-]{36}\}' файл.

Для поиска с контекстом — когда флаг разбит на части или валяется рядом с подсказкой — берите grep -rn -B3 -A3 'password' logs/. Флаги -B 3 и -A 3 покажут по три строки до и после совпадения. На тасках с анализом логов bash учётные данные и флаг часто оказываются в соседних строках, и без контекста находка бесполезна.

Поиск строк в бинарных файлах через strings

Частая ошибка новичков — запускать grep прямо по бинарнику. grep выдаст «Binary file matches» без полезного содержимого. Решение — связка: strings файл | grep -i 'flag'. Утилита strings извлекает все печатаемые последовательности из файла (по умолчанию от 4 символов), а grep ищет паттерн уже по чистому тексту. Флаг -i игнорирует регистр — авторы тасков иногда записывают флаг как FLAG{} или Flag{}.

Запасной вариант — grep -a 'flag' бинарник, где -a заставляет grep обрабатывать бинарный файл как текстовый. Работает, но выдаёт заметно больше мусора. Связка со strings чище и предсказуемее. Можно задать минимальную длину строки: strings -n 8 файл — извлечёт только последовательности от 8 символов, отсеяв короткие обрывки.

Пайплайны bash linux: цепочки команд

Пайплайн — конструкция, в которой вывод одной команды через оператор | подаётся на вход следующей. В контексте CTF пайплайны bash linux позволяют за один однострочник пройти путь от сырых данных до чистого флага. Тут bash для CTF и раскрывается по-настоящему.

find + xargs + grep: массовый поиск

Получили директорию с сотнями файлов разных типов — нужно найти флаг. Команда find . -type f | xargs grep -l 'flag{' 2>/dev/null перебирает все файлы и выводит имена тех, где встречается подстрока flag{. find генерирует список файлов, xargs группирует их в аргументы для grep, а -l заставляет grep выводить только имена файлов. Перенаправление 2>/dev/null глушит ошибки доступа — без него экран забьётся строками «Permission denied».

Для файлов с пробелами в именах (а на тасках это бывает специально, чтобы сломать наивные скрипты): find . -type f -print0 | xargs -0 grep -l 'flag{'. Параметр -print0 и -0 используют нулевой байт как разделитель вместо переноса строки, и пробелы перестают быть проблемой.

Декодирование на лету: strings + base64 + grep

На forensics-тасках флаг часто закодирован в base64 и спрятан внутри бинарника. Типичный пайплайн:

strings dump.bin \
  | grep -oP '[A-Za-z0-9+/=]{20,}' \
  | while read line; do
      echo "$line" | base64 -d 2>/dev/null
    done \
  | grep -i 'flag'

Разбор: strings извлекает текст из бинарника, grep -oP ловит строки длиной от 20 символов из base64-алфавита, цикл while read декодирует каждую строку, 2>/dev/null глушит ошибки невалидного base64, а финальный grep ищет флаг в декодированном выводе. Ограничение: пайплайн работает, только если base64-строка целиком попадает в одну строку вывода strings; для многострочного base64 одного tr -d '\n' часто недостаточно, так как strings разрывает последовательности на границах непечатаемых символов. Надёжнее сначала вытащить текст в файл (strings -n 8 dump.bin > tmp.txt), руками найти границы base64-блока и склеить, либо использовать binwalk/foremost для автоматического извлечения вложенных данных. Это практическая реализация Deobfuscate/Decode (T1140) — приём работает и в CTF, и на пентесте при разборе конфигурационных файлов.

Статистический анализ: sort + uniq

Когда в логе тысячи строк и непонятно, откуда начинать, — начните со статистики. Команда awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -20 покажет топ-20 значений первого поля (обычно IP-адрес) по частоте обращений. Аномальный IP с тысячами запросов — первый кандидат на детальное изучение. Дальше фильтруете: grep '10.0.0.42' access.log | grep -i 'flag\|admin\|secret'.

Тот же подход работает для любого поля: замените $1 на нужный номер — $7 для URL, $9 для HTTP-кода ответа, $10 для размера тела.

awk примеры для CTF: разбор логов по полям

awk — полноценный язык обработки текста в linux, но на CTF он нужен главным образом для одной задачи: вытащить конкретное поле из структурированных данных. Если grep ищет строку целиком, то awk работает с колонками внутри строки.

Извлечение полей и нестандартные разделители

Типичная строка access-лога Apache: 192.168.1.1 - - [10/Oct/2023:13:55:36] "GET /secret HTTP/1.1" 200 2326. По умолчанию awk разбивает строку по пробелам и табуляциям. Команда awk '{print $7}' access.log выведет седьмое поле — URL запроса. Команда awk '{print $1, $7, $9}' access.log выведет IP, URL и код ответа — три поля, с которых начинается любой анализ.

Для данных с другим разделителем — -F. Разбор /etc/passwd по двоеточиям: awk -F: '{print $1, $3}' /etc/passwd — выводит имя пользователя и UID. CSV с запятой: awk -F, '{print $3}' data.csv. На CTF-тасках попадаются и экзотические форматы — pipe-delimited (|), логи с произвольными разделителями. Указывайте нужный символ через -F.

Условная фильтрация и подсчёт

awk умеет фильтровать строки по условию. Найти записи с HTTP-ответом 500 и выше: awk '$9 >= 500 {print $0}' access.log. Отфильтровать POST-запросы к конкретному эндпоинту: awk '$6 ~ /POST/ && $7 ~ /login/' access.log. Оператор ~ проверяет совпадение с regex, а && — логическое «и».

Подсчёт уникальных значений в конкретном поле — одна из самых частых задач при поиске по логам:

awk '{print $7}' access.log | sort | uniq -c | sort -rn | head -10

Результат: топ-10 запрашиваемых URL с количеством обращений. Аномально популярный путь вроде /admin/flag.txt или /backup/dump.sql сразу бросается в глаза. Связка awk | sort | uniq -c | sort -rn — один из самых ходовых рецептов обработки текста в linux, запомните его как готовый шаблон.

sed команды linux: трансформация и очистка данных

sed — потоковый редактор. На CTF он нужен, когда данные надо не найти, а трансформировать: убрать мусор, заменить символы, вырезать подстроку по шаблону.

Замена, удаление и извлечение подстрок

Базовый синтаксис замены: sed 's/что/на_что/g' файл. Флаг g — замена всех вхождений в строке, без него заменится только первое. Практический пример: авторы misc-тасков обожают leet-speak. Команда echo 'fl4g{r3pl4c3_m3}' | sed 's/4/a/g; s/3/e/g' вернёт flag{replace_me} — две замены через точку с запятой в одном вызове.

Удаление мусорных строк: sed '/^$/d' файл убирает пустые строки, sed '/^#/d' config.txt — комментарии. Очистить HTML от тегов: sed 's/<[^>]*>//g' page.html — полезно, когда флаг спрятан в HTML среди разметки. Удалить первые N строк заголовка: sed '1,5d' файл — убирает строки с 1 по 5.

Группы захвата: хирургическое извлечение флага

Самый мощный приём sed для CTF — извлечение подстроки через группы: конструкция echo 'User flag is: CTF{s3d_m4st3r} here' | sed -n 's/.*\(CTF{[^}]*}\).*/\1/p' вырезает ровно флаг из любого окружающего текста. \(...\) определяет группу захвата, \1 ссылается на неё, а комбинация -n с флагом p выводит только совпавшие строки. Если в файле сотни строк и лишь одна содержит флаг — этот однострочник выдаст чистый результат без мусора.

Для замены с перестановкой частей: echo '2023-10-15' | sed 's/\([0-9]*\)-\([0-9]*\)-\([0-9]*\)/\3.\2.\1/' превратит 2023-10-15 в 15.10.2023. На тасках с логами иногда нужно привести даты к единому формату для сортировки.

Bash one-liners для CTF: готовые рецепты

Набор однострочников, которые работают практически на каждом соревновании. Каждый решает конкретную задачу из CTF-практики.

Рекурсивный поиск файлов с флагом: grep -rnl 'flag{' . 2>/dev/null — -l выводит только имена файлов, без содержимого.

Вытащить все URL из файла: grep -oP 'https?://[^\s"<>]+' файл — Perl-regex ловит HTTP- и HTTPS-ссылки целиком.

Файлы, изменённые за последние 10 минут: find / -mmin -10 -type f 2>/dev/null — на wargames вроде OverTheWire свежий файл почти всегда содержит подсказку или флаг.

Декодировать base64 из файла: cat encoded.txt | base64 -d — для чистого base64. Если файл содержит мусор вперемешку с base64: grep -oP '[A-Za-z0-9+/=]{4,}' файл | base64 -d 2>/dev/null.

Поиск по истории bash: cat ~/.bash_history | grep -i 'pass\|flag\|secret\|key' — на пентесте это Shell History (T1552.003, Credential Access; ранее выделялась как отдельная техника T1139 Bash History, ныне deprecated). На CTF — частый источник флагов на SSH-машинах. Я однажды нашёл так флаг за 10 секунд — предыдущий участник забыл почистить историю.

Рекурсивный поиск приватных ключей: grep -rl 'BEGIN.*PRIVATE KEY' /home/ 2>/dev/null — Private Keys (T1552.004, Credential Access).

Уникальные email из дампа: grep -oP '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' дамп.txt | sort -u.

Подсчёт ошибок в логе: grep -c 'ERROR\|FATAL\|CRITICAL' app.log — -c считает количество совпадений вместо вывода строк.

Найти файлы по расширению и проверить содержимое: find . -name '*.txt' -exec grep -l 'flag' {} + — ищет flag только в .txt-файлах.

grep vs awk vs sed: когда что применять

Утилита Сильная сторона Ограничение Когда использовать Когда не использовать
grep Быстрый поиск по паттерну, рекурсия по директориям Не трансформирует текст, не работает с полями Найти строку с флагом, отфильтровать по ключевому слову Нужно вытащить поле из CSV или заменить подстроку
awk Работа с полями, условная логика, арифметика Избыточен для простого поиска строки Разбор логов, CSV, извлечение колонки, подсчёт Простой поиск подстроки — grep справится быстрее
sed Замена, удаление, трансформация текста на лету Неудобен для сложной условной логики Очистка мусора, декодирование leet-speak, удаление тегов Фильтрация по значению поля или математические условия

Алгоритм выбора: нужно просто найти строку — grep. Нужно вытащить конкретное поле из структурированных данных — awk. Нужно заменить или удалить часть текста — sed. Нужно несколько операций подряд — пайплайн: grep | awk | sed. На практике 90% задач закрываются первыми двумя.

Частые ошибки при поиске строк в файлах linux

Забыли кавычки вокруг паттерна. Команда grep flag{test} file.txt сломается — bash интерпретирует фигурные скобки как brace expansion. Правильно: grep 'flag{test}' file.txt. Одинарные кавычки отключают интерпретацию спецсимволов шеллом.

Не экранировали точку в regex. Точка — это «любой символ», не буквальная точка. Ищете IP 192.168.1.1? Пишите grep '192\.168\.1\.1' с обратными слешами. Без экранирования 192.168.1.1 совпадёт и с 192x168y1z1.

grep по бинарнику без strings. grep пропускает бинарные файлы молча или пишет «Binary file matches». Берите strings файл | grep 'flag' или grep -a 'flag' файл. Первый вариант чище — меньше ложных срабатываний.

Путаница между -E и -P. -E — расширенные POSIX-regex: не нужно экранировать +, ?, {}. -P — Perl-совместимые regex: поддерживают \d (цифра), \w (буква/цифра), \s (пробел), lookahead и lookbehind. Для CTF -P мощнее, но недоступен на macOS без GNU grep. Если работаете на Mac — ставьте через brew install grep и вызывайте как ggrep.

Жадные квантификаторы. Паттерн grep -oP '\{.*\}' на строке {first} и {second} захватит {first} и {second} целиком — .* жадный и забирает максимум. Нежадный вариант: grep -oP '\{.*?\}' — захватит {first} и {second} отдельно. Знак ? после * делает квантификатор ленивым. Это одна из самых коварных ловушек регулярных выражений regex для новичков — на ней сгорают стабильно.

Забыли 2>/dev/null. Рекурсивный grep -rn или find в системных директориях генерирует сотни ошибок «Permission denied». Добавьте 2>/dev/null в конец команды. Без этого полезный вывод тонет в потоке ошибок.

Двойные кавычки вместо одинарных. В двойных кавычках bash раскрывает переменные: grep "$HOME" файл подставит путь к домашней директории, а не будет искать литерал $HOME. Если в паттерне есть $, ! или обратные кавычки — одинарные кавычки, в них bash ничего не интерпретирует.

Пропустили флаг из-за невидимых символов. Иногда флаг содержит непечатаемые символы: \r (carriage return из Windows), нулевые байты, BOM-маркеры. Если grep находит строку, но площадка флаг не принимает — прогоните через cat -A (покажет ^M для \r) или xxd для побайтового просмотра. Очистка: sed 's/\r$//' файл удалит Windows-переносы. Для тех кто в танке — \r это символ возврата каретки, наследие DOS, и он любит ломать всё, что выглядит «нормально» в терминале.

Навыки linux командной строки для CTF — не зазубривание флагов каждой утилиты, а понимание потока данных через пайплайн. Каждая команда делает одно простое действие: grep фильтрует, awk разбирает по полям, sed трансформирует, sort и uniq считают. Мощь — в комбинации этих простых блоков.

По опыту решения тасков на picoCTF, HackTheBox и участия в jeopardy-соревнованиях — 80% forensics- и misc-задач закрываются одним-двумя пайплайнами из трёх-четырёх команд. Оставшиеся 20% требуют Python или специализированные инструменты вроде Volatility и Autopsy. Но даже в этих случаях предварительный strings | grep экономит время, потому что показывает, с чем вообще имеешь дело, прежде чем поднимать тяжёлую артиллерию.

Среди коллег по CTF-команде я вижу устойчивый паттерн: те, кто быстро закрывают forensics, не знают больше команд. Они знают, как комбинировать базовые. Один пайплайн из find, xargs, strings, grep -oP и sort -u покрывает задачу, на которую человек без этого навыка тратит полчаса ручного перебора. Разница между пятью решёнными тасками за соревнование и пятнадцатью — не в количестве выученных утилит, а в скорости сборки пайплайна. Мой совет: не гонитесь за экзотическими инструментами и не пытайтесь осилить тысячестраничный мануал по awk целиком. Отрабатывайте связку: увидел файл — file — strings — grep -oP 'паттерн' — ответ. Доведите её до автоматизма на десяти тасках — следующие двадцать будут решаться вдвое быстрее. Если хочется закрыть базу системно — не только bash, но и сети, веб, криптографию — на codeby.school/ib-basics есть IB Basics, от нуля до первых рабочих задач без академического тона.

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

Поделиться

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

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

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

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

Pwntools для начинающих: pwn на Python без боли

11 мин.

1

Pwntools для начинающих: pwn на Python без боли

Сквозной разбор pwntools от checksec до remote-эксплойта. GDB-интеграция из скрипта, cyclic для offset и 3 ошибки, на которые уходит по часу.

2 НОЯБРЬ, 2026

OSINT разведка для CTF: дорки, Shodan, фото

13 мин.

3

OSINT разведка для CTF: дорки, Shodan, фото

Конкретные Google Dorks, Shodan-запросы и приёмы reverse image search для OSINT-задач на CTF. Пошаговые воркфлоу с командами, готовые шаблоны дорков и цепочки pivot'ов.

2 НОЯБРЬ, 2026

Wireshark анализ PCAP: пароли и секреты в CTF

12 мин.

1

Wireshark анализ PCAP: пароли и секреты в CTF

Пошаговый алгоритм разбора PCAP в CTF: фильтры для credential hunting, Export Objects, Follow TCP Stream, tshark и ловушки авторов тасков.

1 НОЯБРЬ, 2026