El malware creado en Go es tendencia y ha llegado para quedarse

David García    3 agosto, 2021
malware Go

Aunque no se podría decir que Go es un lenguaje de programación nuevo (tiene ya más de diez años) sí que pertenece a esa nueva hornada de lenguajes que junto a Rust, Typescript, Zig, etc. que están despuntando cada vez más en los últimos tiempos. Go nació, en cierto modo, de la necesidad de Google de encontrar un sustituto al eficiente pero inmensamente complejo C++. Esa complejidad producía dos efectos nada deseables en una compañía: tiempos de compilación muy dilatados y poca oferta de ingenieros con un nivel alto de conocimientos; muy necesarios si se quiere sacar partido (y no generar fallos de seguridad) al lenguaje.

Así, nombres ampliamente conocidos como Rob Pike o Ken Thompson y otros diseñaron un lenguaje de programación que cubriese las necesidades descritas anteriormente. Un lenguaje que fuese seguro, sin errores de memoria que se tradujesen en vulnerabilidades de seguridad, tiempos reducidos de compilación, multiplataforma, orientado a Internet y a la programación concurrente. A priori, la tarea parecía un reto inabarcable, la cuadratura de un círculo perfecto.

Pero funcionó, Go era (y es) sencillo, seguro, potente y moderno. El éxito está fuera de toda duda. Es ya un ecosistema que ha producido proyectos como Docker, Kubernetes o CoreOS. Su sintaxis, que hereda la sencillez del lenguaje C, ha abierto las puertas a una ingente cantidad de programadores con su suave curva de aprendizaje y gestión automática de la memoria.

¿Es esa sencillez de uso la que ha provocado que el malware lo adopte como una lengua “oficial” más?

Una de las primeras oportunidades de ver a Go usado como parte de la infraestructura de un malware fue con la botnet Mirai (cuyo código fuente fue liberado y puede leerse aquí). Si recordamos, Mirai se enfocaba en la búsqueda y detección de dispositivos con contraseñas fáciles o por defecto. Tuvo un tremendo éxito y a los pocos días de echar a rodar sumaba millones de nodos bajo su control.

Aunque Mirai estaba escrito principalmente en el venerable lenguaje C, su centro de control (C2) estaba escrito en Go:

Quienes diseñan y programan malware no difieren mucho de un desarrollador salvo la intencionalidad, evidentemente maliciosa. Al final, es un proceso de evolución bien definido que incluye actualizaciones, mejoras y corrección de bugs con la continua liberación de nuevas versiones. Tampoco podemos olvidar que la vida de un malware es corta y termina cuando la industria antivirus despliega las firmas necesarias para su detección. Nuevas versiones del mismo malware permiten aumentar esa ventana de infección, al pasar por debajo del radar de los antivirus, aunque sea momentáneamente.

Dado que la creación de malware no dista mucho de la del software común, las herramientas siguen siendo comunes y estas no son ajenas a los cambios de tendencias. Además, en Go se han encontrado con una herramienta con características muy deseadas: multiplataforma, gestión automática de memoria, test unitarios integrados en el lenguaje, etc.

No solo hallaron una buena herramienta, sino que en Go los binarios producidos portan de forma estática las librerías necesarias para su ejecución, es decir, no necesitan que el sistema posea una librería concreta, ya la incluyen ellos incrustada en el ejecutable. Esto, sin embargo, provoca que los binarios alcancen tamaños “anormales”, de varios megas, circunstancia que puede ser ambivalente: permite caracterizarlos y por el contrario un gran tamaño pone trabas a la inspección automática.

¿Es esto suficiente para el relativo éxito que está teniendo Go en su adopción respecto al malware?

Cuando un analista se interesa por una muestra concreta utiliza un conjunto de herramientas para empezar a hacerse una idea de lo que tiene delante. Entre el análisis estático y dinámico se va trazando un cuadro que termina por dibujar las intenciones de un malware.

Los analistas llevan décadas de experiencia tratando con ejecutables producidos por los compiladores habituales y hechos en C o C++ en su inmensa mayoría. Los binarios de Go se estructuran de forma diferente y al abrirlos para su inspección el analista se encuentra con un territorio desconocido. Las herramientas usadas necesitan, por tanto, adaptarse a este nuevo canon para dar con un proceso ágil de análisis.

Mientras eso ocurre, los creadores de malware ven un añadido beneficioso el hecho de que producir un binario en Go permite enfangar los análisis y aumentar la ventana de actividad del malware.

Una pequeña muestra, dos programas básicos, dos “Hello World” en C y en Go. Fijémonos en sus tamaños:

Ahora, veremos la cantidad de funciones (símbolos) que portan cada uno de los binarios producidos:

Como podemos observar, el binario de Go no solo porta el programa, consigo va un grupo de funciones procedentes de su librería estándar y que nos permiten imprimir en el terminal la clásica frase “Hello World”. Este comportamiento puede ser reproducido por C si hubiésemos compilado estáticamente todo lo necesario para que realice la misma función, pero no es lo común.

No obstante, el número de funciones no debe amedrentar a un experimentado analista. Solo es paja que hay que ir retirando hasta alcanzar la verdadera raíz del binario, el comportamiento codificado por sus autores. Así, tan solo hay que ir adaptando las herramientas ya disponibles de ingeniería inversa y análisis al nuevo panorama.

Por cierto, si hacemos stripping (borrar información de debug y símbolos (nombres de funciones, etc.)) de un binario en Go, los símbolos (al igual que su homólogo en C) desaparecen y dificultan, si cabe, aun más el análisis:

Solo es la punta del iceberg. Existen muchos más problemas que deben afrontar los analistas para ir desenredando la madeja: detección de cadenas, reservas de memoria, etc. Todo “parece” familiar a los binarios producidos por otros compiladores, pero es distinto en la forma en el que se efectúan operaciones habituales. Es como hablar ensamblador, pero con un acento notablemente diferente.

¿Es entonces una tendencia firme a seguir?

El número de muestras de malware crece a diario en proporciones ingentes. Obviamente, muchas son variantes de una misma familia y existe un crisol de lenguajes de programación sobre el que se diseñan y liberan.

Ya en 2019, un estudio de la UNIT42 de PaloAlto Networks arrojaba un número de 13.000 muestras únicas de malware creado en Go. Un par de años después, la tendencia se iba confirmando por otros laboratorios, como el informe de Intezer publicado el pasado marzo, representaba un crecimiento del 2000% desde hace unos años atrás.

No solo Go

Otro lenguaje de programación de factura moderna es Rust, nacido en el seno de Mozilla, ahora independizado de la organización del navegador Firefox. Tampoco se libra de ser usado por los cibercriminales para incluirlo en su arsenal de herramientas.

Además, curiosamente, Rust, que es un lenguaje llamado a ser el sustituto del complejo y enorme C++, posee un meme denominado “Rewrite it in Rust”, consistente en solicitar a proyectos que no estén escritos en Rust que vuelvan a reescribirlos en este lenguaje. Evidentemente, en un tono jocoso y burlesco.

Pues bien, ha ocurrido de forma real en el mundo del malware con “Buer”. Este malware se dio a conocer escrito en lenguaje C… hasta que hace unos meses se encontraron con una reescritura completa (rewrite it…) en Rust.

El malware es una industria, que no nos extrañe, y los procesos que son inherentes a la industria terminan por permear a aquellos. Las cadenas de diseño, montaje, despliegue y calidad son calcos a los usados por las organizaciones. Como hemos visto, se usará todo aquello que suponga una ventaja competitiva usando las últimas tendencias en desarrollo.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *