Hatching logo

Reversing Qakbot

  • 2019-11-12
  • Markel Picado (d00rt)

Summary

Qbot or Qakbot is a sophisticated worm with banking capabilities. This malware family has been infecting computers since 2009, utilizing a number of techniques (some of them quite advanced) which make it difficult to detect. It has a packing layer, anti-VM techniques, anti-debug techniques, and anti-sandbox techniques which make the analysis of this threat difficult. Qakbot is capable of updating itself and this also makes this threat more complex to detect since it is constantly changing on disk.

Using Triage we analyzed the most recent variant of this malware, and we added a new module to support the detection and configuration extraction of Qakbot samples as shown in the image below. A tool to deobfuscate the Qakbot payload is also included (qakbuscator.py).

/static/images/blog/reversing-qakbot/reversing-qakbot-16.png

Qakbot family detection in Hatching Triage

/static/images/blog/reversing-qakbot/reversing-qakbot-24.png

Qakbot config extraction Hatching Triage

Unpacking process

Qakbot has a custom packer. There are probably other versions of Qakbot in the wild with different packers, but this section is based on analysis of the packer for the sample: e736cf964b998e582fd2c191a0c9865814b632a315435f80798dd2a239a5e5f5.

In summary, the unpacking process is as follows:

/static/images/blog/reversing-qakbot/reversing-qakbot-15.png

The unpacking process

The packer allocates memory and then drops an encrypted buffer there (Step 1-2).

The dropped buffer is decrypted and the decrypted data contains a PE file (Step 3). This PE file is not at the beginning of the buffer but starts at offset 0x427. From the beginning to the PE file offset is filled with 0x00 bytes.

/static/images/blog/reversing-qakbot/reversing-qakbot-12.png

Offset is filled with ``0x00`` bytes

This could be a trick to make analysts think that this function is “freeing memory” or that it’s a memset-like function.

The PE header is modified - this can also confuse analysts or memory dumping tools that look for PE file signatures since they can’t find the “MZ” magic number. This is shown in the image below.

/static/images/blog/reversing-qakbot/reversing-qakbot-21.png

Modified PE header

The decrypted PE file image size is calculated to allocate memory for it. The PE file is copied (mapped as a windows loader would do) from the decrypted buffer to the newly allocated memory (Step 3-4).

/static/images/blog/reversing-qakbot/reversing-qakbot-6.png

The PE is copied over

/static/images/blog/reversing-qakbot/reversing-qakbot-9.png

Mapping file to Allocated Memory

Once the file is mapped to the newly allocated memory, the header is fixed as shown in the following image. Once the PE file is mapped its entry point is called. (Step 4)

/static/images/blog/reversing-qakbot/reversing-qakbot-3.png

Calling the entry point

This PE is going to read the rest of the previous decrypted buffer since there is still some encrypted data. Once the data is decrypted a new PE file can be found. (Step 4-5)

/static/images/blog/reversing-qakbot/reversing-qakbot-5.png

The new PE file

This time the header is also modified and is fixed before mapping it. (Step 5-6)

/static/images/blog/reversing-qakbot/reversing-qakbot-22.png

New PE file with new header

The decrypted PE is Qakbot itself. In this case the PE header doesn’t have the well-known string “This program cannot be run in DOS mode”, because the DOS-Stub was deleted.

This PE file is the final payload of Qakbot so finally the PE file is mapped to the ImageBaseAddress of the original file (Step 6).

The original image loaded at address 0x400000 is wiped.

/static/images/blog/reversing-qakbot/reversing-qakbot-1.png

The address 0x400000 is wiped

The newly unpacked PE (Qakbot) is copied to the original image base address 0x400000.

/static/images/blog/reversing-qakbot/reversing-qakbot-13.png

Qakbot copied over to 0x400000

So, after mapping the Qakbot binary the execution flow goes to the EntryPoint of this file. (Step 7).

The unpacked sample hash of the file we ran in Triage: 850ff92b7f3badda4bd4eca0a54fbdea410667db1ea27db8069337bf451078d1

/static/images/blog/reversing-qakbot/reversing-qakbot-10.png

Overview

Obfuscation

Once the sample is unpacked, Qakbot itself also implements an obfuscation layer in its code. This obfuscation makes the analysis a bit harder. The flow graph of the main function is the following:

/static/images/blog/reversing-qakbot/reversing-qakbot-18.png

Qakbot's obfuscation

The obfuscation basically consists of adding unused loops with an empty body. Like the following:

/static/images/blog/reversing-qakbot/reversing-qakbot-20.png

Unused loops

As is shown in the image above, it does a "XOR EAX, EAX" operation and then decides to loop or not depending on the Z flag which is set with the previous instruction (so the loop will never happen). The goal of these small loops is to make a less comprehensive flow graph and to make the analysis harder. There are more than 600 loops like this throughout the code.

At Hatching, we implemented a tool (qakbuscator.py) to deobfuscate the code and make the analysis much easier. This tool is provided with this analysis to allow all researchers to use it.

/static/images/blog/reversing-qakbot/reversing-qakbot-11.png

Qakbot's deobfuscated

The DLLs that are in the Qakbot resources also have this obfuscation layer - you can use the script to deobfuscate them.

Behavioral analysis

The sample used to perform the behavioral analysis is the deobfuscated sample using our deobfuscator tool explained in the previous section.

SAMPLE: 3bd468d29868bb3f198530ef2426668efe30a8330bf3835a4f3a941d534ef2df

This is how a process tree of a Qakbot infection looks like:

/static/images/blog/reversing-qakbot/reversing-qakbot-19.png

Process tree after Qakbot infection

Regardless of the input vector, the first time Qakbot runs it tries to install itself.

Anti-VM/Anti-analysis tricks

First of all, it checks if it is running in a virtualized environment or not. Qakbot executes itself with the option "/C". Qakbot admits parameters, in this case the parameter "/C" is to make anti-VM and anti-sandbox checks like the following ones:

Reading from the virtual port in order to detect VMWare

/static/images/blog/reversing-qakbot/reversing-qakbot-17.png

VMWare detection

Check the CPUID

/static/images/blog/reversing-qakbot/reversing-qakbot-23.png

CPUID check

There are also other techniques used by Qakbot to know if it is running in an emulated environment like checking the sample name - in order to see if it is set to some default name like “sample.exe” or “malware.exe”; or checking running processes in order to detect any related to a virtual environments, anti-virus, debuggers etc.

Among the different options that Qakbot accepts we can find the following:

Accepted parameters Description
/C Anti-VM checks
/I [name] Disable Windows SpyNey and delete scheduled task [name]
/P[file] Decrypt [file] and load it
/Q Set exit status to 0x6F
/T Sync related stuff
/V Debug/Testing option
/W Debug/Testing option
/i [name] Install itself and delete scheduled task [name]
/s Create service
/t Send Window Message
/A [1] [2] Unknown

Installation

If a VM is detected it exits. Otherwise, it copies itself into %APPDATA% under a randomly generated folder with a randomly generated name. Those names are unique for each infected machine since they are created using some characteristics from infected host.

/static/images/blog/reversing-qakbot/reversing-qakbot-2.png

Copying to %APPDATA%

It also creates the following registry key in order to be run when the system reboots “HKCUSoftwareMicrosoftWindowsCurrentVersionRun”.

/static/images/blog/reversing-qakbot/reversing-qakbot-8.png

Run on system boot

Also, it drops a .dat file that has configuration information, like botnet name, timestamp, etc. This file contains encrypted data which is decrypted in memory during run time. Once this file is decrypted it looks like is shown in the image below.

/static/images/blog/reversing-qakbot/reversing-qakbot-7.png

Decrypted file

The following table, from a blog post by the security researcher Vitaly Kremez (link) , shows the meanings of some of these config values:

Qakbot Config
11 = 2 (number of hardcoded C2)
1 = date of qbot install in HH:MM:ss-dd/mm/yyyy
2 = victim qbot install
45 = C2 IP
46 = C2 Port
39 = victim external IP
38 = last victim call to C2 (time in Unix)
43 = time of record ((time in Unix)
5 = victim network shares

Finally, the copied file is executed and the original file is overwritten with calc.exe. Some malware deletes the file directly, but Qakbot has decided to overwrite it with a legitimate binary. This way it doesn't leave traces.

/static/images/blog/reversing-qakbot/reversing-qakbot-4.png

Overwriting with legitimate binary

When Qakbot is installed, its behavior is different. In this case, it is going to create an instance of the explorer.exe process in order to inject itself into it.

Once injected into explorer, the main .dll is loaded. At this point, different things could happen since the communication with the control panel begins. As shown in the process tree above, the explorer process executes an update of Qakbot directly downloaded from the C&C. Also, it can exfiltrate data, or infect browsers in order to get banking information from the victim system.

Qakbot update sample: https://tria.ge/reports/191104-athqk1tjxn/task2

Triage

In Triage we’ve just added support for this family, meaning you can detect Qakbot as well as get its configuration directly after the analysis.

/static/images/blog/reversing-qakbot/reversing-qakbot-14.png

Qakbot in Triage

Samples

The Triage report for the sample that was used for this blog can be found here.

Sample state SHA256
Packed Qakbot e736cf964b998e582fd2c191a0c9865814b632a315435f80798dd2a239a5e5f5
Qakbot 850ff92b7f3badda4bd4eca0a54fbdea410667db1ea27db8069337bf451078d1
Deobfuscated Qakbot 3bd468d29868bb3f198530ef2426668efe30a8330bf3835a4f3a941d534ef2df
Qakbot resource 1 (main.dll) 83273809a35ba26c2fb30cba58ba437004483ae754babad63c5d168113efa430
Deobfuscated Qakbot resource 1 (main.dll) 74f8907acfd070d2590895523433a8c85b5ef87f4e1a5ef7ccd356f5562b7a6b
Qakbot resource 2 (injects dll x86) b7d9a462bd105193e998b6324f3343b84f11ceb21ab24e60e2580a26d95e4494
Qakbot resource 3 (injects dll x64) 8c7a43002ee6105fc37fcdfc00a192239639f7c08bf28e06ca1432551fe21b3f

Here is a list of related samples and their corresponding Triage reports.

SHA256 Triage Report
f614a06748251107a34fa7e44c7652fd88e61fd958df724455e14ec88040abf9 1.bin
7d4d207fb5258f504d3f9ef60d431332d1e7320d5849c0b0acf624612b01c8f0 2.bin
357b4979324e2065adc8e6bd11cd7161f830250cae30f50fb13edd70fd2b506b 3.bin
29754f0caa9576eba6b9c351d20549e7e19216c6e72c2963da33450719a51277 4.bin
304a01a339d86ccbba7b1f671839624d446e6ea86474912bf976837df779bad2 5.bin
d2f8a61e8cfc9a6c983fc40d2b7ac33e2a686872d0136dce2f66466c044f246c 6.bin
2b9ef4a9f47402d171eec28acadf3753cbb33c9bc6ec26d99aa060127a470e95 7.bin
eb17935cf972d90be92c9b39fff8b3d760ecda78a6f602cb2b8bbaf3d87e6b61 8.bin
6b88260f4c4da4651a82bb62761cd23ee9ad6662a2a0abbec017e7193668397b 9.bin
256967605423fea1e00368078eea1cdb52d391aa0091e0798db797ab337d1567 10.bin
13c2f4b6fb80500884a4ea9d2fe80774124f46ebfd80de3e1dfcfb9e167aee08 11.bin