shem · Capítulo 29
Me dijo su nombre tres veces
Cayó en el cebo otro ELF de IoT con pinta de Mirai del montón. Lo bauticé «zbot» por sus ficheros de cron, y resultó que ni se llamaba así: por tres caminos distintos (las rutas que dejó en el disco, los banners con que habla SSH y HTTP, y los primeros bytes de cada mensaje a su central) el bicho me fue diciendo su verdadero nombre. Detrás había algo más interesante que un bot de tumbar servidores: una máquina para alquilar la línea de casa de su víctima como proxy. Y un operador que, con todo montado, rompía sus propias direcciones de descarga. XLab ya la había bautizado «Shemzbot» en un tuit; esto es el destripe que aquel tuit no traía.
Cayó en la trampa un ELF de 64 bits, estático, sin símbolos, de 1 MB. La presentación estándar de un bot de IoT, de los que veo a diario. Entró por telnet, no por SSH, y el matiz no es cosmético: telnet en el puerto 23 con la contraseña de fábrica es el vector de IoT de toda la vida, el que muchos ya ni miran. La credencial que le abrió la puerta fue root/xc3511: la de las cámaras XiongMai, la misma que encendió Mirai en 2016. Diez años después sigue funcionando.
Lo bauticé «zbot» porque así se llaman los ficheros de cron que deja al instalarse. Spoiler: ni siquiera se llama así. Pero la gracia de este bicho no está en el final, sino en el camino, en cómo me fue corrigiendo el nombre él solo una y otra vez. Así que vamos por orden.
shem alias «Shemzbot» (XLab)
- sha256 (con relleno)
- 1d3c4108…9f46cf8b
- sha256 (ELF sin cola)
- 82ab1202…0a2d8124
- BuildID
- 8e7a8299…3ded94c
- Tipo
- ELF 64-bit LSB, x86-64, estático, stripped
- Tamaño
- 1.088.003 B (ELF 1.086.272 + 1.731 de cola)
- Nombre interno
- shem · «zbot» solo en sus crons
01El operador cambia el hash en cada descarga
El reflejo de siempre: saco el hash del fichero y lo busco, a ver si ya está catalogado. No lo estaba: ni en VirusTotal, ni en MalwareBazaar. Y eso, en un bot de reparto masivo y activo, no cuadra. Un bicho que infecta a mansalva deja muestras por todas partes; que el suyo no figurara en ningún sitio olía mal. Olía mal porque el hash mentía.
Miré el fichero por dentro: el ELF terminaba en su último segmento cargable y, sin embargo, el fichero seguía 1.731 bytes más allá. Una cola pegada al final, de máxima entropía (casi 7,9 bits por byte): ruido puro, nada de código ni de texto. La corté, rehíce el hash de lo que quedaba, y apareció al instante: catalogado, veinte motores marcándolo.
# el ELF de verdad acaba aquí
offset 0x109340 (1.086.272) ┤ fin del ELF
offset 0x109340 … 0x109A02 ┤ 1.731 B (0x6C3) de basura, entropía 7,88 b/byte
tamaño del fichero = 0x109A03 (1.088.003 B)
sha256(fichero completo) = 1d3c4108… → no catalogado (único por descarga)
sha256(ELF sin la cola) = 82ab1202… → MalwareBazaar / VirusTotal 20/…Bajé todo lo que el servidor repartía y comprobé el truco: a cada descarga le añade una cola aleatoria distinta (las vi de 182 a 2.020 bytes). O sea que cada fichero que sirve su caja sale con un sha256 distinto. La consecuencia para quien defiende es dura: el hash del fichero completo no sirve de nada como indicador. Lo que aguanta es el hash del ELF sin la cola, y sobre todo el BuildID, la huella que la compilación deja grabada dentro y que sobrevive a la cola y al renombrado.
02Esperaba una tabla cifrada. Estaba todo en claro.
Los forks de Mirai guardan su configuración en una tabla cifrada con un XOR que, en la práctica, es de un byte; uno la busca por reflejo, casi sin pensar. Aquí no había tabla: la definición entera del protocolo estaba en claro en .rodata, en inglés, a la vista con un simple strings. Las órdenes, sus formatos, las plantillas. (El tráfico en el cable es otra historia: ese sí va cifrado, y lo abro en el §05. Pero el vocabulario del bicho estaba servido.) La lista completa de las órdenes que acepta de su central, con sus formatos scanf, que de regalo me cantaban los argumentos de cada una:
| Orden | Formato | Qué hace |
|---|---|---|
| PING / PONG | - | latido |
| PROXYON / PROXYOFF | - | enciende / apaga el proxy (§06) |
| UPDATE | %255s → /tmp/.upd | autoactualización |
| SHELL | SHELL %s %s %s | shell remota interactiva (/bin/sh -i) |
| UDP | UDP %63s %d %d | inundación UDP (destino, puerto, duración) |
| AMP | AMP %63s %hu %d %15s | DDoS por amplificación (chargen, ntp) |
| TGTS / VTGT | %23s %23s %u | carga objetivos para el escáner |
| SCAN / STOPSCAN | - | arranca / detiene el escaneo |
| YOURIP | %63s | la central le dice su IP pública |
| NOREPL / NOTOR / NOIDIRECT | - | modificadores de transporte |
| DIE / LOLDONE / LOL | - | terminar / acuse |
Y lo que emite de vuelta: ZBOT %s %s (el registro), ZCR1 %s (credenciales cosechadas), y los hallazgos del escáner como %s|%s|telnet-brute. Entre las cadenas, algo que un bot no debería llevarse jamás a producción: las rutas absolutas del disco de su autor.
/root/shem/targets.txt
/root/shem/web_targets.txt
/root/shem/targets_adb.txt ← también guarda objetivos ADB
SSH-2.0-sheM ← el banner de su cliente SSH
User-Agent: sheM ← en sus peticiones HTTP
SHEM_INST SHEM_LAB SHEM_NOMASQ SHEM_RAM_MBshem. Ese es el nombre, y lo deja por todo su propio disco: las rutas /root/shem/… y las variables SHEM_INST, SHEM_LAB, SHEM_NOMASQ, SHEM_RAM_MB que dejó el desarrollador. «zbot» era solo la etiqueta de sus crons; shem es como lo llama su autor en su máquina. Primera vez que me dice cómo se llama.
Y lo repite en cómo se presenta al hablar con el mundo: su cliente SSH se anuncia SSH-2.0-sheM, y sus peticiones HTTP van con User-Agent: sheM. Firmas que valen mucho más que «zbot»: el operador puede cambiar de servidor mañana, pero esas no se tocan sin recompilar. Segunda vez, por otro camino.
03El error que enseñó el panel del operador
En el registro del ataque había URLs imposibles. Esta, que troceo para que no sea clicable:
hxxp://176.65.134[.]121:36023PROXYONUPDATE:7416/bot.$m
└── un puerto, un comando, y otro puerto ──┘Un puerto, la palabra PROXYONUPDATE, y otro puerto. Eso no es una dirección. Mi primera lectura fue que el bot se auto-aplicaba PROXYON y UPDATE como argumentos; monté un test, con el pegote y sin él, y daba exactamente igual. El test no detectó nada. Me quedé con que la pista no valía, hasta que entendí que el fallo era mío, no de la pista. Estaba midiendo la cosa equivocada; por qué, lo entiendo en el §06.
Porque la URL rota, bien mirada, contaba algo mucho mejor. Puse en fila varias descargas y el patrón cantó. La explicación que mejor encaja con las capturas: su panel maneja una variable «host» con {IP}:{puerto aleatorio}, y a veces se le concatena detrás la cola de comandos pendientes (PROXYON, UPDATE), que acaba colándose donde solo debería ir la dirección de descarga. Los días que el campo va limpio, la URL de descarga es válida; los días que arrastra comandos, esas URLs de descarga fallan. PROXYONUPDATE no es del bot: es, casi con seguridad, una fuga del panel del atacante, y deja entrever cómo tiene montada la consola.
04A la jaula: habla UDP, y dice «SH»
Lo detoné apuntando su C2 a mi propia máquina (el binario lo acepta por argumento, sin parchear nada). Y lo primero ya corrigió dos cosas que yo tenía mal apuntadas. No habla TCP con su central: habla UDP, por el puerto 6881, el de BitTorrent. Si lo eligió a propósito o es casualidad no lo sé, pero el efecto le viene bien: su tráfico UDP en el 6881 puede pasar por ruido de P2P, y quien lo busque por TCP no lo verá pasar. Y los tres primeros bytes de cada mensaje:
→ UDP 53 48 01 "SH" + tipo (hola)
→ UDP 53 48 06 e1 f0 46 e1 dc 85 60 52 c6 … "SH" + registro (cifrado)
│
└── 0x53 0x48 = "SH" → las iniciales de shem53 48 es SH en ASCII: las iniciales de shem. El propio protocolo firma con el nombre. Tercera vez que me lo dice, y van tres caminos independientes: el disco, cómo se presenta en SSH y HTTP, y ahora los dos bytes que abren cada datagrama con su central. (En claro van solo esos tres bytes: la cabecera SH + tipo. De ahí en adelante todo viaja cifrado, empezando por un identificador de sesión de 9 bytes, aleatorio en cada ejecución salvo su último byte, que se mantiene constante. No sirve como indicador, y en el §05 se verá por qué importa que cambie.)
05RC4 con clave fija, roto sin romperlo
Tras la cabecera SH, el cuerpo iba cifrado. Pasé el binario por capa y me dio el algoritmo: RC4, un cifrado de flujo. La regla de oro de RC4 es sencilla: el chorro de bytes que genera, el keystream, no se reutiliza jamás. Dos mensajes cifrados con el mismo keystream y el cifrado se desmorona.
Sospeché que se la saltaba, y comprobarlo fue barato: capturé el mismo mensaje de registro en dos ejecuciones distintas, cada una con su identificador de sesión aleatorio. Con un cifrado decente, ese cuerpo cifrado tendría que salir distinto las dos veces. No salió.
# datagrama: [SH+tipo 3B] · [sesión 9B, desde offset 3] · [cuerpo, desde offset 12]
# la sesión (9B) SÍ difiere entre tiradas; aquí comparo solo el CUERPO (offset 12+):
tirada 1 (sesión e1f046…): cuerpo = 01 2f f4 dc 8b 06 6e dd df 4b d3 e0 60 …
tirada 2 (sesión ef368c…): cuerpo = 01 2f f4 dc 8b 06 6e dd df 4b d3 e0 60 …
↑ idéntico byte a byte, pese a sesiones distintas
⇒ keystream reutilizado: misma clave en cada tirada, ajena a la sesiónEl experimento demuestra directamente una cosa: keystream reutilizado. Con nonces distintos, el mismo texto claro da el mismo cifrado, así que el flujo de cifrado no cambia entre ejecuciones ni depende del nonce; la clave, por tanto, es constante (no abrí el KSA para extraer sus bytes, pero el efecto es el de una clave fija). El error de manual de RC4. Lo bonito es que no hace falta atacar RC4 con matemáticas: basta con recuperar el keystream. Puse un punto de ruptura en la función de RC4, volqué el búfer antes (en claro) y después (cifrado) de la llamada, y con un simple K = claro ⊕ cifrado tenía el chorro. El keystream entero me lo guardo: publicarlo sería regalar la llave para descifrar y falsear el tráfico de cualquier nodo, y esto es un análisis, no un kit. Con dos mensajes distintos confirmé que K es el mismo siempre, aplicado a todo lo que sigue a la cabecera de 3 bytes (el offset 3: la cifra cubre el identificador de sesión y el cuerpo). A partir de ahí, el canal con la central se lee en claro:
# K recuperado con gdb (break @ 0x40a410). Lo muestro recortado a propósito:
K = 0e7aeeba 7f3c91a0e4d28b651af09c37b802e5d49c6a1f08d3b47e52a0c9 … ← keystream (redactado por OPSEC)
# con K, el canal C2 se lee en claro:
SH 06 <9B sesión> "ZBOT x86_64 overlay" ← registro: arquitectura + transporte
SH 06 <9B sesión> "ZCR1 <32hex>" ← reporte de credenciales cosechadasY con el protocolo en la mano monté un sumidero que habla shem, todo dentro de la jaula. Aquí el bot se delató solo: le mandé un SH 02 por UDP y me apuntó como peer (se quedó con la IP y el puerto de origen de mi datagrama), me llamó de vuelta por TCP y me habló SOCKS5 como cliente. La prueba en vivo de que, en modo overlay, encamina su salida a través de sus propios peers.
→ UDP 6881 53 48 02 respondo "SH" 02 a la baliza
→ el bot me apunta como peer (mi IP:puerto de origen)
← TCP 05 01 → CONNECT 127.0.0.1:1338 me habla SOCKS5 como cliente
→ 05 00 … completo el handshake: túnel aceptado
(127.0.0.1:1338 = el destino que pide alcanzar por el túnel; yo haría de salida)06PROXYON: el interruptor que lo explica todo
Al detonarlo abría tres puertos: el 6881/UDP de la central y dos TCP, el 7331 y el 7332. El 7331 respondía por fin a la pregunta que arrastraba desde el comando PROXYON. Porque ese puerto siempre se abre y siempre escucha. La diferencia no está en abrir: está en el accept.
conexion = accept(...);
if (interruptor == 0) close(conexion); // apagado: te cuelga sin contestar
else crear_hilo(conexion); // encendido: te atiende
// interruptor (global) ← lo mueven exactamente dos comandos de la central:
PROXYON → interruptor = 1 PROXYOFF → interruptor = 0No es un modo de arranque: es un mando a distancia. Y aquí está por qué mi test del §03 falló: desde fuera, encendido y apagado tienen los mismos puertos abiertos. Yo estaba midiendo la cerradura en vez de mirar si la puerta se abre. Con el interruptor a 1, le mandé al 7331 un saludo de SOCKS5 y me respondió con el «adelante»; con el interruptor a 0, me colgó sin una palabra.
Y esto cierra la duda del §03: el proxy se enciende por el canal C2, no por un argumento de arranque. Así que el PROXYONUPDATE pegado en la URL no puede ser el bot auto-aplicándose comandos, y encaja con la fuga del panel. Honestamente, es deducción y no prueba cerrada: no relancé el bot con el pegote midiendo el handshake del 7331, solo comparé puertos (que era el error). Pero con PROXYON ya demostrado como comando del C2, es la única lectura que cuadra con todo.
→ 05 01 00 saludo SOCKS5 (versión, 1 método, sin auth)
← 05 00 responde: es un proxy SOCKS5 sirviendoLa palabra «SOCKS» no aparece ni una vez en el binario: está implementado a mano, byte a byte. Ese «no hay cadenas de proxy» que me despistó al principio no era ausencia de proxy: era ausencia de literales. Y para salir, el bot maneja cuatro modos de transporte (direct, relay, tor, overlay): habla SOCKS5 por los dos lados, lo ofrece en el 7331 y lo consume para encaminar lo suyo, con Tor entre las opciones.
07No hay servidores de reparto dedicados. Hay víctimas.
El tercer puerto, el 7332, es un servidor web. Le pedí bot.x86_64 y me sirvió su propio binario, idéntico byte a byte a la muestra. Es decir: cada aparato infectado es también el que infecta al siguiente. No hace falta un servidor de reparto dedicado: el grueso del reparto recae en las propias víctimas. Pero la central también sirve (los .se/.sk salen de su IP, §10), así que no es todo víctima-a-víctima.
Y los tres puertos no son fijos: se calculan, base + 2N con N = getenv("SHEM_INST"). Los puertos de reparto de los loaders de la central (7416 → N=42, 7420 → N=44, 7428…) encajaban todos en 7332 + 2N: no era «rotación de puertos», era aritmética. Su caja reparte sobre todo por el 8080 por defecto, pero sirve el binario también en varios de esos puertos altos. Shodan vio abierto el 7434 (= 7332 + 2·51), lo que apuntaría a una instancia con N=51 corriendo en la propia central. Lo dejo como indicio, no como hecho: un N=51 completo abriría además 7433/TCP (SOCKS5) y 6983/UDP, y la ficha de Shodan (22/8080/7434) no los recoge, probablemente porque no barre esos puertos. Lo firme es que el operador también sirve desde su caja.
Ahí se ve para qué está montado: shem infecta líneas de casa, abre un SOCKS5 en ellas bajo demanda, y de paso las usa para infectar a las siguientes. El producto no es el ataque: es tu conexión.
08El arsenal de propagación
Por telnet reparte el bot.<arch> en claro. Pero para propagarse por la red trae, además, un juego de exploits contra aparatos del borde, embebidos como plantillas.
| Endpoint (verificado en el binario) | Aparato | Identificación mía |
|---|---|---|
| /ctrlt/DeviceUpgrade_1 | Huawei HG532 | CVE-2017-17215 |
| /GponForm/diag_Form | routers GPON | CVE-2018-10561/10562 |
| SetNTPServers (SOAP) | TR-064 / CWMP | inyección NTP (Mirai 2016) |
| SetNTPServerCredentials (HNAP1) | D-Link HNAP | inyección por HNAP/SOAPAction (p.ej. CVE-2015-2051) |
| /setup.cgi?…todo=syscmd | Netgear DGN | RCE setup.cgi syscmd |
| /cgi-bin/luci/;stok=/locale?form=country | TP-Link Archer AX21 | CVE-2023-1389 |
| /cgi-bin/nas_sharing.cgi?user=message… | D-Link NAS | CVE-2024-3273 |
| /apply.cgi (od_fourfaith) | Four-Faith | CVE-2024-12856 (prob.) |
| /tmUnblock.cgi | Linksys E-series | «TheMoon» |
| thinkphp | ThinkPHP 5 | RCE ThinkPHP |
| /ftptest.cgi?loginuse=… | DVR / cámara | inyección ftptest.cgi |
Lo relevante no es que use CVE viejos (el de Huawei es de 2017; los de GPON y TR-064, de 2016-18, son de dominio público): es que mezcla clásicos con otros relativamente recientes: TP-Link Archer de 2023, D-Link NAS y Four-Faith de 2024. Es un arsenal mantenido, no un copia-pega abandonado.
Y un detalle fino: hay dos estilos de entrega. Algunas plantillas sueltan el bot en claro; otras entregan una cadena cifrada, partida en tres piezas.
09Persistencia, y lo que trae de más
Persistencia quíntuple, más terca de lo habitual: se engancha al arranque por cinco sitios a la vez: crontab -, /etc/cron.d/zbot, /var/spool/cron/zbot, /etc/crontab y /etc/rc.local. Y el cron no vigila un proceso: cada 5 minutos comprueba [ -x /tmp/.z ] y, si falta, lo restaura desde /var/.z o /etc/.z. Para tener de dónde restaurar, se copia (%s/.z) en seis rutas: /tmp, /var, /etc y además /jffs, /rw, /data (particiones escribibles de routers, firmware embebido y Android), lo que confirma, sin que lo diga, que el objetivo es IoT.
Y de regalo: un barrido por los binarios SUID del sistema que lanza el bot desde cada uno, un intento de cargar un módulo de kernel (el .ko no venía embebido todavía), un intento de autoborrado (unlink de /proc/self/exe y de sus descriptores) que en Linux ni siquiera borra el fichero del disco, camuflaje con nombres [kworker/…], la apertura de /dev/watchdog para que el perro guardián del hardware no reinicie el aparato (un reinicio se llevaría el bot, que solo vive en RAM), y un matador de competidores. Este último trae un desliz precioso de linaje:
# bots de Linux (esperable):
mirai.arm tsunami hakai sora qbot astaroth …
# …y de pronto, antivirus de WINDOWS en un bot de Linux:
msmpeng avast avgnt kavsvc clamd msseces.exe
# aquí no hay nada de Windows que matar → indicio de código reciclado (de origen Windows)No hay un solo proceso de Windows que matar en un router Linux. Esos nombres parecen una lista heredada de otro sitio y nunca limpiada, probablemente de código pensado para Windows, que es donde esos antivirus tienen sentido. De qué familia exactamente no lo sé: es un buen indicio de código reciclado, no una prueba del ancestro.
10La nombraron de pasada; aquí va entera
Antes de cerrar hice la comprobación de siempre, la aburrida: ¿esto ya lo ha contado alguien? Porque un bot-proxy tan completo y tan activo bien podría estar documentado y yo llegando tarde. Miré en los sitios públicos (MalwareBazaar, VirusTotal, ThreatFox, URLhaus) y la respuesta tiene matiz: la muestra sí circula, pero casi nadie sabe qué es.
El ELF sin cola está catalogado, pero como trojan.mirai a secas, uno más del montón. El fichero entero, con su cola aleatoria, no existe en ningún repositorio, que es justo lo que buscaba el operador. La central la tienen fichada como «Bashlite». Ninguna de esas etiquetas dice shem, ni proxy, ni describe el protocolo. Para la automatización es ruido de Mirai; el nombre de familia no lo pone una máquina. No está sin catalogar por sigilosa: está mal catalogada porque rompe justo la pieza con la que se cataloga, el hash.
Con una excepción, y conviene decirla: XLab, el laboratorio de Qi'anxin, la bautizó Shemzbot el 23 de septiembre, en un tuit con el C2 correcto y el diagrama de su cadena RC4 .se/.sk/.z. Un vistazo certero, y de gente que sabe. Pero un tuit no es un destripe: lo que estás leyendo es lo que aquel mensaje no traía, desde la cola anti-IOC del §01 hasta el keystream reutilizado del §05 y el interruptor del proxy del §06. Y un guiño que me hizo gracia: ellos juntaron en un solo nombre los dos que yo había sacado por separado, mi shem de las cadenas y el zbot de los crons.
11Familia propia, con herencia (y en obras)
Propia en lo que importa: protocolo inventado (UDP/6881, magic SH, RC4), sin la tabla XOR de Mirai, arquitectura de cuatro transportes, y los marcadores shem por todas partes. No es un Mirai maquillado.
Heredada en los detalles: la killer-list con antivirus de Windows y el arsenal de exploits de dominio público. Y en obras: comparada con una compilación de apenas cinco días antes, en ese margen el autor había añadido los transportes relay y overlay, el propagador por SSH, la numeración de instancia SHEM_INST, el reporte ZCR1 y el intento de módulo de kernel. Es un proyecto que su dueño mejora semana a semana.
En el fondo, shem no es «o proxy o DDoS»: es una plataforma de acceso que hace las cuatro cosas (proxy SOCKS5 bajo demanda, DDoS, backdoor y gusano autorreplicante). El diseño apunta a que la monetización principal puede ser la reventa de proxies residenciales; el DDoS, la puerta trasera y la propagación son capacidades adicionales de la plataforma.
La tendencia, más allá de este bicho, está clara: el borde de la red se está convirtiendo en mercancía de proxy, y shem es un ejemplar particularmente completo de esa ola.
12Indicadores (IOCs)
Los estables, los que sobreviven a que el operador cambie de servidor mañana:
| Tipo | Valor |
|---|---|
| Familia | shem (nombre interno) · alias externo «Shemzbot» (XLab/Qi'anxin) · «zbot» = sus ficheros de cron |
| Firma en red | SSH-2.0-sheM · User-Agent: sheM · magic 53 48 («SH») sobre UDP/6881, cuerpo RC4 |
| Puertos (nodo) | 6881/UDP · 7331/TCP (SOCKS5) · 7332/TCP (reparto) · fórmula base+2N (N=SHEM_INST) |
| Detección | host que escuche P y P+1 TCP + (P−450) UDP |
| Vector | telnet 23 / 2323, credenciales de fábrica (root/xc3511, admin/admin, admin/1234) |
| Marcadores | /root/shem/{targets,web_targets,targets_adb}.txt · SHEM_INST · SHEM_LAB · SHEM_NOMASQ · SHEM_RAM_MB |
| Comandos | PROXYON PROXYOFF UPDATE SHELL UDP AMP SCAN STOPSCAN TGTS VTGT YOURIP NOREPL NOTOR NOIDIRECT DIE · modos direct/relay/tor/overlay |
| En el host | copias %s/.z en /tmp /var /etc /jffs /rw /data · cron 5 min que restaura · barrido SUID · insmod /tmp/zbot.ko · intento de autoborrado unlink /proc/self/exe (no efectivo en Linux) |
| Etapas por exploit | stub.<arch> (cargador+descifrador) · bot.<arch>.se (bot cifrado) · bot.<arch>.sk (clave RC4 128b, rota) |
| Claves .sk vistas (RC4 128b) | b2134c3e17e0a9b77119ebbf05f122b5 · 659ed8e9cee54f7127358ff92a96f6d2 (descifran su propio .se; rotan por build, ya caducadas) |
| Hash | IOC = BuildID + sha256 del ELF SIN la cola de relleno (el del fichero completo NO vale) |
| SHA-256 · ELF sin cola (x86_64, la que atacó el cebo) | 82ab1202a5941b9d2947e99b2b03bc469e2a97f590c6a4efea819da20a2d8124 (catalogado en MalwareBazaar/VT) |
| BuildID (x86_64) | 8e7a8299899cf8dcb9b64116645a236a63ded94c (pivote estable, sobrevive a la cola y al renombrado) |
| SHA-256 · copia con relleno | 1d3c4108464cd2370ee428c296f64552af89fdebf19051e4bb1666db9f46cf8b (ejemplo de UNA descarga; no agrupa: relleno aleatorio por entrega) |
| ELF sin cola · multi-arch (lote de reparto 23-sep) | bot.x86_64 674107dcf1a876489123240add215cbb92649c2bbb321780057822232891ac10 (build del reparto, distinta de la capturada) bot.arm64 ef7466d1507430fc0e0f99c29d7184ee726e68934895bfdc37ad855c0c488b91 bot.armv7 74af9d637530df497444e47bfc12e4aba66a084546d413d1e0b54d7282c2a777 bot.mipsel fe12480efddd9603004a4165265e57192242a79144b124a936bfe95e66de2cb4 (= mips64el, mismo ELF) stub.x86_64 37dd737a342729c7b8c4e6f28140f2ff977a433793482b6bd488efd56a20812e (catalogado en MB desde 20-sep) |
| Fingerprint C2 | clave SSH ce:cd:4c:9e:86:a2:76:40:40:88:f9:50:85:a8:21:01 (ecdsa) · hassh 671c5858… · puertos vistos por Shodan 22 / 8080 / 7434 (7434 = 7332+2·51; ficha parcial) |
| Infra C2 | 176.65.134.121 (datacenter, AS51396 Pfcloud) |
| Reparto | vía víctimas (p. ej. una línea residencial de HK); NO listar como infraestructura del operador |
| Firma del actor | bug de plantilla: hxxp://<IP>:<puerto>PROXYONUPDATE:<puerto>/bot.$m |
| Documentación pública | XLab (Qi'anxin) la nombró «Shemzbot» el 23-sep-2026 · el tuit (@Xlab_qax) |
Continuará - el cebo sigue encendido, y shem sigue en obras. Cuando el operador suelte la próxima versión, volveré a mirar qué le ha puesto. 🍯
Comentarios