Una herramienta de ingeniería inversa para binarios compilados por Nim
Investigación ESET
Disponible como complemento IDA y script de Python, Nimfilt ayuda a aplicar ingeniería inversa a archivos binarios compilados con el compilador del lenguaje de programación Nim al desmantelar nombres de paquetes y funciones, y aplicar estructuras a cadenas.
23 de mayo de 2024
•
,
6 min. leer
El nim El lenguaje de programación se ha vuelto cada vez más atractivo para los desarrolladores de malware debido a su robusto compilador y su capacidad para trabajar fácilmente con otros lenguajes. El compilador de Nim puede compilar Nim a JavaScript, C, C++ y Objective-C, y compilación cruzada para los principales sistemas operativos como Windows, Linux, macOS, Android e iOS. Además, Nim admite la importación de funciones y símbolos de los lenguajes mencionados anteriormente y la importación desde bibliotecas vinculadas dinámicamente para Windows y bibliotecas compartidas para Linux. También están disponibles módulos envolventes de Nim, como Winim, que hacen que la interacción con el sistema operativo sea sencilla. Todas estas capacidades permiten una fácil integración de Nim en los procesos de desarrollo utilizando estos lenguajes e impulsan el desarrollo de nuevas herramientas, tanto benignas como maliciosas.
No sorprende, entonces, que ESET Research haya observado un uso continuo de malware desarrollado en Nim en estado salvaje. Ya en 2019, Sednit era manchado usando un descargador malicioso escrito en Nim. Otro grupo notorio que juega el juego de Nim, y el ímpetu para desarrollar de una ninfaes el panda mustang Grupo APTO. Investigación de ESET registrada Mustang Panda usando Nim en su conjunto de herramientas por primera vez en una campaña contra una organización gubernamental en Eslovaquia en agosto de 2023. La DLL maliciosa detectada y utilizada como parte del clásico grupo tridente Cargador Korplug: fue escrito en Nim.
Para los investigadores encargados de realizar ingeniería inversa en dichos binarios, Nimfilt es una herramienta poderosa para acelerar el análisis. Si bien Nimfilt se puede ejecutar como un script de Python tanto en la línea de comando (con un subconjunto de su funcionalidad) como en Hex-Rays AIF programa, se presentará aquí principalmente como un complemento de Python para IDA.
Inicializando Nimfilt en IDA
Cuando IDA se abre por primera vez, carga e inicializa los complementos en el directorio de complementos de IDA. Durante la inicialización de Nimfilt, el complemento utiliza heurística básica para determinar si el binario desensamblado se compiló con el compilador Nim. Si se pasa una de las siguientes comprobaciones, Nimfilt determina que se utilizó este compilador:
- El binario contiene las dos cadenas siguientes:
- El binario contiene cualquiera de los siguientes nombres de funciones de Nim conocidos:
- NimPrincipal
- NimPrincipalInterior
- Módulo principal de Nim
- El binario contiene al menos dos de las siguientes cadenas de mensajes de error:
- @valor fuera de rango
- @división por cero
- @desbordamiento excesivo o insuficiente
- @Índice fuera de los límites
Las reglas YARA se proporcionan junto con Nimfilt que realizan comprobaciones similares para determinar si un archivo ELF o PE se ha compilado con Nim. En conjunto, estos controles son mucho más sólidos que el enfoque adoptado por otras herramientas, como Detectarlo fácilque actualmente sólo comprueba el .rdata sección de archivos PE para la cadena io.nim o fatal.nim.
Como paso final de inicialización, si Nimfilt AUTO_RUN bandera se establece en verdadero, el complemento se ejecuta inmediatamente. De lo contrario, Nimfilt se puede ejecutar como de costumbre desde el menú de complementos de IDA, como se muestra en la Figura 1.
Desafiando con Nimfilt
Nim utiliza un esquema de manipulación de nombres personalizado que Nimfilt puede decodificar. Durante una ejecución, Nimfilt itera a través de cada nombre de función en el binario, verificando si el nombre es un paquete Nim o un nombre de función. Los nombres descubiertos cambian de nombre a sus formas demandadas.
Curiosamente, estos nombres pueden filtrar información sobre el entorno del desarrollador, de forma muy similar a las rutas PDB. Esto se debe a que el compilador de Nim agrega la ruta del archivo al nombre durante la manipulación; Nimfilt revela la ruta al realizar la manipulación.
Por ejemplo, los nombres de funciones de paquetes de terceros se almacenan como rutas absolutas durante el proceso de manipulación. La Figura 2 muestra el nombre de una función que se almacena como una ruta absoluta que revela la versión y la suma de verificación del nimSHA2 paquete utilizado, junto con la ruta de instalación del desarrollador para ágil – Administrador de paquetes predeterminado de Nim.
Python nimfilt.py GET_UINT32_BE__6758Z85sersZ85serOnameZOnimbleZpkgs50Znim837265504548O49O494554555453d57a4852c515056c5452eb5354b51fa5748f5253545748 505752cc56fdZnim83726550_u68
C:/Users/User.name/.nimble/pkgs2/nimSHA2-0.1.1-6765d9a04c328c64eb56b3fa90f45690294cc8fd/nimSHA2::GET_UINT32_BE u68
Figura 2. Exigir el nombre de una función de un paquete de terceros
Por el contrario, la Figura 3 muestra el nombre de una función de un paquete Nim estándar almacenado como una ruta relativa (es decir, relativa a la ruta de instalación de Nim).
Python nimfilt.py toHex__pureZstrutils_u2067
puro/strutils::toHex u2067
Figura 3. Exigiendo el nombre de una función de un paquete estándar de Nim
Sin embargo, los nombres no siempre se mutilan de la misma manera. La Figura 4 muestra que el mismo nombre de función anterior del paquete nimSHA2 se almacena en Linux como una ruta relativa.
Figura 4. Exigiendo el nombre de una función de un paquete de terceros en Linux
Las funciones de inicialización de paquetes se modifican de una manera completamente diferente: el nombre del paquete se almacena como una ruta de archivo (incluida la extensión del archivo) colocada antes del nombre de la función y se utiliza un esquema de escape para representar ciertos caracteres como barras diagonales, guiones y puntos. Al realizar la demanda, Nimfilt limpia el nombre del paquete eliminando el .nim extensión de archivo, como se muestra en la Figura 5.
Figura 5. Exigiendo el nombre de una función de inicialización de un paquete de terceros
La Figura 6 muestra cómo los nombres de las funciones de inicialización de los paquetes nativos se almacenan como rutas absolutas.
Python nimfilt.py atmCatcatstoolsatsNimatsnimminus2dot0dot0atslibatssystemdotnim_Init000
C:/herramientas/Nim/nim-2.0.0/lib/system::Init000
Figura 6. Exigiendo el nombre de una función de inicialización desde un paquete nativo
En IDA, el proceso de gestión de nombres de Nimfilt es seguido por la creación de directorios en la ventana Funciones para organizar funciones según su nombre de paquete o ruta, como se muestra en la Figura 7.
Aplicar estructuras a cadenas Nim
La última acción realizada durante la ejecución de Nimfilt es aplicar estructuras de estilo C a las cadenas de Nim. Así como las cadenas en algunos otros lenguajes de programación son objetos en lugar de secuencias de bytes terminadas en nulo, también lo son las cadenas en Nim. La figura 8 muestra cómo la cuerda A B C D E F Aparece en IDA antes y después de ejecutar Nimfilt. Tenga en cuenta que en forma desensamblada, un binario compilado con Nim usa el prefijo _TM como parte del nombre temporal de algunas variables; Suelen ser cadenas de Nim.
Nimfilt itera a través de cada dirección en el .rdata o .rodata segmento y en cualquier otro segmento de datos de solo lectura, buscando cadenas de Nim. Las estructuras se aplican a cualquier cadena descubierta; la estructura contiene un campo de longitud y un puntero a la carga útil que consta de los caracteres de la cadena.
Envolver
En camino a ser compilado como ejecutable, el código fuente de Nim generalmente se traduce a C o C++; sin embargo, este proceso no elimina por completo todos los rastros de Nim. Al realizar un recorrido por el código fuente del compilador de Nim, hemos desentrañado algunos de los caminos tomados en el proceso de compilación y, por lo tanto, pudimos construir Nimfilt como una herramienta de Python y un complemento IDA para ayudar en este desenredado.
En resumen, ya sea que sea nuevo en Nim o no, recurrir a Nimfilt hará que su trabajo de ingeniería inversa con binarios compilados por Nim sea casi instantáneamente más fácil y más enfocado. Sin embargo, el desarrollo de Nimfilt no está paralizado en ningún caso; Estamos trabajando en funciones adicionales para manejar la doble manipulación y mejorar el formato de los nombres solicitados y la agrupación de nombres de paquetes.
El código fuente y la documentación de Nimfilt están disponibles en un repositorio alojado en la organización GitHub de ESET en https://github.com/eset/nimfilt.