Ploutus is back, targeting Itautec ATMs in Latin America
December, 12, 2022
14 minutes read
By Jesus Dominguez from Metabase Q’s Ocelot Team
Ploutus, one of the most sophisticated ATM malware families worldwide, is back with a new variant focused on Latin America. Discovered for the first time in 2013, Ploutus enables criminals to empty ATMs by taking advantage of ATM XFS middleware vulnerabilities via an externally connected device. Since its first discovery, Ploutus has evolved to target various XFS middleware types, focusing on banks across Mexico and Latin America. Previously, researchers have discovered the following variants and associated target middleware:
Ocelot, the Offensive Security research team of Metabase Q, identified a new variant of Ploutus in Latin America. This variant, dubbed Ploutus-I, controls ATMs from the Brazilian vendor Itautec. Itautec has been connected to other major ATM players over the years. In 2013, the Japanese manufacturer, OKI, partnered with Itautec to enter the Brazilian market; subsequently, NCR acquired OKI’s IT services and selected software in Brazil in 2019.
Throughout this blog, we will describe the details of this new variant. We will cover the infection methodology, AV bypass technique, obfuscation layers, malware interaction with the crooks, and the XFS control to dispense the money on demand.
Ploutus-I heist operation overview
Ploutus-I Installation
At the beginning of the heist, the mule extracts the hard disk from the ATM. The binaries and artifacts (seen below) are copied to the path C:\itautec. Because this path is whitelisted by the Antivirus, the binaries and artifacts can bypass detection.
Persistence is gained by adding the malware path to the Userinit registry key (see Figure 2), which lists the programs run by Winlogon when a user logs in to the system.
This path is found here: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Winlogon\
The Ploutus-I executable is shown as “Itautec Protection Agent,” with a compilation time of April 17, 2020.
Deobfuscating Ploutus-I
Every new variant of Ploutus is harder to deobfuscate, and this last version is not the exception. This section is highly technical but essential to share for researchers to improve awareness and ATM security in the future. If you are not interested in the technical details, please skip to the next section.
Ploutus-I has always been written in .NET Framework as a method of further obfuscation to avoid signature-based detection and to make the reverse engineering task very challenging.
Before getting into the deobfuscation details, it is imperative to understand how the execution of .NET managed code(C#, F#, etc.) occurs in memory. For a more detailed explanation, we recommend reading Phrack. For this blog, a minimalistic flow is shown in Figure 4.
In a glimpse, what Ploutus-I obfuscator (Reactor) does is obfuscate the MSIL Managed Code so that the source code cannot be displayed by DnSpy Debugger & Decompiler tool. At runtime, the malicious code is deobfuscated by the malware and then passed to the Just-In-Time (JIT) Compiler to create the native code that ends up been executed by the CPU. How can we recover the source code and understand the inner workings of the malware? Keep reading.
By opening the assembly file Itautec.exe (see Figure 5), we can immediately see the structure of the old variant Ploutus-D. Later in our discovery, we realized that the criminals behind Ploutus-D just added support to control Itautec/OKI XFS Middleware.
Deobfuscation strategy
Before digging into the deobfuscation strategy, it is crucial to understand how Reactor obfuscator hides the malicious code in memory. We can explain this obfuscation by looking at Figure 8, where:
When a specific MSIL Code Function (let’s say the Ploutus-I Keyboard one) is called, JIT is going to call getJIT to get the address of the compileMethod to compile it into Native Code
However, Ploutus-I already installed a hook in memory redirecting that address to its own malicious one. It then deobfuscates the function and finally calls the original compileMethod to proceed with normal execution.
It is worth mentioning that this process is performed at the memory and only for the function been called at that moment, explaining why there is no visibility of functions in DnSpy.
With this context, our strategy is to set a breakpoint in the original compileMethod in memory, to pivot from there into identifying the function of Ploutus-I controlling the deobfuscation process.
For this, we need to switch to a more advanced tool, the Windbg debugger, with its SOS.dll extension to deal with .NET Managed code.
You can see in Figure 9 that we set a breakpoint at function getJit() (exported by clrjit.dll) because it returns a VTable (array of pointers) where the first value is the address of the compileMethod!
Once we set a breakpoint at compileMethod(at 0x6e1e3700) and let the malware run, we can see in Figure 10 when the breakpoint hits. We then use the !CLRStack command to see the stack trace of managed code, and voila! We found the malicious method that redirects the execution when compileMethod is called:
GQa2qrta795LeasM25.vlIg50mEXlJEDAGw36.GyQV7V7HyQ()
It is essential to mention that each class’s static constructor (.cctor) in the malware code uses this function. This function usage makes sense because, as previously mentioned, every method is going to be deobfuscated in memory before getting compile into native code for execution.
Unfortunately, we are not there yet. In previous versions of Ploutus, the above function would contain the deobfuscation code for us to dump. However, when looking at the function (see Figure 11) in DnSpy, we realized we entered a vast obfuscated function with hundreds of switch cases, spaghetti code, death code, and other tricks, which make it impossible to debug.
We keep digging into the new function. Based on previous versions of Ploutus, we expected some keylogging to be running in the background. Based on prior discoveries, we pressed some F keys and eventually got a new hit at compileMethod (see Figure 12). When we looked at the stack trace, we identified the function that contained the deobfuscated MSIL Code that was about to call compileMethod to get executed!
GQa2qrta795LeasM25.vlIg50mEXlJEDAGw36.NvQ34uZt895nxEhi2FIr()
By accessing that function, as shown in Figure 13, the deobfuscated MSIL code is passed to the original compileMethod function (line 35). This process is described further in the Phrack article (referenced above). As a result, we receive the second parameter, the CORINFO_METHOD_INFO structure, where we can get the address where the MSIL Code is located and its size (highlighted in yellow):
With this information, we can either dump the MSIL Code from memory via DnSpy or directly in Windbg, and we are all set! An excellent tool written by @s4tan deobfuscating a previous variant of Ploutus.
Now, let’s compare the results by looking at the function Launcher.KeyBoard::RealStart() before deobfuscation. We can see it is empty in Figure 14.
And then, after the magic happens, we can see in Figure 15, the deobfuscated MSIL Code ready to be analyzed!
Understanding Ploutus-I Inner workings
With the MSIL Code in our hands, we can understand what is going on with this new variant. The primary function we focused on is Launcher.KeyBoard::RealStart() since it triggers all the actions executed by the malware. It implements a keylogger (already seen before) to intercept all keys and numbers entered by the mule via an external keyboard. It is essential to mention that this variant was successfully executed in the Windows 7 and Windows 10 versions.
Ploutus-I encrypts all its strings. When needing one of them, the malware will call the instruction ldc.14.s passing an offset as an argument that will be the pointer into a Unicode byte array decrypted from the resources section at runtime pointing to the plaintext value. For example, in Figure 16, the instruction “ldc.14.s 0x9f0”, goes to the offset 0x9f0 and returns the string “F8F1F1”. You can see all the strings extracted in the Appendix A section at the end.
Following this process, we were able to identify the combinations to trigger specific actions to Ploutus-I, as shown in Figure 17.
Some functions are from the previous version of Ploutus, but still work in this variant. As an example, PrintScreen.Windows() that once the correct combination is received, the screen at Figure 18 is displayed.
Once the combination “F8F1F2F3F4” is entered by the criminals, the Launcher.Launch::LaunchClient() is called as seen at Figure 19.
Then inside Launch.LaunchClient() function, we can see the offset 0x218 is used to decrypt a string which ended up being “GG.exe” that eventually is able to control the XFS middleware in the ATM (see Figure 20).
Finally the binary gets executed but fails in our system since no DLLs are present. See Figure 21.
Controlling XFS to dispense the money
The binary GG.exe and XFSGG.dll are used to interface with Itautec/OKI XFS Middleware. When examining the properties of GG.exe, it is described as “JIG NMD” as seen in Figure 22. This resembles a legitimate Itautec tool used to test the functionality of the Dispenser. While it is not novel that criminals utilize ATM maintenance tools for malicious purposes, it is interesting that the criminals behind Ploutus did not follow the same methodology to control the XFS middleware directly. This suggests that the group behind Ploutus-I may not be the same group that created prior variants.
Additionally of note, the tool is written in Portuguese. In Figure 23, some extracts of the strings in the binary are visible.
GG.exe opens a session with the Dispenser by using its logical name as “NDC_CASH_DISPENSER” in order to request information via code number 310 and action “WFS_INF_CDM_CONF” as shown in Figure 24.
Once the session opens, GG.exe reads data from the Dispenser via “WFS_CMD_CDM_READ_DATA” action, typically to get the total number of notes (bills) available and denomination. See Figure 25.
In the next step, Ploutus-I requests an activation code, similar to a software license. This code enables criminals to limit the number of times the mules can use Ploutus-I to once a day. If the code is correct, it’s “show me the money” time! In this stage, the XFS command “WFS_CMD_CDM_PRESENT” instructs the Dispenser to present the requested bills to the mule (see Figure 26).
As expected, the criminals know the exact ATM version they are targeting and its physical capabilities. As a result, in every round of attacks, the malware requested the maximum amount of bills to retrieve. In this case, the maximum number is 70, starting from the cassette with the highest denomination, to equal $35,000 MXN (~$1677 USD) per round. All the dispensing activity is stored in the log in: C:\itautec\exe\LibraryLog.txt. See Figure 27.
Also, Ploutus creates a SQLite Database at c:\Users\%USERNAME%\AppData\Roaming\NewLog, showing the dispensing related activities. See Figure 28.
Recommendations
Periodic check of AV whitelist folders to make sure they are up to date and do not have malicious paths added
Automatic updates for all the software running in the ATM if possible
Up-to-date AV signatures
A proper implementation of hard disk encryption, but it is critical to do it correctly. An incomplete implementation can allow an attack to sniff the Volume keys from TPM to CPU over SPI/I2C bus, among other flaws.
Next-generation centrally managed end-to-end encrypted cameras with tampering detection, motion alerts and facial detection
Periodic ATM Penetration Testing to identify vulnerabilities and countermeasures at Hardware, Middleware, Firmware and Software level
Make sure your provider generates of Indicators of Attack(IOA) and Indicators of Compromise (IOCs) during this exercise to improve the detection and monitoring of these attacks
Set alerts on specific events inside the Journal, AV, EventLog or XFS log to detect and respond to these attacks in a timely manner
Make sure your provider understands the format of the Journal of your ATM and can recommend what type of events to monitor.
Who we are
Ocelot, by Metabase Q, is the leading Offensive Security team in Latin America. This elite team of researchers represents the best of the best, partnered together to transform cybersecurity in the region. Ocelot threat intelligence, research, and offensive skills power Metabase Q’s cybersecurity managed solutions.
Our Advanced ATM Penetration testing covers logic and physical attacks. We test ATMs with customized malware like Ploutus and others, as well as perform multiple physical attacks in the Dispenser, including Endoscope, TPM sniffing, DMA Attacks, TRF, CMOS Shock, etc., to provide a real assessment experience.
Do you know how your systems would perform with ransomware or other advanced attacks? Due to our reverse engineering capabilities, we track and dissect APTs to replicate their TTPs in our customers’ environment. As a result, we are able to simulate advanced attacks and measure your security controls’ effectiveness and investment
Do you have devices? IoT/ICS? We can assess them as well, from Hardware, Boot Loader, Middleware, Firmware all the way to Application level
We wrote the first secure code guideline for BASE24 to find vulnerabilities at the Switch or Bank BASE24/CONNEX to identify payment authorization bypass and PCI violations.
Please reach out at contact@metabaseq.com
Indicators of Compromise:
Paths:
C:\itautec\exe\*
C:\itautec\exe\LibraryLog.txt
c:\Users\<user>\AppData\Roaming\NewLog
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Winlogon\UserInit
Appendix A
Decrypted strings
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