I hope everyone is healthy :-).
I finally managed to find some time to continue my analysis of QBot. If you did not read my previous articles, I’ve already covered the packer as well as the string decryption algorithm. I’ve linked them both here.
In this blog post I will cover the process execution chain that is happening before it even injects itself into the
explorer.exe. I will talk about the anti analysis methods that are implemented into QBot and explain the injection process. Finally I finish off with a quick look at the unpacking routine being executed by the injected task.
Process execution chain
Process execution chain before process injection
Before QBot drops itself and injects into
explorer.exe, it has a fascinating process execution chain. Once the sample is unpacked it always checks if a known anti virus process is running. Next it starts itself with parameter
/C and probes wether it is running in a virtual environment. All anti analysis measures which are carried out in this sub process are explained in the next chapter.
The parent process holds its execution by calling
WaitForSingleObject until the child process (“
QBot.exe /C“) is done.
If the subprocess detects a virtual machine, an event is sent to the parent process to stop its execution. If not, the parent process drops itself and its config file into into a randomly created folder in
QBot dropped itself into Roaming/Microsoft/X
Once it executes this dropped file, the starting binary is overwritten by the parent process with
calc.exe leaving no obvious clues of a malware dormant on the system.
QBot implements a huge arsenal of anti analysis measures it uses to detect an analysis environment. If any of those checks match, the process kills itself.
The first check is done by enumerating all processes and searching for processes known for protecting its user from malicious activity. It’s worthy to mention that this check is always done, regardless of the parameter QBot is started with.
First it initialises a table of decrypted strings. For each of those strings, all processes are enumerated with
Process32Next and compared against strings in its table with
strcmpiA. QBot stops its execution once one of those processes are found.
Here is the list of processes it tries to detect:
ccSvcHst.exe avgcsrvx.exe avgsvcx.exe avgcsrva.exe MsMpEng.exe mcshield.exe avp.exe egui.exe ekrn.exe bdagent.exe vsserv.exe vsservppl.exe AvastSvc.exe coreServiceShell.exe PccNTMon.exe NTRTScan.exe SAVAdminService.exe SavService.exe fshoster32.exe WRSA.exe vkise.exe isesrv.exe cmdagent.exe MBAMService.exe ByteFence.exe mbamgui.exe fmon.exe
Virtual machines and sandboxes leave trails on a system, these trails can be found the registry of a Windows system. QBot enumerates the device list and tries to find the following device entries:
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 wdsk vmx_svga ansfltr sbtisht
Not only anti virus processes are detected, it also checks for common processes found in sandbox environments.
vmtoolsd.exe vmacthlp.exe metsvc-server.exe windump.exe
DLLs used by sandboxes
SbieDll.dll is for example used by sandboxie. If one of those is detected as a running process, execution aborts.
Sandbox file names
There is this good old tip that you should not call a malware sample you are executing
sample, because the malware might check its file name and stops executing if it detects a suspicious name. Here is the living proof:
sample mlwr_smpl artifact.exe
It also implements the
CPUID check. By executing this instruction with
eax=1, the return value describes the processors features.
On a physical machine the last bit will be equal to 0, on a guest though it will be a 1.
Overwriting itself with calc.exe
In order to conceal the infection, the starting file is overwritten with
calc.exe, using the following command:
command used to overwrite the starter file
Injection into explorer.exe
Once the binary is dropped, a suspended
explorer.exe process is created and a new memory page is allocated via
VirtualAlloc. It injects itself into this process and the suspended thread is invoked with
Once again the parent process waits for an incoming event, if the injection was successful. If it failed, it will restart the injection procedure.
I’ve compared the injected code with the unpacked QBot binary and identified that it injects itself into
explorer.exe and not custom code.
Comparing the injected code and the injector with diaphora
Unpacking the payload
We are now talking about what is happening in the injected process. Once the thread is resumed, another unpack routine is started.
New memory is allocated again and its access rights are set on executable.
VirtualAlloc call, creating space for the DLL
So far I identified atleast 1 routine which is influencing the unpacking process. I will talk about this in my next blog article.
Graph overview of mentioned routine
5 – Conclusion
I’ve spent some time now reversing QBot and I am still very far away from understanding everything what is happening there, but I’ve made some serious progress. From my point of view, I believe that the way QBot tries to detect virtual machines as well as analysis environments is pretty extensive. If you don’t think so, I would be glad to hear your opinion.
In my next post I will handle the unpacking process which I’ve only mentioned in the forth chapter of this article.
6 – IoCs
* This article was originally published here