K7 Labs found out from a tweet about a massive phishing campaign going on against Brazil, spreading the malware via WhatsApp web from the victim’s machine to their contacts by using  the open source WhatsApp automation script from Github and also loading a banking trojan into memory.

There were multiple variants of Water-Saci Campaign targeting Brazil using the SorvePotel malware. This variant uses a Python script for malware distribution along with a Banking Trojan.

Figure 1: Kill chain

It starts with a Phishing email with a ZIP archived malicious VBS script file. The script leverages charcode and XOR encoding techniques to evade the Sign based detections.

Figure 2: Char and Xor

After manually deobfuscating it we observed that the script contains 2 functionalities, downloading a MSI file and a VBS file and executing them.

Figure 3: Deobfuscated Vbs

VBS Functionality

The downloaded VBS also has the same charcoding and XOR encoded obfuscation code as mentioned in Figure 2. The script drops a .bat script which downloads and installs Python.zip, ChromeDriver.exe and PIP to download the webdriver from Selenium and executed a Python script whats.py.

Figure 4:  Install Selenium and invokes py

whats.py

This script downloads a payload and sends it to the victim’s WhatsApp contacts using the Selenium Chrome driver. The Selenium Chrome driver is used to inject a malicious JS code in WhatsApp Web. WhatsApp web internal APIs are used with the aid of a helper JS file from Github. A PHP server is used as C2 to collect logs and harvested contacts.

Figure 5: Helper JavaScript and C2

Config

This section defines the configuration for delivering the payload to contacts, including the source location from which the payload is downloaded, the filters applied to the collected contacts, and the batch size for sending to multiple contacts at once. The whats.py script can connect to the C2 server (shown in Fig. 6) to update this configuration file.

Figure 6: Sets up configs

whats.py enumerates common browser locations (Chrome, Firefox, Edge) and inspects standard profile folders (e.g., User Data\Default) for session artifacts – Cookies file, Local Storage entries and IndexedDB files. Artifacts are copied to a temporary folder and Selenium Chromedriver is executed with the temporary path as user-data-dir argument, to launch the browser with the victim’s past whatsapp web session, to avoid the need of QR-scan authentication.

Figure 7: Sets up the user-data-dir

The browser loads WhatsApp Web as a logged-in session using a Selenium feature of executing a script in the webpage context.  The helper JS is used to access the WhatsApp Web internal API calls like WPP.contact.list, WPP.chat.sendTextMessage, WPP.chat.sendFileMessage.

Figure 8: Injection of helper JavaScript in WhatsApp web

Then with an embedded JavaScript inside the python is executed to get the contacts list via in-page APIs(WPP.contact.list()) and then filters the contact configured by the attacker: skip numbers flagged as a groups and businesses and @lid-style IDs and number patterns like 13135 (Figure 6) are applied. Then the harvested contact lists are batched as per the config for delivering the payload.

Figure 9: Fetching contacts

Then it downloads the payload from a configured URL, instead of saving the payload as a file, a Base64-encoded String is stored in a variable which is passed to Whatsapp Web page context via Selenium’s execute_async_script. This transfers the binary data as text to the browser memory without touching the victim’s disk which could cause AV detection.

Figure 10: Downloads and encodes the file

Inside the page, the JavaScript decodes the received encoded string and wraps it in a browser Blob/File-like object (kept in memory). That object is then passed directly to the WhatsApp internal API (e.g., WPP.chat.sendFileMessage) so the attachment is transmitted mimicking the action of the user attaching a file from disk. 

Figure 11: Decodes and makes it a blob

For each validated contact, it sends a greeting message then the payload file and then the final message: (1) sendTextMessage(number, greeting), (2) sendFileMessage(number, inMemoryFile), (3) sendTextMessage(number, closing). It uses createChat:true to ensure that the chat exists and if not then create a new chat to send the messages and payload. Then it returns structured success/failure info for each contact back to the server.

Figure 12: Sending msg and file

All the harvested contacts and successful payload send-result logs are typically POSTed back to the attacker’s PHP server. The outgoing POSTs  include JSON containing contact batches, timestamps, and success/failure flags.

Figure 13: Reports to C2

MSI Part

The MSI drops an AutoIt script, a compressed and encrypted payload in .tda and .dmp file format, a VBS Script, a BAT script and other dependent files. AutoIt Script contains an infinite loop that monitors the active windows and decides when to execute the malicious payload by scanning all visible window title strings, normalizing them, and checking if any window title contains the name of a Brazilian bank, crypto exchange/wallet, or other known finance-related target.


The MSI Executes BAT that executes AutoIt Script.

The script registers dropped VBS under run entry in registry for persistence.

AutoIt script establishes a working directory for the AutoIt in the Windows Registry under HKEY_CURRENT_USER\Software\MyApp\Config: WorkDir and DmpPath. Then it checks for the “executed.dat” file in the WorkDir directory, if not found, It creates and writes the current timestamp into it.

Sending System information to Threat Actor

System information like Computer name, OS info, Username, Local IP, External IP, Current Timestamp, AntiVirus Products, Windows Edition/Version, Processor Name, Total RAM, Logon Domain, Brazilian banking sites visited are sent to the attacker’s server.

The script fetches local IP by using AutoIt’s macro variables and gets the user’s external IP address by creating a WinHttp.WinHttpRequest.5.1 object, sending an HTTP GET request to https://api.ipify.org.

Figure 14: Fetching external IP

Checking for Security Products

The AutoIt script attempts to identify antivirus, firewall, and antispyware software installed on the system by trying three different methods:

It first queries the Windows Management Instrumentation (WMI) SecurityCenter2 to get a list of AntiVirus, Firewall, and AntiSpyware Products installed using AutoIt’s OBJGET() and ExecQuery() Functions and stores it.

If the query returns nothing, it checks the list of running processes against a large array of security software executable names using the PROCESSEXISTS() function from AutoIt.

If it still finds nothing, It looks for program display names that contain keywords of AV program names in the Windows “Uninstall” registry keys.

AVGAviraAvastWindows DefenderMcAfeeESET
BitDefenderNortonSophosKasperskyMalwarebytesF-Secure
WebrootComodoPanda360 Total SecurityZoneAlarm

Table 1: List of targeted security products

Then it gathers additional details about the victim’s computer hardware and operating system like Processor name, Total Physical Memory using WMI and also looks at LOGONDOMAIN.

Figure 15: Fetching system information

It then looks for common security apps used by Brazilian banks by checking if certain folders exist on the C: drive

ScpbradWarsawTopaz OFDSicoobnetAplicativo Itau

Table 2: List of application folders targeted

Then it copies the Chrome browser history to the temp folder and tries to find keywords of Brazilian banks like Santander, Sicredi, etc. and deletes the file from the temp folder once read.

Figure 16: Checks for Banking keywords in browser history

Then it collects all the above stolen information from other functions and sends it to the attacker’s server.

Figure 17: Posting stolen info to server

Loading into memory

The script checks for the most recent SVCHOST’s PID and then fetches the names  of active windows by using AutoIt’s WINLIST() function and then normalizes it to match  with a list of array elements that contains names of bank and crypto wallets.

List of targeted Brazilian banks/Financial institution and Crypto wallets:

Banco do BrasilCaixa Econômica Federal (CAIXA)BradescoItaú / Itaú UnibancoSantanderSicrediSicoob
BMG (Banco BMG)BTG PactualBS2Mercado Pago / Mercado Pago BrasilBinanceCoinbaseKraken
BitstampBitfinexKuCoinHuobiOKXGate.ioBybit
Crypto.comMercado BitcoinFoxbitBitcoinTradeNovaDAXBitPreçoFlowBTC

Table 3: List of targeted Brazilian banks/Financial institutions and Crypto wallets.

If it finds a match, it looks for the .tda file or .dmp (if .tda is not found) in the script directory dropped by MSI earlier. The AutoIt script reads it, decrypts it, decompresses it all in memory.

Figure 18: Looking for .tda/.dmp file

Decryption of payload (.tda or .dmp) works by looping through each byte and using a simple XOR trick to change the values back to normal. After decrypting, it decompresses the payload using Windows built-in function RtlDecompressFragment. it sets up the required memory and workspace for the process, then it returns the decompressed data, a PE in this case which is executed using reflective loading techniques.

Before the AutoIt script does reflective loading, it reads the Optional Header to ensure it’s a 32-bit PE, the original ImageBase, SizeOfImage to see how much virtual memory the whole image needs once mapped, and the AddressOfEntryPoint. The loader then calls VirtualAlloc to reserve and commit a region of memory of size SizeOfImage with PAGE_READWRITE permissions.

Figure 19: Allocates memory

After copying sections, applying relocations, and resolving imports, the loader calls VirtualProtect on the allocated region to change protections to PAGE_EXECUTE_READWRITE. Then it reads the characteristics value in the image’s header and checks if the PE file is a DLL or an EXE. If it is an EXE, it creates a new thread pointing to the entrypoint and if it is a DLL, it creates a DLL call address to the entrypoint (DLLMain).

Figure 20: Creates Thread or Calls DLLMain

The loaded PE then injects itself into SVCHOST and sends info to the attacker’s server using IMAP over TCP connection once AutoIt finds active windows mentioned in Table 3 in a loop. This approach avoids writing  the final payload into the disk, instead the real binary runs purely in memory. 

On inspecting the injected PE we found that it targets a set of  Brazilian banks and crypto wallets.

Figure 21: Banking Trojan
Figure 22: Connects back to server

We’re seeing many similar campaigns active across the cyber landscape. In this particular campaign, the malware spreads through WhatsApp. Because the malicious file is sent by someone already in our contacts, we tend not to verify its authenticity the same way we would if it came from an unknown sender. This trust in familiar contacts reduces our caution and increases the chances of the malware being opened and executed. So, we recommend using a reliable product like K7, which will protect you from these ongoing campaigns and safeguard both your information and resources from potential security threats

IOCs

File NameHashDetection Name
58e_577c10-3fd3751b-58e.vbsF8DC59AF96E73F14FEFBC34840096153Trojan ( 005d22581 )
Installer.msiDB0EAB25B047F82A4644B3B86767A1AATrojan ( 0001140e1 )
mDjEvbze.log (AU3)CE45C057113BA1CA6F1D7AE7E2004AFBTrojan ( 0001140e1 )
NsmKL5.tda5BCB9F187320893D1B1C36FA0C18E094Trojan ( 0001140e1 )
95p1jx.dmp8DBF440436EB57F38827351DDD05911ATrojan ( 0001140e1 )
Installer.VBSFB6A29742389AF2A0CB2AD114442D0FBTrojan ( 005d22581 )
instalar.bat6F1B82B320FEDA1F719C3028DA73E843Trojan ( 0001140e1 )
whats.py45027D8EA53921B59C70C38D90DD8C14Trojan ( 0001140e1 )

C2s

hxxps[:]//varegjopeaks.com/altor/receptor.php

vip-imap-az.terra[.]com[.]br

Like what you're reading? Subscribe to our top stories.

If you want to subscribe to our monthly newsletter, please submit the form below.

    0 replies on “Brazilian Campaign: Spreading the Malware via WhatsApp”