Ploutus está de regreso, atacando cajeros de Itautec en Latinoamérica
diciembre, 12, 2022
17 minutos de lectura
Por: Jesús Domínguez del equipo Ocelot de Metabase Q
Desde su primera aparición en 2013, Ploutus ha sido conocido como el malware de cajeros automáticos (ATMs) más sofisticado en el mundo. En esta ocasión regresa con una variante enfocada a México y Latinoamérica. Ploutus permite a criminales vaciar cajeros automáticos en segundos, sacando ventaja de las vulnerabilidades XFS Middleware, a través de un dispositivo externo. Desde su primer descubrimiento, Ploutus ha evolucionado, pudiendo atacar diferentes tipos de middleware XFS. Investigaciones previas han descubierto los siguientes blancos y variantes:
Ocelot, el equipo de Seguridad Ofensiva de Metabase Q, ha identificado una nueva variante de Ploutus en Latinoamérica. Esta variante, nombrado Ploutus-I controla ATMs del fabricante brasileño Itautec, el cual, en 2013, formó una alianza con el fabricante japonés OKI para entrar al mercado de cajeros automáticos en Brasil, posteriormente, en 2019, NCR adquirió los servicios de Tecnología de la Información (TI) y otros activos seleccionados de OKI en Brasil.
En este blog, describiremos todos los detalles de esta nueva variante; empezando por el método de infección, pasando por la evasión de Antivirus, las capas de ofuscamiento, la interacción entre el malware y quienes realizan los ataques y terminando con los detalles sobre cómo se controla el XFS para extraer dinero del cajero.
Vista rápida al modus operandi de Ploutus-I
Instalación de Ploutus-I
Al inicio del ataque, el sujeto activo extrae el disco duro del ATM. Los binarios y artefactos de la siguiente tabla son copiados al directorio C:\itautec, el cual, se encuentra en la lista blanca del antivirus y, por lo tanto, evita ser escaneado y detectado.
Se logra la persistencia agregando la ruta del malware en la llave del registro con nombre Userinit, la cual almacena los programas que son ejecutados por el Winlogon una vez que la persona usuaria inicia sesión en el sistema.
La ruta es la siguiente:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Winlogon\
Como se muestra en la Figura 3, Ploutus-I, se hace pasar por un agente de protección y fue compilado por los creadores el 17 de abril de 2020.
Desofuscando Ploutus-I
Cada nueva variante de Ploutus es más difícil de desofuscar y esta última versión no es la excepción. Esta sección es altamente técnica pero sumamente importante de compartir con analistas de malware ya que se explica cómo hacer frente a este tipo de situaciones, protecciones y ataques. Si usted no está interesado en los detalles técnicos, por favor diríjase a la siguiente sección.
Ploutus-I siempre ha sido escrito en .NET Framework con un gran esfuerzo en su protección para evitar ser detectado por antivirus basados en firmas y, desde luego, para hacer la tarea de ingeniería inversa mas difícil para quien realiza el trabajo de análisis.
Antes de entrar en los detalles de la desofuscación, es imperativo comprender el proceso de ejecución del llamado managed code de .NET en memoria (C#, F#, etc). Para mayores detalles se recomienda leer el artículo de Phrack al respecto. Para el propósito de este blog, una explicación muy sencilla de este proceso se muestra en la Figura 4.:
Lo que el ofuscador Reactor (usado por Ploutus-I) hace es ofuscar, valga la redundancia, el código MSIL generado por el framework para que no pueda ser descompilado por herramientas como DnSpy evitando así, el acceso al código fuente para el análisis; sin embargo, en tiempo de ejecución, el código MSIL es desofuscado por el malware para entonces enviarlo al Just-In-Time(JIT) Compiler, el cual, finalmente, lo convierte en código nativo para ser ejecutado por el CPU. Entonces, ¿cómo podemos desofuscar el código y con esto entender detalles de esta nueva variante? Siga leyendo.
Al abrir el archivo Itautec.exe en DnSpy (ver Figura 5), podemos reconocer inmediatamente la misma estructura usada por la variante Ploutus-D. Los creadores solo agregaron una nueva función para poder interactuar con el XFS Middleware de Itautec/OKI.
Estrategia de desofuscación
Antes de entrar en los detalles de la estrategia de desofuscación, es importante entender cómo el ofuscador Reactor esconde el código malicioso en la memoria. Esto puede ser entendido en la Figura 8, donde observamos que:
Cuando una función maliciosa es llamada, JIT, a su vez, llama a getJIT para obtener la dirección de compileMethod, el cual genera el código nativo a ejecutarse.
Sin embargo, Ploutus-I ya ha instalado un gancho, o hook, que permite redireccionar todas las llamadas hacia dicha función a su propia ruta; posteriormente, desofusca el código MSIL de la función y entonces llama a la dirección original de compileMethod para su compilación y ejecución.
Es importante mencionar que este proceso solo sucede en memoria y solo para la función que se está llamando en ese momento, esto explica porque no hay visibilidad en el código de las funciones en DnSpy.
Con este contexto, nuestra estrategia es poner un breakpoint, en la dirección original de compileMethod y correr el malware tratando de identificar la función de lo esta interceptando.
Para lograrlo, debemos usar una herramienta más avanzada, el debugger Windbg con su extensión SOS.dll para poder analizar el Managed code de .NET.
En la Figura 9, se puede ver que pusimos un breakpoint en la función getJit (exportada por crljit.dll), ya que esta regresa una tabla de indicadores (VTable) donde ¡el primer puntero corresponde a la dirección de compileMethod!
Una vez puesto el breakpoint en el compileMethod (0x6e1e3700), y dejando correr el malware, observamos en la Figura 10 el momento en el que el breakpoint es alcanzado; es ahí cuando usamos el comando ¡CLRStack para ver la lista de funciones llamadas hasta ese momento y ¡voilà! Encontramos el método malicioso de Ploutus-I que redirecciona la ejecución cuando el compileMethod es llamado:
GQa2qrta795LeasM25.vlIg50mEXlJEDAGw36.GyQV7V7HyQ()
Cabe destacar que esta función es llamada por cada constructor estático (.cctor) de cada clase en el malware, lo cual tiene sentido, cada método va a ser desofuscado individualmente en memoria y solo cuando se le llame, para entonces ser compilado en código nativo.
Desafortunadamente, todavía falta un camino por recorrer. En versiones previas de Ploutus, esta función identificada ya contenía el MSIL Code desofuscado por lo que solo faltaba vaciarlo o dumpearlo desde la memoria. Sin embargo, al ver a detalle la función (ver Figura 11) en DnSpy, entendimos que habíamos entrado a una nueva función fuertemente ofuscada con cientos de opciones en un switch selector, código espagueti, código muerto y otros trucos, haciendo imposible debuggearlo.
Al continuar analizando la función, y basándonos en versiones previas de Ploutus, supusimos que el keylogger ya está corriendo al fondo, es decir, en el background, por lo que presionamos las teclas de función “F” deteniendo casi de manera inmediata el debugger, de nuevo en el compileMethod (ver Figura 12), pero esta vez, al ver las funciones llamadas antes de ese punto, ¡identificamos la función que contiene el código MSIL desofuscado! Y que está listo para ser compilado en código nativo
GQa2qrta795LeasM25.vlIg50mEXlJEDAGw36.NvQ34uZt895nxEhi2FIr()
Dentro de la función mostrada en la Figura 13, el código desofuscado de MSIL es pasado a la función compileMethod (línea 35) que, como se describe en el artículo de Phrack, recibe en su segundo parámetro la estructura CORINFO_METHOD_INFO, donde podemos obtener la dirección de MSIL Code y el tamaño del código (resaltado en amarillo):
Con esta información, podemos obtener el código MSIL desde la memoria ya sea con DnSpy o con Windbg. Aquí puede encontrar una excelente herramienta escrita por @s4tan que desofusca automáticamente una versión anterior de Ploutus.
Comparemos los resultados en la función Launcher.KeyBoard::RealStart(), se puede notar en la Figura 14 que antes de ser desofuscada, no tiene contenido.
Una vez desofuscada como lo muestra la Figura 15, podemos ver el código MSIL Code ¡está listo para ser analizado!
Entendiendo el interior de Ploutus-I
Teniendo el código MSIL desofuscado en nuestras manos, podemos entender la nueva funcionalidad que trae consigo esta variante. Nos concentramos en la función Launcher.KeyBoard::RealStart() que es la que despacha las diferentes acciones a ejecutar por el malware. Se implementa un keylogger (nada nuevo aquí) para interceptar las teclas presionadas por el sujeto activo con el teclado externo. Cabe destacar que esta variante se pudo ejecutar en Windows 7 y Windows 10.
Ploutus-I encripta todas las cadenas de texto que utiliza y cuando el malware las necesita llama a la instrucción ldc.14.s pasando un offset como primer argumento que guiará a una posición dentro de un arreglo de bytes en formato Unicode (previamente extraído de la sección de recursos y desencriptado en memoria), el cual, a su vez, regresará una cadena de texto. Por ejemplo, en la Figura 16, la instrucción “ldc.14.s 0x9f0”, extrae del arreglo de bytes en el offset 0x9f0 la cadena “F8F1F1”. Todos los strings extraídos se pueden encontrar en el apéndice A.
Siguiendo este procedimiento, identificamos la combinación de teclas para ejecutar distintas opciones del malware, como se muestra en la Figura 17.
Algunas funciones de versiones anteriores de Ploutus, todavía funcionan en esta variante, por ejemplo la función PrintScreen.Windows(), la cual una vez que recibe la combinación correcta, despliega la ventana que se muestra a continuación (Figura 18).
Como se muestra en la Figura 19, una vez que quienes realizan el ataque ingresan la combinación «F8F1F2F3F4» la función Launcher.Launch::LaunchClient() es llamada.
Ya dentro de la función Launch.LaunchClient(), podemos ver que que el offset 0x218 se usa como offset para obtener una cadena de texto, que resulta ser “GG.exe”, la cuales la encargada de controlar el XFS Middleware del cajero (ver Figura 20).
Finalmente, el binario GG.exe es ejecutado pero falla en nuestro laboratorio al no tener todas las DLLs necesarias (ver Figura 21).
Controlando el XFS Middleware para ordeñar el ATM
El binario GG.exe y XFSGG.dll son usados para interactuar con el XFS Middleware de Itautec/OKI. Al observar las propiedades del binario, es descrito como “JIG NMD” como se muestra en la Figura 22, lo cual parece una herramienta de Itautec legítima para probar la funcionalidad del Dispensador. No es nuevo que los atacantes ocupen estas herramientas de mantenimiento, pero es interesante ver que la banda de Ploutus no siguió su metodología de controlar directamente el XFS Middleware, lo que sugiere que la gente detrás de este ataque no es la misma de variantes anteriores.
Y la herramienta esta escrita en portugués, en la Figura 23, algunas cadenas de texto del binario lo demuestran.
GG.exe, abre una sesión con el Dispenser usando su nombre lógico “NDC_CASH_DISPENSER” para pedir información del periférico usando el código 310 y la acción: WFS_INF_CDM_CONF” como se muestra en la Figura 24.
Una vez abierta la sesión, GG.exe lee los datos del dispensador usando la acción “WFS_CMD_CDM_READ_DATA”, normalmente, para asegurarse que cuenta con billetes, así como la denominación de cada Cassette (ver Figura 25).
Después, Ploutus-I pide un código de activación que tiene una función similar a la de una licencia de software. Este código, permite a los criminales limitar el número de veces que el sujeto activo puede usar Ploutus-I al día. Si el código es correcto, ¡es momento de recibir el dinero! En esta etapa, el comando «WFS_CMD_CDM_PRESENT» instruye al dispensador entregar el efectivo al sujeto activo (ver Figura 26).
Quienes realizan el ataque conocen a la perfección el cajero que vandalizan, incluyendo sus capacidades físicas, como la cantidad máxima de billetes que pueden pasar por la escotilla (en este caso es un total de 70) y si sabemos que Ploutus-I empezará sacando dinero del Cassette con mayor denominación ($500 pesos), podemos concluir, que por cada ciclo de retiro se obtienen $35,000 MXN (~$1677 USD).
Toda esta actividad de retiro es guardada en un log en: C:\itautec\exe\LibraryLog.txt, donde se puede ver la secuencia antes descrita (ver Figura 27)
Por otro lado, Ploutos-I guarda una base de datos SQLite con las actividades realizadas por GG.exe en la siguiente ruta: c:\Users\%USERNAME%\AppData\Roaming\NewLog (ver Figura 28)
Recomendaciones
Revisión periódica de los directorios activos en la lista blanca del antivirus, asegurándose de que no haya rutas de archivos desconocidos.
Actualización automática del software que corre en el ATM (en caso de ser posible).
Mantener actualizadas las firmas del antivirus.
Realizar de manera correcta el cifrado del disco duro. Si bien son recomendaciones sencillas, es de suma importancia realizarlas correctamente, ya que una mala implementación podría permitir a atacantes interceptar las llaves del volumen guardadas en el chip de TPM a CPU, mientras pasan por el bus de SPI/I2C, entre otros ataques).
Instalar cámaras cifradas de extremo a extremo de última generación, administradas centralmente con detección de manipulación, alertas de movimiento y detección facial.
Llevar a cabo un Pentest periódico, el cual identifica vulnerabilidades y contramedidas en Hardware, XFS Middleware, Firmware y Software.
Asegurarse de que el proveedor genere Indicadores de Ataque (IOA) e indicadores de Compromiso (IOC) durante este ejercicio para mejorar la detección y monitoreo de estos ataques.
Poner alertas para eventos específicos dentro del Journal, Antivirus, Event Log o XFS Log para responder a estos ataques lo más pronto posible.
Asegurarse que el proveedor entiende el formato utilizado por los Journals del ATM en cuestión y que pueda recomendarle el tipo de eventos a monitorear.
¿Quiénes somos?
Ocelot de Metabase Q, es el equipo de Seguridad Ofensiva de vanguardia en América Latina. Este equipo de élite está conformado por investigadores de talla mundial, que representan lo mejor de lo mejor; unidos con la meta de transformar la ciberseguridad en la región. La inteligencia de amenazas, investigación y habilidades ofensivas de Ocelot ayudan a mejorar constantemente las soluciones que ofrece Metabase Q.
Nuestro equipo de expertos en Penetration Testing se enfoca tanto en ataques físicos como lógicos. Ocelot realiza pruebas de ataques avanzados a ATMs, con malware hecho a la medida como Ploutus. Así mismo, lleva a cabo pruebas de ataques físicos al dispensador, incluyendo ataques con endoscopio, TPM Sniffing, DMA Attacks, Transaction Reversal Fraud, CMOS Shock, entre otros, para garantizar una experiencia real.
¿Sabe cómo funcionarían sus sistemas si sufrieran un ataque de ransomware o algún otro ataque avanzado? Gracias a nuestras habilidades de ingeniería inversa, investigamos APTs y replicamos su funcionamiento y TTPs en la red de nuestros clientes. Con ello, podemos replicar escenarios de Ransomware, Spear Phishing, Movimiento Lateral y Exfiltración de información para medir la efectividad de sus productos de seguridad y su inversión, así como el tiempo de respuesta de la organización.
¿Cuenta con dispositivos IoT/ICS? A estos también podemos realizar un pentest a su Hardware, Boot Loader, Middleware, Firmware y a nivel aplicativo.
Escribimos la primera guía de código seguro para BASE24 para encontrar vulnerabilidades en el switch transaccional o Banco en ambiente BASE24 o CONNEX identificando fallas en la autorización de pagos y violaciones de PCI.
Contáctanos en contact@metabaseq.com
Indicadores de compromiso:
C:\itautec\exe\*
C:\itautec\exe\LibraryLog.txt
c:\Users\<user>\AppData\Roaming\NewLog
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Winlogon\UserInit
Paths:
C:\itautec\exe\*
C:\itautec\exe\LibraryLog.txt
c:\Users\<user>\AppData\Roaming\NewLog
Apéndice A
Cadenas de texto del malware descifradas
IEBOLDP6
C:\Diebold\EDC\edclocal.dat2
[Launcher Client] Request
[LauncherSysApp] Request
CMD.exe /C wmic os where Primary=’TRUE’
reboot [Launcher]
TaskKill.exe /F /IM
GG.exe /F /IM
NDCPlus.exe /F /IM
winvnc.exe /F /IM
MSXFSEXE.exe /F /IM
CajaExpress.exe
GG.exe
C:\NDC+\Lib\MsXfsExe
C:\NDC+\Bin$
[Launcher Client] Admin /C
TaskKill /F /IM
XFSConsole.exe /C
START XFSConsole.exe /C
TaskKill /F /IM
NewAge.exe /C
START NewAge.exe P /C
«C:\Program Files\Diebold\AgilisStartup\AgilisShellStart.exe»
[Launcher] Start
AgilisT:\Program Files\NCR APTRA\SSS Runtime
Coren:\Program Files\NCR APTRA\SSS Runtime Core\ulSysApp.exe
[LauncherSysApp]
«C:\Probase\ProDevice\BIN\ProDeviceStart.bat»
C:\Probase\ProDevice\BIN8 /C
START Delete.bat & pause /C
CMD.exe
[Launcher] Start
CMD procexp.exe
c:\ProgramFiles\Diebold\AMI\Diagnostics\bin\Diebold.Ami.Diagnostics.Diagnostics.exe
c:\Program Files\Diebold\AMI\Diagnostics\bin$ /C
START Main.exe /F /IM
CMD.exe
[Launcher] Start
END /F /IM
Wscript.exe /F /IM script.exe /F /IM vpncli.exe
DIEBOLDJ[Launcher Client]
Inicio Directo BootH
[Launcher Client]
Inicio Directo EPP
LauncherStart
Loading Wait
Press[Esc] to Continue
Software\Microsoft\Windows NT\CurrentVersion\winlogon
/C net localgroup administrators /add
[Launcher]
UserPermision Done
Done
[LauncherConfig:]
Service: >[LauncherConfig:]
Launch Menu: <[LauncherConfig:]
Launch App: <[LauncherConfig:]
LaunchDate: 6[LauncherConfig:]
TimeOut: 8[LauncherConfig:]
ReadFile: B[LauncherConfig:]
ExternalDrive: 2[LauncherConfig:]
Patch:
Reset.txt
[Launcher] Windows 7 Detected
install /c
C:\Windows\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe: & net start DIEBOLDP & pause
installonly
& pauseuninstall /c
C:\Windows\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe/u
test
[Launcher] Starting App Mode Detect Windows 7.B[Launcher]
Starting Service Mode.:[Launcher]
Starting App Mode.Launcher
43246*******4354
5204167231340092
CopyData:
$Config
Read
Start
File Exist.
File Open.
Read End.
Error.
Config New File.
Agilis.log
Config New
File Close.
ConfigCopy:
N.bin
Ploutos
Log.txt
Diebold Event
LogTSYSTEM\CurrentControlSet\Services\DIEBOLDP
Typej
SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Winlogon
Userinit /C REG ADD»HKEY_LOCAL_MACHINE\Software\Microsoft\WindowsNT\CurrentVersion\Winlogon» /v Userinit /t REG_SZ /d «» /f
cmd.exe
Abrir
Arial
Black
Cerrar
Reiniciar
\\.\DISPLAY1
TEST OK
DISPLAY2
END OK
Could not impersonate the elevated user.
LogonUser returned error code {0}.
Load