La búsqueda de identificación
En mi entrada “El misterio de la infraestructura de Duqu“, en el que describí uno de los principales misterios que quedaban sobre Duqu, las singularidades del módulo de comunicaciones del centro de comando que parece estar escrito en un lenguaje distinto al del resto del código de Duqu. Como expertos técnicos, este tema nos intrigó y confundió bastante y quisimos compartirlo con la comunidad.
Los comentarios que recibimos sobrepasaron nuestras expectativas más optimistas, más de 200 comentarios y más de 60 mensajes de correo con sugerencias sobre posibles lenguajes e infraestructuras que pudieron usarse para generar el código de Duqu Framework. Queremos decirles a todos: ¡muchas gracias! por haber participado en esta búsqueda ayudándonos a identificar el misterioso código.
Echemos una mirada a las sugerencias más populares que hemos recibido:
- Variantes de LISP
- Forth
- Erlang
- Google Go
- Delphi
- OO C
- Viejos compiladores para C++ y otros lenguajes
Gracias a varios comentarios muy útiles y eruditos podemos decir ahora, con mucha certeza, que hemos dado con la respuesta correcta. Quisiera citar los comentarios más relevantes que
nos ayudaron a resolver este rompecabezas:
igorsk
Simple Object Orientation (para C)
Parece que alguien en reddit (http://www.reddit.com/r/ReverseEngineering/) tuvo suerte: los códigos snippets parecen_muy_similares a lo que esto produciría: http://daifukkat.su/wiki/index.php/SOO
Hay unas cuantas infraestructuras OO para C, pero tampoco coinciden: http://ooc-coding.sourceforge.net/ http://sooc.sourceforge.net/
Jonwil
Re: ¿Otro compilador C/C++?
He visto cómo funciona internamente GCC y su ABI (para varias versiones distintas) y puedo confirmar con certeza que el código Duqu no se genera con GCC. No sé cómo funcionan otros compiladores de C++, pero las cosas que veo en el ASM (como adónde van los punteros de funciones, la forma en que el “puntero” pasa, etc.) no me sugieren el uso de C++, sino de otra cosa por completo (como la infraestructura “object-oriented” para C que hemos mencionado).
igorsk
Re: ¿Otro compilador C/C++?
Estoy 99% seguro de que el código de la máquina fue generado por MSVC. Es algo que uno sabe por experiencia, pero puedo señalar dos cosas que son bastante propias de MSVC: 1. usa esi como primer candidato para almacenamiento temporal; 2. “pop ecx” en lugar de “add esp. 4”.
También hemos recibido dos mensajes muy interesantes: Pascal Bertran, alias bps, y otro autor que prefiere permanecer anónimo, sugirieron que el código se generaba desde un dialecto C object-oriented personalizado, conocido como “OO C”.
Estos comentarios fueron muy importantes porque nos permitieron rastrear con precisión el compilador usado en el proyecto: Microsoft Visual Studio. Me dediqué a experimentar con diferentes versiones de los compiladores MSVC y diferentes códigos fuente y opciones de compilación tratando de reproducir el código binario de la función constructora mencionada en la anterior entrada de la bitácora, hasta que lo logré.
Disección del código original Duqu: construcción de linked list class
Código C manualmente descompilado que produce el mismo código
Este código C, cuando se compila con MSVC 2008 y opciones /01 (tamaño mínimo) /Ob1 (expand only __inline) produce los opcodes idénticos a los del binario de Duqu. Al cambiar el orden de las operaciones y de los bloques “if/else” se modifica el código resultante; el compilador MSVC 2005 también produce un código algo diferente. Entonces, podemos decir con mucha certeza, que el binario resultante se compiló con MSVC 2008 y las opciones /O1 /Ob1 y que el código fuente de entrada fue completamente C.
¿Y qué significa esto? En breves palabras, que hay dos respuestas probables a nuestra pregunta inicial:
- El código se escribió con una infraestructura personalizada OO C, basada en macros o directivas de preprocesamiento personalizadas. Los comentarios recibidos sugirieron esto, porque es la forma más común de combinar la programación object-oriented con el lenguaje C.
- Todo el código se escribió a mano en OO C, sin ninguna extensión al lenguaje. No podemos negar por completo esta posibilidad, porque es casi imposible diferenciar el código escrito con directivas macro del código copiado-pegado a mano.
A juzgar por la cantidad de códigos similares en cada función constructora y en las funciones miembro, podemos suponer que se usó el preprocesamiento del código fuente y que la variante 1 está más cercana a la verdad.
Ahora bien, existen varias infraestructuras “OO C” de código abierto, y algunas producen construcciones de códigos que son muy similares a las del código Duqu. La mejor coincidencia que encontramos es SOO (Simple Object Orientation for C). Sin embargo, no se pudo haber usado en Duqu, porque se publicó cuando el troyano ya estaba circulando en Internet.
No importa cual de estas dos variantes sea la verdadera, las consecuencias son impresionantes. La carga de datos DLL contiene 95 Kbytes de códigos dirigidos por sucesos escritos en OO C, un lenguaje que carece de gestión automática de memoria para punteros seguros. Este tipo de programación es más común en complejos proyectos “civiles” de software que en los programas maliciosos modernos. Además, toda la arquitectura dirigida por sucesos debe haberse desarrollado como parte del código Duqu o su extensión OOC.
No existe una explicación sencilla para que se haya usado OO C en lugar de C++. Sin embargo, hemos visto casos similares antes. Los programadores que prefieren estas técnicas nos dan dos razones para ello:
- No confían en los compiladores C++; generalmente se trata de antiguos programadores, cuando el ensamblador era la mejor opción. C fue un paso revolucionario directo sobre el ensamblador y pronto se estandarizó. Cuando se publicó C++, muchos programadores de la vieja escuela prefirieron mantener sus distancias con este lenguaje porque desconfiaban de su distribución de memoria y otras funciones oscuras que causaban ejecuciones indirectas de códigos (por ejemplo, constructores).
- Extremadamente portátil. Una vez más, en los viejos tiempos (hace 10-12 años) C++ no estaba estandarizado por completo y era posible tener un código C++ que se compilaría con MSVC pero no con (por ejemplo) Watcom C++. Si uno optaba por la extrema portabilidad y apuntaba a cualquier plataforma, necesitaba C.
Ambas razones parecen indicar que el código lo escribió un equipo de desarrolladores expertos de la “vieja escuela”.
Conclusiones
- La infraestructura de Duqu consiste en un código C compilado con MSVC 2008 usando las opciones especiales /O1 y /Ob1.
- Es muy probable que el código se haya escrito con una extensión personalizada de C, conocida como OO C.
- La arquitectura dirigida por sucesos se desarrolló como parte de la infraestructura de Duqu o de su extensión OO C.
- El código de control y comando puede haber sido reutilizado desde un proyecto de software existente e integrado en el troyano Duqu.
Todas las conclusiones anteriores señalan hacia un equipo de desarrolladores profesionales que parecen haber reutilizado un antiguo código escrito por experimentados desarrolladores de la “vieja escuela”. Estas técnicas suelen verse en software profesional y es muy raro encontrarlas en los modernos programas maliciosos. Una vez más, estas técnicas señalan que Duqu, al igual que Stuxnet, es un programa malicioso único que sobresale como una joya entre la gran masa de programas maliciosos “tontos” que normalmente encontramos.
Resuelto el misterio de la infraestructura de Duqu