Qbot: A Deep Dive into the Banking Trojan

28 minute read

Qbot: A Deep Dive into the Banking Trojan

what is Qakbot?

Qbot (Pinkslipbot) is a Banking Trojan first observed in 2007, It is typically delivered through phishing techniques asking to open malicious attachments or to lure victims onto fake websites that use exploits to execute Qbot onto a victim’s machine, Qakbot steals sensitive data and attempts to self-propagate to other systems on the network. Qakbot also provides remote code execution (RCE) capabilities, allowing attackers to perform manual attacks to achieve secondary objectives such as scanning the compromised network or injecting ransomware

Technical Info:

the sample I have today with ID → spx143 has many capabilities and I will list them in brief then I will conduct in detailed analysis

1- Qbot Encrypts all of its strings and C2 Server to avoid static detection

2- Qbot tries to elevate its authority by using COM and also applying scheduled tasks with NT Authority

3- Qbot also has many anti-analysis and anti-sandboxing tricks

4- can bypass any security control and also inject its Webinjection layer in one of the security control agents which avoids any detection,cause detection control is already run with Qbot code

5- Qbot tries to run a service with high authority

6-Qbot tries to check its Commandline parameters and has a list of parameters and every argument determines a different job to do so it tries to run itself with different command lines and check the Exit Code every time to determine If the subtask was completed successfully or not, like this

exe name [ /C ] or [/W] or [/I] or[P] or[/Q]…..

→ so I will try to make this blog a reference for Qbot cause it will talk about all malware stages, especially Web injection which I will talk a lot about it in this blog or another one, I will determine this when it’s time come in the Malware flow …..keep reading

Technical Analysis

I will not talk a lot about malware through a Word document that contains some macros that own job to download the next stage which is 32-dll and run it, so it uses some hacked websites that contains some image so the sample tries to connect to this legal website and download this image which is PE file and here some C2s I have after some research and reading

hxxp://pickap[.]io/wp-content/uploads/2020/04/evolving/888888[.]png

hxxp://decons[.]vn/wp-content/uploads/2020/04/evolving/888888[.]png

hxxp://econspiracy[.]se/evolving/888888[.]png

hxxp://enlightened-education[.]com/wpcontent/uploads/2020/04/evolving/888888[.]png

hxxp://kslanrung[.]com/evolving/888888[.]png

the downloaded dll is packed so using a debugger and putting some breakpoints in VirtualAlloc() and CreateProcessInternelW() will help you to bypass the Packing routine, let’s do our job and reverse it …

First look

Qbot comes with high entropy due to its encrypted Configuration, the resources are very large and this indicates that there is another layer that will be loaded, all of these many strings have no means but it forgets to delete some of them when he(developer) was debugging the Malware

So the next will be done through my Lady IDA pro, let’s complete

String Decryption

in order to complete the analysis process correctly, we need to perform the decoding process for the strings in the file so I have the time to explore the decryption routine and write a basic script to decrypt the strings and comment it in assembly view, so I build a script which depends in IDA python and PEfile libraries

import idc  
import idautils  
import pefile  
import idautils  
import binascii  
import struct  
  
  
filename = r'Filepath'  
def rename_operand(address,string):  
    idc.MakeName(address,string)  
  
def get_data_key(): #this function parse the data used for decryption  
    pe  = pefile.PE(filename)  
    for section in pe.sections:  
        if b'.data' in section.Name:  
            key = section.get_data()[1216:1283]  
        if b'.rdata' in section.Name:  
            data = section.get_data()[32048:46118]  
    return data,key  
  
  
def decrypt_str(hex_index):  
    data,key = get_data_key()  
    ref_index =int(hex_index,16)  
    ref_max = int(b'36F4',16)  
  
    flag = False  
    decrypted =''  
    if ref_index < ref_max :  
        while key[ref_index & int(b'3f',16)] != data[ref_index]:  
            and_operation = ref_index & int(b'3f',16)  
            decrypted +=chr((data[ref_index] ^ key[and_operation]))  
            ref_index +=1  
          
    return decrypted  
  
  
dec_function = 0x004065B7  # this the address of the function   
                           # used in decryption, so i use it to get all   
                           # refs to it and comment it with the decrypted value  
Xrefs = idautils.CodeRefsTo(dec_function,0)  
for x in Xrefs:  
    ea =idc.prev_head(x)  
    type_ = idc.get_operand_type(ea,1)   
    if type_ == 5 :   
       hex_index = idc.get_operand_value(ea,1)  
       decrypt_val = decrypt_str(hex(hex_index))  
       print(decrypt_val)  
       idc.set_cmt(x,decrypt_val,0)

and here is the result of our script

Check Windows Defender and Decrypt APIs

the sample next will parse the command line and try to check if the file “C:_INTERNAL___empty” exists. This file can be used to check the existence of Windows Defender emulation, and it does this by using GetFileAttributes() if it found it, it will return -1 which will cause the malware to terminate itself

figure 3 -check Defender

if the file doesn’t exist the malware will load some APIs by decrypting the API name and then pass the name to GetProcAddress(), and then it will save this address in the data section to use later

so I append a section in the above script to decrypt APIs and then rename offset with API name and here is how it looks like

and here is how it looks like after decryption and renaming operation

here is the link to the repo which contains all scripts I used against the sample. Click Here.

Prepare Work Environment :

1- the Malware next will try to play with SID (security ID) and also get security Access using process Token to determine the security access level to know the level of the user

2- it also will determine Computer arch [0x64 or 0x86]

3- check if the current user belongs to Active Directory Domain or not

4- it will try to initialize SID and compare it against USER SID

Check AVs Existence

then the malware will decrypt some exe names related to some agents used by famous security Anti-Virus products, Qbot will compare these agent’s names against all running processes in Victim Machine and will do this using CreatToolHelpSnapShot()API, every agent has its own ID and at the end of this comparison the responsible function will return this ID which will be used to avoid some behavior that will be detected by the AV and to simplify this I will try to show you how the data is saved in the stack in this process

the malware creates a structure and uses this structure to save every AV data

struct exe_blob_AVs  
{  
  int ID;            //ID will be used later  
  int Encrypt_Code;  //the encryption index  
  int n;             //the number of agents for this AV  
  int name;          //Agent name   
};

so as I have said before it will generate a list of running process

and after that, it will save the ID in Global Var

ID      Dec_Code   Agent Name

0x1    |  0x660  |    ccSvcHst.exe

0x2    |  0x8C6  |    avgcsrvx.exe;avgsvcx.exe;avgcsrva.exe

0x4    |  0x2E7  |    MsMpEng.exe

0x8    |  0x1A6  |    mcshield.exe

0x10   |  0x6AD  |    avp.exe;kavtray.exe

0x20   |  0x398  |    egui.exe;ekrn.exe

0x40   |  0x141  |    bdagent.exe;vsserv.exe;vsservppl.exe

0x80   |  0x912  |    AvastSvc.exe
 
0x100  |  0x1B3  |    coreServiceShell.exe;PccNTMon.exe;NTRTScan.exe

0x200  |  0x90   |    SAVAdminService.exe;SavService.exe

0x400  |  0x523  |    fshoster32.exe

0x800  |  0x77C  |    WRSA.exe

0x1000 |  0x8F0  |    vkise.exe;isesrv.exe;cmdagent.exe

0x2000 | 0x7F9   |    ByteFence.exe

0x4000 | 0x726   |    MBAMService.exe;mbamgui.exe

0x8000 |  0xAFA  |   fmon.exe



Enum Windows:

Qbot Next will Enum running Windows and Extract its name and compare it to a strange name “snxhk_border_mywnd”, so it’s my first time facing this strange name so I have conducted some research and I found that , this name is related to my MMC so let’s talk in brief about MMC.

MMC stands for Microsoft Management Console. A GUI (Graphical User Interface) allows users to manage Windows settings and components. MMC is a snap-in-based console, which means that it can be customized with different snap-ins to manage different aspects of Windows.

The Qbot Trojan uses the MMC window to install itself on infected computers because the MMC window has a high level of privileges. This means that the Qbot Trojan can install itself without being detected by some antivirus programs.

Exploring EnumFunc() passed to EnumWinsows()API this function is used as a callback function to be called every time this API detects a Window or any graphic symbol, Qbot uses GetClassName()API to Extract Window name by passing a handle to the window

and then it compares it against the Strang name I talked about above “snxhk_border_mywnd”

and based on the result of this operation Qbot will take a decision of resolving an API to be ‘MessageBoxA’’ or ‘’FindFirstFileA’’

Run ChildProcess and Get ExitCode :

next Qbot will parse command line arguments as I said before and compare them against the embedded arguments, if it found the Command line argument is less than or equal to 1, it means that the malware has been executed without any parameters and it will take a decision to run itself but with different arguments, and for the first time it will run with [/C] argument, let’s explore that….

here it compares a number of arguments.

and if it is not greater than 1 it will go to [Loc_401BB2], Exploring this location, the Malware Will Compare Anti-Virus Group Id I explained before to 0x40 that’s means checking if Victim uses BitDefender software and if it’s, it will not run a child process with argument [/C]

My VM does not have any security software so this comparison will lead us to the child process, let’s explore it, inside mw_CreateChildProcess(), Qbot will prepare a command line that will be used to run itself again, it will append [/C] to its file path and then call CreateProcessA()API,

inside mw_CreateProcess(), there is a call to GetExitCodeProcess()API and the malware uses ExitCode to determine if the child process does its task correctly or not,if we take a look at this

and after that, it will check if the exit code = 1 or not which will be used next to determine many steps

So I have attached a debugger to the child process and moved to the Entry point and start again but with a different command line in this case it’s [/C] so I will move to the part the malware does if it found ‘/C’ in the command line

ANTI-Analysis Checks :

As you have seen, the malware will do some anti-sandboxing and Anti- virtualization tricks, so Let’s examine these tricks and learn about them in detail…

1- malware check if it is running in VMware product using I/O ports and will return 0 if it’s

2-Qbot will Enumerate all running devices and also compare them against some VMware, VBox, and Malware Analysis tool Devices and if it detects any of them it will take a different action

3-Qbot will iterate overall running processes and compare them with embedded process names related to some Tools used by Researchers

4-Malware Also Check Loaded Modules and also have some modules that will be used by SandBoxs so it will compare them and flag if it detects any of them

5-Compare Module name against some names also used by sandboxes and Researchers

6- will use cpuid instruction to get CPU Name and compare it against decrypted CPU Name.

check anti-analysis

so let’s dig deep into these functions one by one:

mw_Check_VMware_Port():

this function gets a value from the I/O ports using the ‘in’ instruction and compares it with the embedded value, it uses port = 0x5658, and this port number is related to the VMware product so after executing the instruction it checks if the value = 0x564D5868 → ‘VMXh’ which alter that the malware is running inside a virtual machine

mw_CheckDevices():

inside this function, Qbot will encrypt some Devices names and some devices keyword that may be used inside the Device description and then it will compare these 2 lists against All Devices Names and Descriptions installed inside the machine, figure will explain that….

this is the list to compare, and many of them are related to VMware and Vbox.

the malware starts by calling SetupDiGetClassDevsA() which is used to return a handle to a device information set, this handle will be used again to retrieve device information [description or name]

inside sub_40352c() it will use the third argument which is used to determine the type of data retrieved by SetupDiGetDeviceRegistryPropertyA()API,

SetupDiGetDeviceRegistryPropertyA(// The function retrieves a REG_SZ string that contains the description of a device.

         DeviceInfoSet,  
         DeviceInfoData,  
         Property,              #third argument   
         &PropertyRegDataType,  
         PropertyBuffer,        # Data Retrieved   
         PropertyBufferSize,  
         &PropertyBufferSize) )

and then it will check if an error occurred using GetLastError()API, and then return the retrieved data

then the malware will do the same operation but use a different flag as a property, and this time it uses the service name and then compare it against the installed devices’ names

Here is the list of device names.

Expand to see more
  VMware Pointing
  VMware Accelerated
  VMware SCSI
  VMware SVGA
  VMware Replay
  VMware server memory
  CWSandbox
  Virtual HD
  QEMU
  Red Hat VirtIO
  srootkit
  VMware VMaudio
  VMware Vista
  VBoxVideo
  VBoxGuest
  vmxnet
  vmscsi
  VMAUDIO
  vmdebug
  vm3dmp
  vmrawdsk
  vmx_svga
  ansfltr
  sbtisht

mw_CheckRunning_Process():

next Malware will create a snapshot of all running processes and compare them against a package of tools used by Malware Analyst and Researchers

then it will iterate over all processes and get its name then compare

and here is the list of Process to detect.

Expand to see more
  Fiddler.exe
  samp1e.exe
  sample.exe
  runsample.exe
  lordpe.exe
  regshot.exe
  Autoruns.exe
  dsniff.exe
  VBoxTray.exe
  HashMyFiles.exe
  ProcessHacker.exe
  Procmon.exe
  Procmon64.exe
  netmon.exe
  vmtoolsd.exe
  vm3dservice.exe
  VGAuthService.exe
  pr0c3xp.exe
  CFF Explorer.exe
  dumpcap.exe
  Wireshark.exe
  idaq.exe
  idaq64.exe
  TPAutoConnect.exe
  ResourceHacker.exe
  vmacthlp.exe
  OLLYDBG.EXE
  windbg.exe
  bds-vision-agent-nai.exe
  bds-vision-apis.exe
  bds-vision-agent-app.exe
  MultiAnalysis_v1.0.294.exe
  x32dbg.exe
  VBoxService.exe
  Tcpview.exe

mw_CheckLoaded_Modules():

inside this function, Qbot creates a snapshot of all loaded modules inside the victim machine and compares it against some modules that had been used by sandboxes, like.

ivm-inject.dll

SbieDll.dll

mw_CheckModuleFileName():

inside this function, Malware will compare filename against some names that are used a lot with sandbox and Malware Researchers,like

‘sample’

‘mlwr_smpl’

‘artifact.exe’

mw_Check_CPU():

this function benefits from _cpuid x86 instruction and uses it twice to retrieve data about the CPU used inside the victim machine.

when u use cpuid instruction u need to put a value inside the EAX register that will determine the return value of cpuid instruction, in our case, the first time it put 0 inside EAX, that returns the CPU model and will be saved inside EBX, ECX, and EDX registers

the second chance it will put 1 inside EAX and the result of this has much information but we are interested in one bit of them that is stored inside ECX eax and if it’s = 1 → VM, and if = 0 → Normal Machine

mw_Check_NAT_Network:

if you have used VMware before and adjusted the network card settings to be NAT, VMware will start a process called vmnat.exe which is used to manipulate the communication in the NAT formula with the guest machine

vmnat.exe is a Windows executable file that is used by VMware Workstation to provide Network address translation for virtual networks

so Qbot will create a snapshot for all running processes and compare them with ‘vmnat.exe’

check Hibernation :

the malware encrypts a string called ‘c:\hiberfil.sysss’ and after some research, I found that The file “c:\hiberfil.sys” is a system file on the Windows operating systems. It is created when you enable the Hibernate feature, which allows your computer to save the current state of your system to the hard disk and power off

I know that I talked a lot about Anti-analysis but as I said before I want this article to be a reference in reverse engineering Qbot -_-

Back To the parent :

so after all of these anti-analysis checks, Malware will back again to Parent Process but with ExitCode I explained above, this exit code determines if it’s running inside VM or not

1 = VM OR SandBox (Analysis Machine)

0 = Normal machine

Load Resource 307 :

then after the parent takes control again it will proceed to load resource with [ID = 307 ] using sub_40419A which I have renamed to ‘’MW_W_ResourceManuplations ‘’

so we need to dive deep into this function and u will find that it wraps a function that has the core API Calls for resource manipulation…

inside sub_40405B → ‘mw_Resource_307_Manuplations’ it has some calls like..

FindResourceA() → to obtain the location of the resource

SizeOfResource() → to get resource size

LoadResource() → retrieves a handle that can be used to obtain a pointer to the first byte of the resource

then it goes further to decrypt this resource using RC4 using some nested calls, but I am interested only in the decrypted resource so maybe we need to bypass some calls…

here is Qbot after getting a pointer to Resource’s first Byte it uses wrapped RC4 function → sub_402D00 ‘’mw_w_w__RC4_Decrypt’’, if we take a look inside this function …

you will find that the function first allocates a heap with a size of 0x448 but I have observed that this size is very small compared to the Resource Size so this heap may be used as a structure next or another thing but it will not contain the decrypted Data

so we need to move forward to sub_402C1F “mw_RC4_Decrypt”, and inside this function, I really have found what I need, there is a heap allocation but this time uses Resource Size as an argument and that will give us a heap with size = 0x233CA → Resource Size.

and next, I observed another function (sub_403117) which I have renamed to ‘mw_RC4_Decrypt’ cause inside it RC4 mechanism comes

take a deep look at the figure above to be able to understand what comes next.

the RC4 Decryption Routine:

Qbot uses the first 20 bytes of resource as a key which will be used to generate RC4 Key and then implement complex XOR operation inside RC4 Algorithm, so let’s take another look inside ‘’mw_RC4_Decrypt’’

so we need to see this operation in a more dynamic view so that I will use the debugger for the next step

first, it will copy the data inside the large heap

malware will do the 2 following steps related to KSA and PRGA and will result in us the decrypted chunk …

as we know in RC4_KSA it initializes an array with 256 and then will do some operations to generate a symmetric key, it will generate a 256-byte key using the first 20 bytes of the resource

next, the final part comes which is xor and decrypt …

so let’s Explore RC4_PRGA, and inside it, the decryption is done correctly but results in a destroyed PE File

this Header is destroyed with many Null Chars ‘0x00’ bytes, so I will not give up and will trace its code until it fixes this PE File.

Fixing PE Headers

after the Decryption part, we got Distorted data so statically that we couldn’t resolve it, so inside sub_40703C there is some suspicious operation that may help us in this stage of fixing

getting into this function I found that it Allocate a heap 3 times. at this point, I am not interested in how it fixes the File I just want it to be fixed so I will parse the 3 pointers that Allocate Heap returns and watch them in the dump, and set a HardWare Breakpoint in the first DWORD in the 3 heaps until the Malware Hits any of them and when we hit this breakpoint we will know what function is responsible for this

so we got a hit inside sub_4080A2 and the malware started writing a Normal PE file inside the Allocated Heap

sub_4080A2 is responsible for PE Fixing operation

fixed pe file

so after resolving all sections, I dumped this memory chunk for further analysis

Resource 308 :

after that malware decrypted resource 307 and load it into memory but does not execute it yet

but the trick is that, Qbot loads 307 PEfile into memory and gets a pointer to it, and then will use this pointer to get a reference for one of its resources with ID = 308, the following figure will explain more.

it processed in decrypting 308 rcs and it will do the same operation, so I dumped the resource cause its size is smaller than the first one, just 0x40 bytes, and uses Cyber chef to decrypt it by using the first 20 bytes as a key for RC4_KSA routine

10 = spx143 → the botnet ID

3 = 1592482956 → Unix Time refers to the Creation Time of 307 PeFile

Check AVAST Anti-Virus Software :

inside sub_408F6F Qbot has much work to do, so in the next words I will try to summarize more cause this article is going to be tall more than I expected

inside sub_406726 “mw_Check_AVAST_AV” Qbot Tries to Check the existence of AVAST SoftWare by trying to get a handle for some DLLs used be AVAST

_aswhooka.dll   aswhookx.dll_

and if it detects any of them,it will not complete the whole sub_408F6F and return -1.

Play with SpyNet Registry Key :

after ending the AVAST check Qbot checks if Token Flag obtained before has the priority of 3 which means it’s Mandatory and if it’s, it will Do some operation in the registry with keys related to Windows Defender and Anti-Malware Service inside sub_406874() “mw_Maniuplate_with_SPYNET_Registery()”

SOFTWARE__Microsoft_\Microsoft AntiMalware\SpyNet_

SOFTWARE__Wow6432Node_\Microsoft AntiMalware\SpyNet_

and will check for 2 values

1- ‘SpyNetReporting’: This value specifies whether or not Microsoft Antimalware will report information about malware to SpyNet.

2- ‘SubmitSamplesConsent’: This value specifies whether or not Microsoft Antimalware will submit samples of malware to SpyNet

but the trick here is that Qbot doesn’t access the registry via direct API Calls like AddRegKey() or whatever, instead of that it creates a process that uses reg.exe and passes the command line to modify the Registry

— — — u need to add here the full command line executed by reg.exe — — —

if we return to sub_408922 which will do many things, I will talk about important keys and operations inside it.

sub_408922 :

1- Query User Profile Via Registry

the first action done inside sub_408922 is querying a value from the registry related to User’s profile paths, so inside sub_40A6C1, Qbot will try to decrypt the subkey and use the value to extract

subkey → SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList

value → ProfileImagePath → This value specifies the path to the user profile folder.

cause there are many user profiles in this subkey so it will append the SID of the User to only get its profile path

2- Generate 2 File Names:

we are still inside sub_408922 and after getting the user profile path and AppData path Qbot will generate 2 file names that will be used one for saving data or its configuration and the other to save itself

3-Write Data into .dat File

after generating 2 Random names for files, Qbot starts allocating data to be stored into a data file which will be used as Config and will be accessed many times by Qbot, after that Data is RC4 decrypted and then written to the file.

here is what the data looks like before encryption.

11=2 → hard drive type
1=09.53.50–24/06/2023 → time of Qbot’s installation
2=1687625630 → Unix time

and hereafter writing encrypted Config into a .dat file

and then Qbot will copy itself to the same path but it uses a different approach than using CopyFile() API, so it decrypts a VBS code and then save it for further execution

Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\.\%coot\cimv2")  
Set colFiles = objWMIService.ExecQuery("Select * From CIM_DataFile Where Name = '%s'")  
    For Each objFile in colFiles  
    objFile.Copy("%s")  
    Next

VBScript uses the Windows Management Instrumentation (WMI) service to copy a file. The script first creates a WMI object and then executes a query to select all files that match the specified name. The script then loops through the results of the query and copies each file to the specified location

Qbot uses CScript.exe to run the code and this code is responsible for coping data from one place to another

the file is the same name as the .dat file I explained before and is saved in the same directory

Execute Dropped File :

after dropping itself in another path it will check AVs via the IDs Explained before, if Qbot detects F-Secure or Kaspersky Avs it will use COM to Execute the Dropped File, else it will run it normally using CreateProcess(), so I forced the File to Use com Just for learning.

The first step is to create a WMI object. This is done by calling the ConnectServer() API with the WMI namespace ROOT\\CIMV2. The ROOT\\CIMV2 namespace is the root namespace for WMI.

The next step is to call the CoSetProxyBlanket() method. This method is used to set the security context for the WMI object. The security context determines the permissions that the WMI object has.

The third step is to call the GetObject() method with the Win32_Process class. The Win32_Process class represents a process on a Windows computer.

The fourth step is to call the Put() method with the command line %AppData%\Microsoft\Vhdktrbeex\Qbot.exe. The Put() method is used to set the properties of the WMI object. In this case, the property that is being set is the command line that the process will execute.

The fifth and final step is to call the ExecMethod() method to run the process. The ExecMethod() method executes the method that is associated with the property that was set in the Put() method. In this case, the method that is being executed is the Run() method.

using a WMI object to run QBot is a better way than directly calling CreateProcess for protecting the process. As we know, the WMI object is handled by the Windows process “wmiprvse.exe”

Persistence :

Qbot uses a variety of persistence methods.

1- Via Registry

the first and famous method of persistence is adding a malware path to the registry key that runs all of its value when the OS boots, so Qbot uses

SOFTWARE\Microsoft\Windows\CurrentVersion\Run

Qbot uses sub_406B6A for Adding Key values but instead of using Normal APIs, it runs rege.exe to perform this Task.

2- Run PowerShell Code:

Qbot has the ability to run PowerShell code to scam users into something related to Windows updates, sub_4069E9 Qbot Decrypt the PowerShell code and then appends Dropped file to this code

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command
“$windowsupdate = "C:\Users\Hack\AppData\Roaming\Microsoft\Zqtyjwtbony\nlpuzzcw.exe";
& $windowsupdate

This code assigns the file path "C:\Users\Hack\AppData\Roaming\Microsoft\Zqtyjwtbony\nlpuzzcw.exe" to the variable $windowsupdate. Then it executes the command stored in $windowsupdate using the & operator.

it also has the ability to create a link file and add it to the path of startup programs

C:\Users\Username\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\StartUp\nlpuzzcw.lnk

This means it will be automatically executed when the users start their computer.

then it will use COM to create an object of Shell32.dll to run this

4-Create a scheduled Task:

Qbot tries to add itself to schedule tasks to run itself every 5 hours, the scheduled task runs this dropped file as a kind of persistence, and the dropped file executes with [“/i”] on its CommandLine.

so it adds the task to run as NT Authority

“C:\Windows\system32\schtasks.exe” /Create /RU “NT AUTHORITY\SYSTEM” /tn pbyrjymee /tr “"C:\Users\UserName\Desktop\QbotForTesting\Qbot.bin" /I pbyrjymee” /SC ONCE /Z /ST 20:34 /ET 20:46

The Schedule Task Process:

the executed task which has been fed with the argument “/I”, In fact, this mission has been fueled by more than 2 argument, If you check the code section above you will observe that there is 2 argument passed to Qbot Task

“/I pbyrjymee “ and that makes the number of arguments = 3 due to

Process name , /I , pbyrjymee

Qbot Handles this via a different Code branch in which all missions is deleting scheduled tasks and replace the image file with a legitimate file

1 - Replace Your Self :

due to argument [“/I”] the created task will go to the code branch prepared for “/I”

“mw_LoadRcs” is the function we have analyzed before but this time in sub_408F6F “mw_Create_Schedule_Task” it will check the existence of the Dropped File in %APPDATA%Rooming/Microsoft/Zqtyjwtbony and if it exists it will make a different behavior and at this point, it will replace itself with Calc.exe process

inside sub_40870E()mw_ShellExecute()” it will check AV Group Id and if it is one of the following it will return -1.

Symantec   Kaspersky   Trend Micro

else it will complete the Hollowing mission

and the full command will be like this

Cmd.exe /c ping.exe -n 6 127.0.0.1 & type “C:\Window\System32\calc.exe” > “C:\Users\UserName\Desktop\QbotForTesting\qbotfortesting_00820000.bin

2 - Delete Scheduled Task :

cause the scheduled task executed with 3 command line arguments, so in Qbot main it retrieves the number of arguments and then checks if it is bigger than 2

Command line → Process name /I pbyrjymee

inside sub_406990 “mw_Delete_Schedule_Task,” Qbot will resolve the command line used to run “schtasks.exe” and Delete this task

Process injection :

if you remember the process created by WMI which is called nlpuzzcw.exe this process runs Under WMI and had been executed without any argument so it will do the same behavior done with Parent File as it is executed for the first time but the difference comes on the event that it checks for its directory and if it exists, it will take a different code branch, so one of the most important methods done by this WMI process is Process injection, inside sub_4045A8() which is responsible for Process injection mechanism Qbot check the x64 Flag obtained before to determine the victim process to be hacked

After finding out the unlucky process Qbot starts preparing for injection and this stage includes:

1-Creating a process in a suspended state

this type of injection requires a suspended process to modify its Binaries

2-Create a new section to contain the code to be injected

to complete the injection steps, Qbot needs to create a new section to contain the code and then map this code in the 2 processes the current process and the suspended process, if this process completes successfully then it need to unmap the section of the current process.

3- Write payload into Remote Process and Set Entry Point.

at this point, memory is ready for code writing but first Qbot needs to change the memory protection of the created section from RX to RWX to be able to write data without any access violation. and before this step, it needs to obtain metadata related to the entry point of the suspended process using GetThreadContext() API and then it will change EAX register which contains the entry point address with 0xE9 which is saved inside V9,

0xE9 → Jmp instruction in x86 arch

this jump instruction will point to The Payload entry point

4- Resume the suspended Thread

The final step is to Resume the suspended thread after modifying its binaries and sections

C2 Connection :

this stage of Qbot has a few connections to C2 inside some functions and is only used for updating Qbot but if you remember Resource with ID 307 which after decryption was PE File.

307 Resource has 2 resources 308,311

we have talked about 308’s Resource which contains campaign data like ID and Compilation Time, by using the same decryption approach used for 308 and 307 resources which was about using the first 20 bytes as Key for RC4 Decryption, I have used CyberChef for this operation, and it extracts me with more than 100 IPv4 addresses.

Conclusion.

Qbot is one of the most sophisticated Malware, It has the ability of Banking Trojans by using WebInjection and Exfiltrate user data so in the next part I will talk in deep about API Hooking and Webinjection Module used by Qbot….soon ISA

IOCs:


Qbot: F5FF6DBF5206CC2DB098B41F5AF14303F6DC43E36C5EC02604A50D5CFECF4790  
  
Resource_307 : 118FC3D93D6E34B8F1A817313E218A3A4F5BAF996E03CD2BE34E237B197FA0F3  
  
URL :  
    http://st29[.]ru/tbzirttmcnmb/88888888.png  
  
    http://restaurantbrighton[.]ru/uyqcb/88888888.png  
  
    http://royalapartments[.]pl/vtjwwoqxaix/88888888.png  
  
    http://alergeny.dietapacjenta[.]pl/pgaakzs/88888888.png  
  
    http://egyorg[.]com/vxvipjfembb/88888888.png  
  
C2 :  
39.36.254.179;995  
24.139.132.70;443  
24.202.42.48;2222  
72.204.242.138;443  
172.242.156.50;995  
72.204.242.138;20  
68.174.15.223;443  
74.193.197.246;443  
96.56.237.174;990  
64.19.74.29;995  
70.168.130.172;443  
189.236.166.167;443  
68.4.137.211;443  
76.187.8.160;443  
76.86.57.179;2222  
73.226.220.56;443  
67.250.184.157;443  
75.183.171.155;3389  
173.172.205.216;443  
173.3.132.17;995  
172.78.30.215;443  
207.255.161.8;32103  
75.137.239.211;443  
68.49.120.179;443  
206.51.202.106;50003  
82.127.193.151;2222  
207.255.161.8;2222  
207.255.161.8;2087  
24.152.219.253;995  
187.19.151.218;995  
197.37.48.37;993  
188.241.243.175;443  
72.88.119.131;443  
89.137.211.239;443  
108.30.125.94;443  
187.163.101.137;995  
100.19.7.242;443  
45.77.164.175;443  
80.240.26.178;443  
66.208.105.6;443  
207.246.75.201;443  
199.247.22.145;443  
199.247.16.80;443  
95.77.223.148;443  
68.60.221.169;465  
5.107.220.84;2222  
41.228.212.22;443  
86.233.4.153;2222  
68.200.23.189;443  
201.146.127.158;443  
79.114.199.39;443  
87.65.204.240;995  
71.74.12.34;443  
217.162.149.212;443  
195.162.106.93;2222  
75.165.112.82;50002  
201.248.102.4;2078  
96.41.93.96;443  
89.247.216.127;443  
84.232.238.30;443  
103.238.231.40;443  
174.34.67.106;2222  
98.115.138.61;443  
91.125.21.16;2222  
84.247.55.190;443  
193.248.44.2;2222  
74.135.37.79;443  
78.96.190.54;443  
86.126.97.183;2222  
2.50.47.97;2222  
68.39.160.40;443  
96.232.203.15;443  
86.144.150.29;2222  
71.220.191.200;443  
24.231.54.185;2222  
80.14.209.42;2222  
24.164.79.147;443  
70.183.127.6;995  
47.153.115.154;993  
184.180.157.203;2222  
50.104.68.223;443  
67.165.206.193;995  
200.113.201.83;993  
47.153.115.154;465  
24.42.14.241;995  
189.160.203.110;443  
188.27.76.139;443  
207.255.161.8;32102  
49.207.105.25;443  
71.210.177.4;443  
117.242.253.163;443  
50.244.112.106;443  
69.92.54.95;995  
41.34.91.90;995  
72.204.242.138;53  
41.97.138.74;443  
72.29.181.77;2078  
71.88.168.176;443  
2.50.171.142;443  
67.83.54.76;2222  
86.125.145.90;2222  
47.153.115.154;995  
24.122.157.93;443  
47.146.169.85;443  
72.181.9.163;443  
187.155.74.5;443  
71.209.187.4;443  
74.75.216.202;443  
24.44.180.236;2222  
24.43.22.220;993  
108.188.116.179;443  
100.4.173.223;443  
76.170.77.99;443  
70.95.118.217;443  
134.0.196.46;995  
68.225.56.31;443  
72.204.242.138;32102  
72.204.242.138;50001  
108.190.151.108;2222  
72.204.242.138;465  
50.244.112.10;443  
173.22.120.11;2222  
24.43.22.220;995  
24.43.22.220;443  
92.17.167.87;2222  
72.209.191.27;443  
72.204.242.138;80  
72.204.242.138;443  
71.187.170.235;443  
96.56.237.174;32103  
71.187.7.239;443  
184.98.104.7;995  
70.124.29.226;443  
137.99.224.198;443  
73.23.194.75;443  
151.205.102.42;443  
64.224.76.152;443  
72.204.242.138;32100  
173.187.101.221;443  
72.179.13.59;443  
208.93.202.49;443  
70.174.3.241;443  
96.37.137.42;443  
76.111.128.194;443  
67.209.195.198;3389  
61.3.184.27;443  
24.42.14.241;443  
74.56.167.31;443  
5.193.61.212;2222  
117.216.177.171;443

References :

https://www.fortinet.com/blog/threat-research/deep-analysis-of-a-qbot-campaign-part-1

https://n1ght-w0lf.github.io/malware%20analysis/qbot-banking-trojan/

https://blog.vincss.net/2021/03/re021-qakbot-dangerous-malware-has-been-around-for-more-than-a-decade.html

Updated: