[RE021] Qakbot analysis – Dangerous malware has been around for more than a decade


1. Overview

QakBot (also known as QBot, QuakBot, Pinkslipbot) is one of the famous Banking Trojan with the main task to steal banking credentials, online banking session information, or any other banking data. Although detected by anti-virus software vendors since 2008, but util now it’s still operating and keep continuously maintained by the gangs behind it. Qakbot continuously evolves by applying advance or new techniques to evade detection and avoid reverse analysis, making analysis more difficult. In recent reports, it could be used to drop other malware such as ProLock, Egregor ransomware.

Source: CrowdStrike 2021 Global Threat Report
Qakbot can be distributed via Emotet, however Emotet has been taken down recently, currently this malware uses email spam and phishing campaigns as main method. Unlike Emotet that uses MS-Word in conjunction with VBA to download malicious payload, Qakbot uses MS-Excel with the support of Excel 4.0 Macro (XLM macro) to download and execute malicious payload on the victim's computer.

In this article, we will analyze how QakBot infects after launched by malicious Excel document, the techniques used to make the analysis difficult, and how to extract the C2 list. QakBot’s persistence can not be detected at runtime, the run key only created before system shutdown or enter suspended state, and deleted immediately after QakBot is executed again. Qakbot also applied encryption techniques to conceal information, as well as encrypt the payload on memory.

Hashes used in this post:

2. Document template and XLM macro

Qakbot templates are constantly changing depending on the campaign, the final target of attackers for leveraging templates to trick the victims into enabling macros to start the infection. This type of maldocs will usually have a cell is “Auto_Open cell”, its functionality which is similar to the “Sub AutoOpen()” function in VBA to automatically run macros when victim press “Enable Content” button.

As already mentioned, these templates use Excel 4.0 macros (predate VBA macros), they are composed of functions placed inside cells of a macro sheet. To analyze this form of macro can use following tools:

2.1. XLMMacroDeobfuscator

This tool allows to extract the cells’s content, shows which macro sheet has cell is “Auto_Open cell”, and utilizes an internal XLM emulator to interpret the macros, without fully performing the code.

However, cause macros in maldocs usually implement obfuscation techniques, so that the emulate function of the tool does not always work well:

2.2. Cerbero Suite

Cerbero Suite is developed by Erik Pistelli. The latest version added support for the XLSB format, so that now it can decompiles both XLS and XLSB formulas and also support previews spreadsheets same as opening in Microsoft Excel. Furthermore, it also provides the ability to emulate Microsoft Excel formulas. During the discussion with the author, I and my friend have commented and provided samples to him for improving the functionality of the product.

Like XLMMacroDeobfuscator, when analyzing maldoc, this tool also shows the starting point of execution (entry point) is the cell containing Auto_Open.

With the help of emulate feature, we can spot that the maldoc registered an API is URLDownloadToFileA , then use this function for downloading payloads from multiple addresses:

If successfully download one of the above payloads, it will use rundll32.exe to execute:

2.3. Microsoft Excel

The above mentioned tools based on xlrd2, pyxlsb2 and its own parser to extract cells and other information from xls, xlsb and xlsm files. Therefore, in case these tools cannot satisfied, using Microsoft Excel is still the best option.

When analyzing with MS Excel, navigate to the cell containing Auto_Open, select the Macros feature and click Step Into to open the Single Step window:

By using Step Into or Evaluate to trace each cell in the same column and display the value of each Formula, we get the following information:

To sum up, when Qakbot maldoc executes its macro code, it will download payload to victim’s computer and run this payload by using rundll32.exe.

3. Loader payload

3.1. Basic analysis

As analyzed above, the downloaded payload is a DLL. This DLL exports 4 functions, one of which is DllRegisterServer function is called by the command rundll32:

Based on the imported APIs list, we can predictable that it will use it to unpack another payload:

This DLL is digitally signed to avoid detection by anti-virus software and other detection systems:

3.2. Technical analysis

This DLL when executed will allocate and unpack the main payload to the allocated memory and execute this payload:

Dump payload from memory to disk for later analysis. Dumped payload is also a DLL, was built with Microsoft Visual C++, original name is stager_1.dll and exports only one function is DllRegisterServer:

To make sure the dumped payload is correct, usually in the resource section of this payload must has resource names are "308" and "311".

4. Some techniques used in the main payload

4.1. Junk code

A well-known technique that's used in many samples, is junk code insertion. With this technique, the malware inserts lots of code that never gets executed, a call that never returns, or conditional jumps with conditions that would never be met. The main goal of this code is to make the code graph look more complicated than it actually is and to waste the reverse engineer's time analyzing.

With Qakbot's payload, the malware author inserts useless API calls alternating between real instructions, in addition to the time-consuming goal, it can cause disturbing information when executing in the sandbox environment or via applications that log windows APIs call.

4.2 Use non-standard calling convention

The common standard calling conventions when analyzing malware are cdecl, stdcall, thiscall or fastcall. Howerver, to complicate the analysis task, Qakbot added non-standard calling convention that making it difficult to recognize the parameters passed to the function as well as Hexrays when decompiles will fail.

For example, the following function takes 3 parameters, in which the first and third parameters are pushed onto the stack, and the second parameter is assigned to eax. At this point, Hexrays will miss the parameter when decompile code:

IDA supports the user-defined calling convention, read this article. With the above case, we can redefine function prototype as follows: int __usercall sub_100184FE@<eax>(int arg1, int arg2@<eax>, int arg3). Result:

Another example, the function below takes an parameter and this parameter is assigned to the eax register. Incorrect recognition lead to Hexrays decompiles missing a parameter:

To help Hexrays decompiles correctly, we can explicitly specify the locations of arguments and the return value like this: int *__usercall sub_10017EC5@<eax>(unsigned int arg1@<eax>). And here is the result:

4.3. Decrypt strings

Like Emotet, all strings are encrypted and decrypted at runtime into memory only and destroyed right afterwards. Most of QakBot strings are encrypted and stored in a continuous blob. The decryption function accepts one argument which is the index to the string, then it xors it with a hardcoded bytes array. During the analysis this payload, we found 02 byte arrays which containing the value of the original string already encrypted:

Corresponding to each above array will have a byte array containing the values used for xor to decode to get the real strings:

As mentioned, The decryption function accepts one argument which is the index to the string. Inside this function will call the main routine to decrypt the string that malware need to use:

The f_decrypt_string in the figure does the following:

  • Based on the index value passed to the function, computes the length of the string to be decryped.
  • Allocates memory to store the decrypted string.
  • Through the loop to xor with bytes of xor_bytes_arr array to retrieve the original string.

By using IDAPython, we can rewrite the code to decrypt the strings and add them as comments:

The results before and after the script execution will make the analysis easier:

Do the same with other decryption functions. However, the strings shown in the above picture are the results obtained after decrypting pre-assigned indexes in Qakbot's code. The rest of strings indexes are calculated dynamically at runtime. For example the following code snippet:

Therefore, to get the entire decrypted strings along with associated index, use the following code:

Please see the Appendix 1 – Complete list of decrypted strings below.

4.4. Dynamic APIs resolve

Based on the results decrypted strings, get a list of major DLLs that Qakbot will uses to obtain the necessary API functions:

Payload will find the address of the API functions through lookup a pre-computed hash based on the API function name. For each above DLLs will have an array that stored pre-computed hashes. Below is an illustration of an array that stores pre-computed hashes of API functions belong to kernel32.dll. (This array will then be overwritten by the real address of the corresponding API):

For calculating hashes, the payload uses an additional table containing the values used for xor at address 0x1002B6F8 (g_xor_key_tbl). The search algorithm used by Qakbot as follows:

Rewrite the hash function, combine with IDAPython to retrieve a list of APIs and generate a corresponding enum list for the calculated hashes:

And here is the result:

From this result, create a corresponding struct and apply this struct in the relevant code, we will recover the call to the API functions. That’s much easier to work with:

4.5. Check protection solutions on victim machine

Qakbot create a list of processes related to endpoint protection solutions including the fields: group_id, group_index. Use the loop for decrypting the corresponding strings to get a list of the process names:



process name

















































After that, payload uses the functions CreateToolhelp32Snapshot; Process32First; Process32Next to enumerate all the processes running on the victim machine, check the name of the process is in the above list. If has:

  • Processes belong to the same list, return the corresponding group_id. For example: if has avp.exe;kavtray.exe will return 0x10.
  • Processes belong to different lists, the result is or of the corresponding group_id. For example, if hash avp.exe;kavtray.exe and AvastSvc.exe then the result is 0x10 | 0x80 = 0x90.
This result will affect to the flow of process injection. For example, if the victim machine uses Kaspersky protection (has avp.exe process), Qakbot will inject code into mobsync.exe instead of explorer.exe.

4.6. Anti-sandbox

4.6.1. Checking file name

Payload checks whether its name is in the blacklist including: artifact.exe;mlwr_smpl;sample;sandbox;cuckoo-;virus. Some sandboxes may change the sample file name.

4.6.2 . Checking processes

Payload checks whether the running processes are in the blacklist, including: srvpost.exe;frida-winjector-helper-32.exe;frida-winjector-helper-64.exe.

4.6.3. Checking Device

Payload uses API functions SetupDiGetClassDevsA, SetupDiEnumDeviceInfo, SetupDiGetDeviceRegistryPropertyA of setupapi.dll to get information about the device on the system, and then check with the blacklist included: A3E64E55_pr;VboxVideo;Red Hat VirtIO;QEMU.

4.6.4. Checking hostname and account

Payload check whether the hostname and logon account in the blacklist list: VIRTUAL-PC and Virtual.

If it detects any of those, the execution flow will run into an infinite loop:

4.7. Configuration info and List of C2 (IP & Port)

As mentioned above, the payload if dumped correctly will have resource names: "308" and "311". Based on the decrypted strings, we can find the code related to these strings:

4.7.1. Decrypt configuration info

Qakbot's configuration is stored in resource 308, the code related to this resource will do:

  • Call decrypt function with index value 0x3F5 to retrieve the string 308”.
  • Use API functions of kernel32 are FindResourceA; SizeofResource; LoadResource to load the data stored in this resource into the allocated memory.
  • Call the function to decrypt the data.

Payload will re-check the size of the resource and call f_decrypt_res_data_by_using_RC4 function to decrypt:

According to the pseudocode, the whole decrypting process as follows:

  • The first 20 bytes of data are the RC4 key, and the rest are the actual encrypted data need to be decrypt.
  • Use RC4 algorithm with the obtained key to decrypt the data. The data after decrypted includes:
    • The first 20 bytes of the decrypted data will contain the SHA1 hash calculated over the rest of the decrypted data.
    • Decrypted data is the rest of data after subtracting 20 bytes of SHA1.
  • SHA1 is used as a verification for correct decryption.

The entire process above is illustrated as picture below:

The contents of the decrypted resource “308” are:

  • 10=biden02 --> CampaignID
  • 3=1614154620   --> Unix Timestamp (Wed 24 February 2021 08:17:00 UTC)

4.7.2. C2s list (IP & Port)

So by using this method, we can decrypt the other resource "311":

We obtained a list of IP addresses and ports separated by the value 01:

Please see Appendix 2 – C2s list below for the complete list.

4.8. Process Injection

Qakbot select which process to inject its unpacked code based on the operating system environment and group_id information related to the protection solutions that mentioned above.


  • It uses CreateProcessW starts a new suspended process. But for simplicity we will only follow the explorer.exe process injection path.
  • Create a new memory region on the explorer.exe process with RWX protection by using the NtCreateSection, NtMapViewOfSection APIs.
  • Copy the entire Qakbot payload to the memory created above.

Use the GetThreadContext, NtProtectVirtualMemory, NtWriteVirtualMemory functions to overwrite the explorer.exe’s entry point with a jump instruction to the function address of the Qakbot payload:

Finally, it resume execution with ResumeThread. At this time, explorer.exe will execute from its entry point, and execute the jump to the function address of the Qakbot payload:

4.9. Overwrite payload and encrypt payload on memory

To make difficult for people who perform incident response, Qakbot does overwrite null bytes on the payload itself on disk (but keep DOS_HEADER, NT_HEADERS, SECTION_HEADER) and at the same time, it also encrypts all payloads to store on memory for implementing persistence technique. This ensures that all Qakbot's main code will be executed from the injected process as explorer.exe or mobsync.exe.

4.10. Persistence operation

4.10.1. Run key persistence

Creating persistence made after process injection step. At this point, Qakbot will create a thread that performs the task:

  • Call RegisterClassExA to create a window with random class name.
  • Setup a callback function f_process_wnd_message for processing windows messages.

Windows messages are processed into f_process_wnd_message as follows:

  • When receive system shutdown message (WM_QUERYENDSESSION) or power-management broadcast message (WM_POWERBROADCAST) that along with event notify the computer enter suspended state (PBT_APMSUSPEND), call f_install_persistence().
  • When receive power-management broadcast message (WM_POWERBROADCAST) that along with events notify the computer enter resume state (PBT_APMRESUMESUSPEND || PBT_APMRESUMEAUTOMATIC), call f_uninstall_prev_persistence().

  • f_install_persistence() perfoms the following tasks:
    • Decrypt previously encrypted payloads using RC4 into memory.
    • Setup command for execute payload: regsvr32.exe -s <Qakbot_module_path>.
    • Create a registry value name which is random alphabet characters at registry key HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run for saving above command.

  • f_uninstall_prev_persistence() perfoms the opposite tasks:
    • Delete previous created persistence key.
    • Delete payload on disk.

By this way, QakBot’s persistence can not be detected at runtime.

4.10.2. Fake scheduled task persistence

In addition to creating the run key persistence as above, Qakbot also creates a fake persistence which is scheduled tasks to deceive us. Task is created with a random name through the following command: "%s\system32\schtasks.exe" /Create /RU "NT AUTHORITY\SYSTEM" /tn %s /tr "%s" /SC ONCE /Z /ST %02u:%02u /ET %02u:%02u

For example: "C:\Windows\system32\schtasks.exe" /Create /RU "NT AUTHORITY\SYSTEM" /tn gyfzcixqb /tr "regsvr32.exe -s \"C:\Users\REM\Desktop\Qakbot_DLL_unpacked.bin\"" /SC ONCE /Z /ST 12:39 /ET 12:51

However, at this time the payload on the disk has been erased data, only keep information of DOS_HEADER, NT_HEADERS, SECTION_HEADER.

4.11. C2 Communication

To making difficulties for the analyst as well as protection systems, Qakbot will encrypt its POST request before communicate with C2 server. A Qakbot's POST request will usually look like this:

Before encrypted, POST request looks like this:

This POST request will be encrypted and then sent to the C2 server:

In the above pseudocode:

  • f_encrypt_POST_request_by_RC4 performs:
    • Creates an rc4_key with 16 bytes long.
    • This rc4_key will be concatenated with the decrypted string is “jHxastDcds)oMc=jvh7wdUhxcsdt2”. Then use SHA1 to take this data and produce hash value.
    • Use calculated hash as an rc4_key for encrypting POST request.
    • The result is a memory area of the first 16 bytes of rc4_key and the POST request is encrypted.

  • f_base64_transform will perform encode the entire memory containing rc4_key and ecnryted POST request in base64 format.
  • Finally, call f_send_POST_request_to_C2 to send this POST request to C2.

Based on the entire process above, here is an implementation of the decryption algorithm:

5. Conclusion

After more than a decade, Qakbot still exists, evolve and always is a permanent threat for large organizations today. The use of the XLSB documents leads to lower detection rates by security solutions, which are mostly focused on the more common modern VBA macro malware. In addition, QakBot’s payloads also employs a robust set of anti-analysis features, advanced techniques to evade detection and frustrate analysis. The gangs behind Qakbot are also active in adding more sophisticated techniques for further development and feature expansion. So far, the identities of people behind Qbot are unknown. Hopefully, in the near future, Qakbot will be taken down similar to Emotet.

6. References

7. Appendix 1 – Complete list of decrypted strings

index boundary: 0xB10

index: 0x0, decrypted string: tcpdump.exe;windump.exe;ethereal.exe;wireshark.exe;ettercap.exe;rtsniff.exe;packetcapture.exe;capturenet.exe

index: 0x6d, decrypted string: %SystemRoot%\SysWOW64\explorer.exe

index: 0x90, decrypted string: SAVAdminService.exe;SavService.exe

index: 0xb3, decrypted string: user32.dll

index: 0xbe, decrypted string: mpr.dll

index: 0xc6, decrypted string: Mozilla/5.0 (Windows NT 6.1; rv:77.0) Gecko/20100101 Firefox/77.0

index: 0x108, decrypted string: advapi32.dll

index: 0x115, decrypted string: %SystemRoot%\System32\mobsync.exe

index: 0x137, decrypted string: ntdll.dll

index: 0x141, decrypted string: bdagent.exe;vsserv.exe;vsservppl.exe

index: 0x166, decrypted string: Initializing database...

index: 0x17f, decrypted string: %SystemRoot%\SysWOW64\mobsync.exe

index: 0x1a1, decrypted string: .cfg

index: 0x1a6, decrypted string: mcshield.exe

index: 0x1b3, decrypted string: coreServiceShell.exe;PccNTMon.exe;NTRTScan.exe

index: 0x1e2, decrypted string: shell32.dll

index: 0x1ee, decrypted string: image/jpeg

index: 0x1f9, decrypted string: image/gif

index: 0x203, decrypted string: C:\INTERNAL\__empty

index: 0x217, decrypted string: %SystemRoot%\SysWOW64\xwizard.exe

index: 0x239, decrypted string: t=%s time=[%02d:%02d:%02d-%02d/%02d/%d]

index: 0x261, decrypted string: abcdefghijklmnopqrstuvwxyz

index: 0x27c, decrypted string: SOFTWARE\Wow6432Node\Microsoft AntiMalware\SpyNet

index: 0x2ae, decrypted string: \sf2.dll

index: 0x2b7, decrypted string: Content-Type: application/x-www-form-urlencoded

index: 0x2e7, decrypted string: MsMpEng.exe

index: 0x2f3, decrypted string: %SystemRoot%\SysWOW64\explorer.exe

index: 0x316, decrypted string: image/pjpeg

index: 0x322, decrypted string: SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths

index: 0x357, decrypted string: %SystemRoot%\System32\xwizard.exe

index: 0x379, decrypted string: Software\Microsoft

index: 0x38c, decrypted string: cscript.exe

index: 0x398, decrypted string: egui.exe;ekrn.exe

index: 0x3aa, decrypted string: SOFTWARE\Wow6432Node\Microsoft\Windows Defender\Spynet

index: 0x3e1, decrypted string: WScript.Sleep %u

Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\.\%coot\cimv2")

Set objProcess = GetObject("winmgmts:root\cimv2:Win32_Process")

errReturn = objProcess.Create("%s", null, nul, nul)

WSCript.Sleep 2000

Set fso = CreateObject("Scripting.FileSystemObject")


index: 0x523, decrypted string: fshoster32.exe

index: 0x532, decrypted string: ALLUSERSPROFILE

index: 0x542, decrypted string: kernel32.dll

index: 0x54f, decrypted string: application/x-shockwave-flash

index: 0x56d, decrypted string: Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\.\%coot\cimv2")

Set objProcess = GetObject("winmgmts:root\cimv2:Win32_Process")

errReturn = objProcess.Create("%s", null, nul, nul)

index: 0x641, decrypted string: %SystemRoot%\explorer.exe

index: 0x65b, decrypted string: c:\\

index: 0x660, decrypted string: ccSvcHst.exe

index: 0x66d, decrypted string: %ProgramFiles(x86)%\Internet Explorer\iexplore.exe

index: 0x6a0, decrypted string: netapi32.dll

index: 0x6ad, decrypted string: avp.exe;kavtray.exe

index: 0x6c1, decrypted string: crypt32.dll

index: 0x6cd, decrypted string: shlwapi.dll

index: 0x6d9, decrypted string: snxhk_border_mywnd

index: 0x6ec, decrypted string: SOFTWARE\Microsoft\Microsoft AntiMalware\SpyNet

index: 0x71c, decrypted string: wpcap.dll

index: 0x726, decrypted string: MBAMService.exe;mbamgui.exe

index: 0x742, decrypted string: \\.\pipe\

index: 0x74c, decrypted string: .dll

index: 0x751, decrypted string: SOFTWARE\Microsoft\Windows Defender\SpyNet

index: 0x77c, decrypted string: WRSA.exe

index: 0x785, decrypted string: reg.exe ADD "HKLM\%s" /f /t %s /v "%s" /d "%s"

index: 0x7b4, decrypted string: 1234567890

index: 0x7bf, decrypted string: wmic process call create 'expand "%S" "%S"'

index: 0x7ec, decrypted string: wtsapi32.dll

index: 0x7f9, decrypted string: ByteFence.exe

index: 0x807, decrypted string: SubmitSamplesConsent

index: 0x81c, decrypted string: {%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}

index: 0x863, decrypted string: NTUSER.DAT

index: 0x86e, decrypted string: .dat

index: 0x873, decrypted string: cmd.exe

index: 0x87b, decrypted string: .exe

index: 0x880, decrypted string: %s\system32\

index: 0x88d, decrypted string: ws2_32.dll

index: 0x898, decrypted string: %ProgramFiles%\Internet Explorer\iexplore.exe

index: 0x8c6, decrypted string: avgcsrvx.exe;avgsvcx.exe;avgcsrva.exe

index: 0x8ec, decrypted string: */*

index: 0x8f0, decrypted string: vkise.exe;isesrv.exe;cmdagent.exe

index: 0x912, decrypted string: AvastSvc.exe

index: 0x91f, decrypted string: c:\hiberfil.sysss

index: 0x931, decrypted string: wininet.dll

index: 0x93d, decrypted string: %SystemRoot%\explorer.exe

index: 0x957, decrypted string: Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\.\%coot\cimv2")

Set colFiles = objWMIService.ExecQuery("Select * From CIM_DataFile Where Name = '%s'")

For Each objFile in colFiles



index: 0xa43, decrypted string: aabcdeefghiijklmnoopqrstuuvwxyyz

index: 0xa64, decrypted string: urlmon.dll

index: 0xa6f, decrypted string: SpyNetReporting

index: 0xa7f, decrypted string: setupapi.dll

index: 0xa8c, decrypted string: aaebcdeeifghiiojklmnooupqrstuuyvwxyyaz

index: 0xab3, decrypted string: SOFTWARE\Microsoft\Microsoft Antimalware\Exclusions\Paths

index: 0xaed, decrypted string: aswhookx.dll

index: 0xafa, decrypted string: fmon.exe

index: 0xb03, decrypted string: aswhooka.dll

index boundary: 0x435

index: 0x0, decrypted string: \System32\WindowsPowerShell\v1.0\powershell.exe

index: 0x30, decrypted string: srvpost.exe;frida-winjector-helper-32.exe;frida-winjector-helper-64.exe

index: 0x78, decrypted string: powershell.exe

index: 0x87, decrypted string: /t4

index: 0x8b, decrypted string: %s \"$%s = \\\"%s\\\\; & $%s\"

index: 0xaa, decrypted string: SOFTWARE\Microsoft\Windows\CurrentVersion\Run

index: 0xd8, decrypted string: A3E64E55_pr;VBoxVideo

index: 0xee, decrypted string: .lnk

index: 0xf3, decrypted string: at.exe %u:%u "%s" /I

index: 0x108, decrypted string: Red Hat VirtIO;QEMU

index: 0x11c, decrypted string: net view /all

index: 0x12a, decrypted string: nslookup -querytype=ALL -timeout=10 _ldap._tcp.dc._msdcs.%s

index: 0x166, decrypted string: ipconfig /all

index: 0x174, decrypted string: SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList

index: 0x1ad, decrypted string: regsvr32.exe -s

index: 0x1be, decrypted string: %s "$%s = \"%s\"; & $%s"

index: 0x1d7, decrypted string: Microsoft

index: 0x1e1, decrypted string: Self test FAILED!!!

index: 0x1f5, decrypted string: 311

index: 0x1f9, decrypted string: %s %04x.%u %04x.%u res: %s seh_test: %u consts_test: %d vmdetected: %d createprocess: %d

index: 0x252, decrypted string: whoami /all

index: 0x25e, decrypted string: cmd /c set

index: 0x269, decrypted string: qwinsta

index: 0x271, decrypted string: arp -a

index: 0x278, decrypted string: nltest /domain_trusts /all_trusts

index: 0x29a, decrypted string: route print

index: 0x2a6, decrypted string: "%s\system32\schtasks.exe" /Create /RU "NT AUTHORITY\SYSTEM" /tn %s /tr "%s" /SC ONCE /Z /ST %02u:%02u /ET %02u:%02u

index: 0x31b, decrypted string: VIRTUAL-PC

index: 0x326, decrypted string:  /c ping.exe -n 6 &  type "%s\System32\calc.exe" > "%s"

index: 0x368, decrypted string: error res='%s' err=%d len=%u

index: 0x385, decrypted string: net share

index: 0x38f, decrypted string: Virtual

index: 0x397, decrypted string: net localgroup

index: 0x3a6, decrypted string: artifact.exe;mlwr_smpl;sample;sandbox;cuckoo-;virus

index: 0x3da, decrypted string: Self test OK.

index: 0x3e8, decrypted string: netstat -nao

index: 0x3f5, decrypted string: 308

index: 0x3f9, decrypted string: ProfileImagePath

index: 0x40a, decrypted string: amstream.dll

index: 0x417, decrypted string: jHxastDcds)oMc=jvh7wdUhxcsdt2

8. Appendix 2 – C2s list

QakBot C2 List

Click here for Vietnamese version.

Tran Trung Kien (aka m4n0w4r) 

Malware Analysis Expert


R&D Center - VinCSS (a member of Vingroup)


  1. Replies
    1. So sorry, right now I can not share my IDB!


    2. I understand and it is completely ok and up to you of course. It’s just because I’ve tried using the various public python scripts to resolve the APIs, as I can’t really analyze this malware without knowing which APIs it calls :/

      If it’s not too much to ask, would you spend a few minutes applying these scripts on a sample and then share the resulting IDB with me? Or at least just tell me how I execute the python functions with the correct parameters?


      Python scripts:


      Thank you so much in advance if you’d help me out with this!

    3. OK, I will try to take a look at this sample and hope can help you. Can you drop your email or twitter account, I will ping you back!


    4. Thank you very much!

      E-mail is phpnull at h0tmail.com

    5. @Chatrt.dk: Check your email! Hope this help!