{
	"id": "25c7ee7f-a48b-4390-916d-e07604a6cb6d",
	"created_at": "2026-04-06T00:13:08.819202Z",
	"updated_at": "2026-04-10T13:11:56.433863Z",
	"deleted_at": null,
	"sha1_hash": "f24003e62ba31ae8825ad3ba1a62f93ffc92f093",
	"title": "Deep Analysis of a QBot Campaign – Part I | FortiGuard Labs",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 2041589,
	"plain_text": "Deep Analysis of a QBot Campaign – Part I | FortiGuard Labs\r\nBy Xiaopeng Zhang\r\nPublished: 2020-06-11 · Archived: 2026-04-05 22:49:00 UTC\r\nFortiGuard Labs Threat Research Report\r\nAffected platforms:    Microsoft Windows\r\nImpacted parties:       Windows Users\r\nImpact:                       Collects sensitive information from victims’ computers\r\nSeverity level:             High\r\nQBot is a Trojan, also known as QakBot, which has been active for years. It was originally known as a financial\r\nmalware designed to target governments and businesses for financial fraud by stealing user credentials and\r\nkeystrokes. It was observed by threat researchers at the time that it was delivered through phishing campaigns, or\r\nby another malware, such as Emotet.\r\nFortiGuard Labs recently captured an MS Office Word document in the wild that was spreading a variant of QBot.\r\nNormally, such Word documents are only delivered in a phishing email designed to deceive the victim into\r\nopening it. Unfortunately, we only captured the Word file, so we do not know how it is being delivered.\r\nI performed a deep analysis on this sample file. QBot uses complicated techniques and a framework designed for\r\nit to run covertly on a victim’s system. In this post, I will explain how it works on a victim’s machine, as well as\r\nwhat techniques it uses.\r\nOpening the Word Document Containing QBot\r\nAs you may have expected, the Word document includes a malicious Macro. Once the file is opened in the Word\r\nprogram, it asks the victim to click a yellow button, as shown in Figure 1.1 (on the left). The image on the right\r\npart shows what it looks like after the “Enable Content” button has been clicked. It spoofs the victim into thinking\r\nit is working hard on loading data.\r\nhttps://www.fortinet.com/blog/threat-research/deep-analysis-of-a-qbot-campaign-part-1\r\nPage 1 of 13\n\nFigure 1.1. Word document is opened in Word program\r\nHowever, what’s actually happening is that the malicious Macro (VBA code) is executing in the background. It\r\nhas a function called Document_Open() that is automatically called while the file is opening.\r\nThe Macro creates a folder named “tmpdir” in “C:\\Users\\Public\\”.  It then tries to download the QBot payload into\r\nthis folder. The attacker puts the QBot payload file in five places. These are: \r\nhxxp://pickap[.]io/wp-content/uploads/2020/04/evolving/888888[.]png\r\nhxxp://decons[.]vn/wp-content/uploads/2020/04/evolving/888888[.]png\r\nhxxp://econspiracy[.]se/evolving/888888[.]png\r\nhxxp://enlightened-education[.]com/wpcontent/uploads/2020/04/evolving/888888[.]png\r\nhxxp://kslanrung[.]com/evolving/888888[.]png\r\nThe URLs are decoded from five Base64-encoded strings with PowerShell code. During its execution, the\r\nmalware shows the victim the information shown in Figure 1.1 (the image on the right.)\r\nThe PowerShell code repeats picking one of the five URLs once within a loop to download the payload file\r\n888888.png (EXE file) into “C:\\Users\\Public\\tmpdir\\”. It then renames it to “file*.exe” that finally gets executed.\r\nIt stops the loop when the first payload file has been downloaded. (Note: the “*”symbol used here can be 1, 2, 3,\r\n4, or 5. Therefore, the downloaded payload file will be referred as “file1.exe” in this analysis.) \r\nFigure 1.2 shows the powershell code decoded by Macro to download QBot payload file.\r\nhttps://www.fortinet.com/blog/threat-research/deep-analysis-of-a-qbot-campaign-part-1\r\nPage 2 of 13\n\nFigure 1.2. PowerShell code to download QBot payload and execute it\r\nLooking at the five URLs, you may notice that they were probably built with the same website builder, which may\r\nhave vulnerability that allows the uploading of EXE file onto it with a PNG extension name.\r\nExecuting the Downloaded Payload \r\n“file1.exe” is the downloaded payload that is protected in a packer. When it starts, the packer extracts the\r\nprotected QBot into memory and then overrides the packer’s code. Once that is completed its entry point gets\r\ncalled.\r\nQBot provides some command line parameters, like “/C”, “/W”, “/I”, “/P”, “/Q” and so on, for performing\r\ndifferent features. When it is started by the PowerShell code, no parameter is provided. It goes to a non-parameter\r\nbranch, which first spawns a normal child process of itself with the command line parameter of “/C”. Figure 2.1\r\nshows it about to create a child process with that command line parameter.\r\nhttps://www.fortinet.com/blog/threat-research/deep-analysis-of-a-qbot-campaign-part-1\r\nPage 3 of 13\n\nFigure 2.1. Spawning a child process with parameter “/C”.\r\nThe “/C” feature is for checking whether or not it is running in an analysis environment. The following are the\r\nways that it performs that detection.\r\nIt executes ASM code with the keyword “VMXh”, where it will trigger an exception if it is in a Virtual\r\nMachine. The exception handler can capture the exception and returns 1, otherwise it returns 0. Below is\r\nthe ASM code snippet.\r\n[…]\r\n.text:00403452                 push    ebx\r\n.text:00403453                 push    ecx\r\n.text:00403454                 push    edx\r\n.text:00403455                 mov     dx, 5658h\r\n.text:00403459                 mov     ecx, 564D5868h  ;; \"VMXh\".\r\n.text:0040345E                 mov     eax, ecx\r\n.text:00403460                 mov     ecx, 14h\r\n.text:00403465                 in      eax, dx\r\n.text:00403466                 mov     [ebp+var_1C], eax\r\n.text:00403469                 pop     edx\r\n.text:0040346A                 pop     ecx\r\n[…]\r\nIt checks if it runs in Virtual Machine environment by calling the API function SetupDiEnumDeviceInfo()\r\nto enumerate the device information. It then checks to see if that device information contains the below\r\ntexts, which are keywords for Virtual Machine software, like “VMware”, “VirtualBox”, “CwSandbox”,\r\n“Red Hat Virtualization”, “QEMU”, and so on.\r\nhttps://www.fortinet.com/blog/threat-research/deep-analysis-of-a-qbot-campaign-part-1\r\nPage 4 of 13\n\n\"VMware Pointing\", \"VMware Accelerated\", \"VMware SCSI\", \"VMware SVGA\", \"VMware Replay\", \"VMware\r\nserver memory\", \"CWSandbox\", \"Virtual HD\", \"QEMU\", \"Red Hat VirtIO\", \"srootkit\", \"VMware VMaudio\",\r\n\"VMware Vista\", \"VBoxVideo\", \"VBoxGuest\", \"vmxnet\", \"vmscsi\", \"VMAUDIO\", \"vmdebug\", \"vm3dmp\",\r\n\"vmrawdsk\", \"vmx_svga\", \"ansfltr\", \"sbtisht\"\r\nIt checks to see if any analysis tools are running, like “VMware Tools Service”, “VMware Activation\r\nHelper”, “Metasploit Metsvc Backdoor”, and “Windump”, whose process names\r\nare \"vmtoolsd.exe\",\"vmacthlp.exe\", \"metsvc-server.exe\", and \"windump.exe\".\r\nIt determines if the current process is running in “Sandboxie” by determining whether a special Dll file has\r\nbeen loaded, and also if the current process name contains the string “sample”, “mlwr_smpl”,\r\nor“artifact.exe”. It does this because some sandbox tools may change the sample file name into them. \r\nBesides the above methods, it also checks the CPU information by calling the ASM instruction cpuid. \r\nThe constant strings that appear in the detections are decrypted. In fact, not only these strings, but also all constant\r\nstrings are encrypted by default, and they are decrypted before referring to them.\r\nAfter all the detections, the child process exits with an exit code of 1 if any of the above parameters is triggered,\r\nand with a 0 if nothing is triggered.\r\nBack to the Parent Process\r\nThe parent process can call the API GetExitCodeProcess() to obtain the exit code. When it detects that QBot is\r\nrunning in an analysis device, it does not exit the process immediately, but secretly sets a global variable. As a\r\nresult, it goes to a different code branch where it does some irrelevant things but load the core module and exit the\r\nprocess at last. I will explain this later when we reach the core module.\r\nIf it is not running in an analysis device, it continues to create a home folder under the “%AppData%\\Microsoft\\”\r\nfolder for saving QBot’s process and data. The home folder’s name is randomly generated. In my device, it is\r\n“Vhdktrbeex”. It may differ on different devices. It checks if the current QBot process is from its home folder. Of\r\ncourse, it is not for this first time, as it is in the folder “C:\\Users\\Public\\tmpdir\\”. \r\nIt then copies file1.exe into the home folder and renames it as “mavrihvu.exe”. The file name is generated from\r\nthe user name of the victim. In Figure 2.2, below, you can see the ASM code snippet to compare the two folder\r\nnames.\r\nhttps://www.fortinet.com/blog/threat-research/deep-analysis-of-a-qbot-campaign-part-1\r\nPage 5 of 13\n\nFigure 2.2. ASM code snippet of comparing home folder name.\r\nIn this code branch, it continues to load a resource named “307” from the current process. This is the core module\r\nof QBot. The string “307” is decrypted. If it detects being in an analysis device, according to the exit code from\r\nthe child process called with parameter “/C”, then the “307” string decryption will fail with no error alert. It then\r\ndoes nothing and soon exits the process. It can be treated as an anti-analysis technique.\r\nThe content of “307” is an encrypted PE file. However, it does not really load the core module “307” to perform\r\nits work here. Instead, it loads another resource, named “308”, from the decrypted “307” module. \r\nhttps://www.fortinet.com/blog/threat-research/deep-analysis-of-a-qbot-campaign-part-1\r\nPage 6 of 13\n\nFigure 2.3 Display decrypted data of “308” and decryption function\r\nFrom the decrypted data of “308”, as shown in Figure 2.3, “spx97” in “10=spx97” is the variant identification of\r\nQBot and 3=1586971769, is a unix epoch time, is the creation time of resource “307”. They are used when\r\ncommunicating with the C2 server to reveal its version. Based on that information, the C2 server determines if it\r\nneeds to be upgraded.\r\nIt then creates a file named “mavrihvu.dat” to save the encrypted configuration data. Below is its content before\r\nencryption.\r\n01AFFB60  D8 88 6C 71 57 93 A7 1D D2 B8 97 4F 1B FC C1 E3  ??lqW“§ò?—Oüá?\r\n01AFFB70  A2 D0 F7 C0 31 31 3D 32 0D 0A 31 3D 32 32 2E 34  ￠D÷à11=2..1=22.4\r\n01AFFB80  31 2E 35 37 2D 31 35  2F 30  35 2F  32 30  32 30 0D  1.57-15/05/2020.\r\n01AFFB90  0A 32  3D 31 35 38 39  36 30  37 37  31 37  0D 0A      .2=1589607717..\r\nIt contains several pieces of basic information. The first 14H bytes are the SHA1 value of the rest content, 11=2\r\nrecords the type of hard-drive, 1=22.41.57-15/05/2020 is the time and date when the QBot was installed on the\r\nvictim’s device, 2=1589607717 is the Unix time of the installation time. This “mavrihvu.dat” file will be\r\nfrequently used later to load and save other configuration data for QBot.  \r\nIt also creates a WMI (Windows Management Instrumentation) Object to execute the process of\r\n“%AppData%\\Microsoft\\Vhdktrbeex\\mavrihvu.exe” without a parameter. To do so, it calls the ConnectServer()\r\nAPI with the WMI namespace “ROOT\\\\CIMV2”, CoSetProxyBlanket(), and GetObject() with the\r\n“Win32_Process\". Finally, it calls Put() with the command line\r\n“%AppData%\\Microsoft\\Vhdktrbeex\\mavrihvu.exe” and ExecMethod() to run it. \r\nFigure 2.4 shows how the ASM code snippet calls Put() and ExecMethod().\r\nhttps://www.fortinet.com/blog/threat-research/deep-analysis-of-a-qbot-campaign-part-1\r\nPage 7 of 13\n\nFigure 2.4, WMI object to execute QBot process\r\nI think using a WMI object to run QBot is a better way than directly calling CreateProcess for protecting the\r\nprocess. As we know, the WMI object is handled by the Windows process “wmiprvse.exe”, which then executes\r\nthe mavrihvu.exe process. Below, Figure 2.5 displays a screenshot showing that the process tree starts running\r\n“file1.exe”, and that “mavrihvu.exe” is started by “wmiprvse.exe” (WMI Provider Host).\r\nhttps://www.fortinet.com/blog/threat-research/deep-analysis-of-a-qbot-campaign-part-1\r\nPage 8 of 13\n\nFigure 2.5, Process Tree\r\nI will explain in detail how “mavrihvu.exe” is started by “wmiprvse.exe” in the next section of this blog.\r\n\"file1.exe” then continues to create a one-time run task in the task schedule. It uses the command\r\n“C:\\Windows\\system32\\schtasks.exe /Create /RU \\\"NT AUTHORITY\\SYSTEM\\\" /tn qyuoeflyq /tr\r\n\\\"C:\\Users\\Public\\tmpdir\\file1.exe\\\" /I qyuoeflyq /SC ONCE /Z /ST 22:48 /ET 23:00”. The created task name is\r\n“qyuoeflyq”, which executes the command “C:\\Users\\Public\\tmpdir\\file1.exe /I qyuoeflyq”. “/I qyuoeflyq” is the\r\ncommand line parameter. The code branch then replaces the content of “file1.exe” with “calc.exe” to destroy the\r\n“file.exe” and then delete this one-time-run task of its name “qyuoeflyq” that passes with “/I”. \r\nFigure 2.6 shows that it calls the API CreateProcessW() in the “/I” handling code branch to execute commands to\r\nreplace the content of “file1.exe”.\r\nFigure 2.6, “/I” parameter handler executes a command\r\nhttps://www.fortinet.com/blog/threat-research/deep-analysis-of-a-qbot-campaign-part-1\r\nPage 9 of 13\n\nAt this point, “file1.exe”’s task is completed. It then calls the API ExitProcess() to exit the process.\r\nWMI Provider Host Executes QBot\r\nIn Figure 2.5, you can see that QBot (“mavrihvu.exe”) is started by the WMI Provider Host (“wmiprvse.exe”)\r\nwith no parameter. It performs all the work that “file1.exe” does, like checking to see if it is in an analysis device\r\n(parameter “/C”), which I explained earlier, and then checks to see if it is from its home folder,\r\n“%AppData%\\microsoft\\Vhdktrbeex\\”. This time the result is apparently yes, therefore, it will go to different\r\nbranch than where “file1.exe” goes.\r\nNext, it creates a suspended process from one of a number of common processes, including\r\n\"C:\\Windows\\explorer.exe\", \"C:\\Windows\\System32\\mobsync.exe\", and \"C:\\Program Files\\Internet\r\nExplorer\\iexplore.exe\". Which one is used depends on which one works first. QBot then moves onto the selected\r\ncommon process to execute its malicious code to protect it from being identified by the victim.  The three\r\ncommon process strings are encrypted by default.\r\nFigure 3.1, It creates suspended explorer.exe\r\nFigure 3.1 is a screenshot of when it creates “explorer.exe” with a CREATE_SUSPENDED flag. This way, QBot\r\ncan modify the memory data of “explorer.exe” and then resume its running.\r\nQBot copies its entire data from its memory into explorer.exe’s memory. To do this, it calls API\r\nZwCreateSection(), ZwMapViewOfSection(), and memcpy() to copy the data. It then reads relocation data from\r\nthe PE structure and adjusts the relocation offsets within the copied code in “explorer.exe”. Lastly, it calls the API\r\nGetThreadContext() to get the current entry point of “explorer.exe” and then modifies it so it is able to jump to the\r\ncopied QBot’s code (entry point). It then calls ResumeThread() to resume “explorer.exe” running from its entry\r\npoint. Now, with all the work of “mavrihvu.exe” with no parameter is done, it calls API ExitProcess() as exiting is\r\nthe last thing for it to do. Now, QBot is perfectly running within explorer.exe process.\r\nhttps://www.fortinet.com/blog/threat-research/deep-analysis-of-a-qbot-campaign-part-1\r\nPage 10 of 13\n\nQBot Executes in Explorer.exe\r\nThe code that runs in “explorer.exe” has a new entry point that is first called. Its main task is to load and decrypt\r\nresource “307”. It calls the APIs FindResourceA(), SizeofResource(), and LoadResource() to load resource “307”\r\ninto memory. Next, it gets the “307” data decrypted by calling a RC4 function.  Below, in Figure 4.1, is the just\r\ndecrypted data of “307”, which is a PE file.\r\nFigure 4.1, Decrypted resource “307”\r\nI dumped and analyzed the PE file. It is a Dll file, which will be the core module of QBot. It contains three\r\nresources, “308”, “310” and “311”, which are used by the core module; I’ve explained the content of “308”\r\nbefore. For others, I will walk you through their contents when they are decrypted.. Figure 4.2 shows the three\r\nresources of the dumped resource “307” in a PE analysis tool. \r\nhttps://www.fortinet.com/blog/threat-research/deep-analysis-of-a-qbot-campaign-part-1\r\nPage 11 of 13\n\nFigure 4.2, Three resources of dumped resource “307”\r\nIt continues loading each section from the “307” PE structure into newly allocated memory by calling the API\r\nVirtualAllocate(). It then goes to repair the relocation data and import the neessary APIs for getting the core\r\nmodule ready to execute in “explorer.exe”, which is the same way a PE Loader does when creating a process.\r\nThe core module’s Entry Point is called when above steps are complete. Figure 4.3 shows a snippet of ASM code\r\nto call the Entry Point that is saved in var_10.\r\nFigure 4.3, The Entry Point in var_10 of core module resource “307”is called.\r\nI’ll continue to analyze what the core module does in explorer.exe in the next part of this analysis. For example, I\r\nwill look at how QBot connects to its C2 server and what data it steals from victim’s device and sends to its C2\r\nserver.  Stay tuned.\r\nConclusion\r\nIn the first part of this report, I provided a detailed explanation of how this variant of QBot is downloaded by an\r\nOffice Word document by using a malicious Macro, and how it uses complicated techniques to hide and protect\r\nitself from being recognized by the victim.\r\nDuring my analysis, QBot kept upgrading its payload file, almost once a day. I’ll keep tracking its actions and\r\nposting more analysis for it when some new features have been added.\r\nSolution\r\nThe most common vector for delivery of these threats is email. FortiMail deployed on-premises or in the cloudcan\r\nbe used to detect malicious phishing content and can be configured to send attachments to the FortiSandbox\r\nsolution (ATP), to determine if a file displays malicious behavior. To mitigate against file based threats on PDF\r\nand Office documents, FortiMail and FortiGate support Content Disarm and Reconstruction (CDR) to remove\r\nactive threats such as QBot from these file formats.\r\nhttps://www.fortinet.com/blog/threat-research/deep-analysis-of-a-qbot-campaign-part-1\r\nPage 12 of 13\n\nFortinet customers running FortiGate and FortiMail are already protected from this QBot variant by FortiGuard’s\r\nWeb Filtering service, AntiVirus service, and CDR feature as follows:\r\nThe downloading URLs are rated as \"Malicious Websites\" by the FortiGuard Web Filtering service.\r\nThe Word document and downloaded file1.exe are detected as \"VBA/Qbot.CC!tr.dldr\" and\r\n\"W32/QBOT.CC!tr\" and blocked by the FortiGuard AntiVirus service.\r\nIOCs:\r\nURLs\r\nhxxp://pickap[.]io/wp-content/uploads/2020/04/evolving/888888.png\r\nhxxp://decons[.]vn/wp-content/uploads/2020/04/evolving/888888.png\r\nhxxp://econspiracy[.]se/evolving/888888.png\r\nhxxp://enlightened-education[.]com/wp-content/uploads/2020/04/evolving/888888.png\r\nhxxp://kslanrung[.]com/evolving/888888.png   \r\nSample SHA-256\r\n[Original Word Document]\r\n432B6D767539FD5065593B160128AA7DCE271799AD2088A82A16542E37AD92B0\r\n[file1.exe or 888888.png]\r\nD3B38681DBC87049022A3F33C9888D53713E144A277A7B825CF8D9628B9CA898\r\nReferences:\r\nhttps://malware.wikia.org/wiki/Qakbot\r\nhttps://docs.microsoft.com/en-us/powershell/scripting/samples/getting-wmi-objects--get-ciminstance-?\r\nview=powershell-7\r\nLearn more about FortiGuard Labs threat research and the FortiGuard Security Subscriptions and\r\nServices portfolio. Sign up for the weekly Threat Brief from FortiGuard Labs. \r\nLearn more about Fortinet’s free cybersecurity training initiative or about the Fortinet Network Security Expert\r\nprogram, Network Security Academy program, and FortiVet program.\r\nSource: https://www.fortinet.com/blog/threat-research/deep-analysis-of-a-qbot-campaign-part-1\r\nhttps://www.fortinet.com/blog/threat-research/deep-analysis-of-a-qbot-campaign-part-1\r\nPage 13 of 13",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"ETDA"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://www.fortinet.com/blog/threat-research/deep-analysis-of-a-qbot-campaign-part-1"
	],
	"report_names": [
		"deep-analysis-of-a-qbot-campaign-part-1"
	],
	"threat_actors": [],
	"ts_created_at": 1775434388,
	"ts_updated_at": 1775826716,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/f24003e62ba31ae8825ad3ba1a62f93ffc92f093.pdf",
		"text": "https://archive.orkl.eu/f24003e62ba31ae8825ad3ba1a62f93ffc92f093.txt",
		"img": "https://archive.orkl.eu/f24003e62ba31ae8825ad3ba1a62f93ffc92f093.jpg"
	}
}