Qbot: A Deep Dive into the Banking Trojan
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
CWSandboxVirtual 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.exedsniff.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.
3- Create a link File :
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