Intro
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[1] as well as the string decryption algorithm[2]. 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
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 Roaming/Microsoft
.
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.
Anti Analysis
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.
AntiVirus
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
.
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
VM Devices
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
VM Processes
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[3]. If one of those is detected as a running process, execution aborts.
ivm-inject.dll
SbieDll.dll
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
CPUID Check
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:
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 ResumeThread
.
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.
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.
So far I identified atleast 1 routine which is influencing the unpacking process. I will talk about this in my next blog article.
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 previous chapter of this article.
IoCs
SHA256
: c23c9580f06fdc862df3d80fb8dc398b666e01a523f06ffa8935a95dce4ff8f4
Icons made by Freepik from www.flaticon.com