Operation Dragon Castling: APT group targeting betting companies

When analyzing the binary Analysts discovered a potential security issue that allows an attacker to use the updater to communicate with a server controlled by the attacker to perform actions on the victim’s system, including downloading and running arbitrary executables.
To exploit the vulnerability, a registry key under HKEY_CURRENT_USER needs to be modified, and by doing this an attacker gains persistence on the system and control over the update process.
In the case Analysts analyzed, the malicious binary was downloaded from the domain update.wps[.]cn, which is a domain belonging to Kingsoft, but the serving IP ( has no relationship to the company, so Analysts assume that it is a fake update server used by the attackers.
The downloaded binary (setup_CN_2052_11.1.0.8830_PersonalDownload_Triale.exe – B9BEA7D1822D9996E0F04CB5BF5103C48828C5121B82E3EB9860E7C4577E2954) drops two files for sideloading: a signed QMSpeedupRocketTrayInjectHelper64.exe – Tencent Technology (a3f3bc958107258b3aa6e9e959377dfa607534cc6a426ee8ae193b463483c341) and a malicious DLL QMSpeedupRocketTrayStub64.dll.

The first stage is a backdoor communicating with a C&C (mirrors.centos.8788912[.]com). Before contacting the C&C server, the backdoor performs several preparational operations.
It hooks three functions: GetProcAddress, FreeLibrary, LdrUnloadDll. To get the C&C domain, it maps itself to the memory and reads data starting at the offset 1064 from the end.
The domain name is not encrypted in any way and is stored as a wide string in clear text in the binary.

Then it initializes an object for a JScript class with the named item ScriptHelper. The dropper uses the ImpersonateLoggedOnUser API Call to re-use a token from explorer.exe so it effectively runs under the same user. Additionally, it uses RegOverridePredefKey to redirect the current HKEY_CURRENT_USER to HKEY_CURRENT_USER of an impersonated user.
For communication with C&C it constructs a UserAgent string with some system information e.g. Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1;.NET CLR 2.0).
The information that is exfiltrated is: Internet Explorer version, Windows version, the value of the “User AgentPost Platform” registry values.

After that, the sample constructs JScript code to execute.
The header of the code contains definitions of two variables: server with the C&C domain name and a hardcoded key. Then it sends the HTTP GET request to /api/connect, the response should be encrypted JScript code that is decrypted, appended to the constructed header and executed using the JScript class created previously.

he second dropper is a runner that, when executed, tries to escalate privileges via the COM Session Moniker Privilege Escalation (MS17-012), then dropping a few binaries.
The encryption key is a wide string starting from offset 0x8.
The encrypted data starts at the offset 0x528.
To decrypt the data, a SHA256 hash of the key is created using CryptHashData API, and is then used with a hard-coded IV 0123456789abcde to decrypt the data using CryptDecrypt API with the AES256 algorithm.
After that, the decrypted data is decompressed with RtlDecompressBuffer.
To verify that the decryption went well, the CRC32 of the data is computed and compared to the value at the offset 0x4 of the original resource data. When all the payloads are dropped to the disk, bdservicehost.exe is executed to run the next stage.

The Loader (CoreX) DLL is sideloaded during the previous stage (Dropper 2) and acts as a dropper. Similarly to Dropper 1, it hooks the GetProcAddress and FreeLibrary API functions.
These hooks execute the main code of this library. The main code first checks whether it was loaded by regsvr32.exe and then it retrieves encrypted data from its resources. This data is dropped into the same folder as syscfg.dat. The file is then loaded and decrypted using AES-256:

– Key is the computer name and IV is qwertyui12345678
– AES-256 setup parameters are embedded in the resource in the format #. So you may e.g. see cbfc2vyuzckloknf#8o3yfn0uee429m8d.

The main code continues to check if the process ekrn.exe is running. ekrn.exe is an ESET Kernel service. If the ESET Kernel service is running, it will try to remap ntdll.dll. Analysts assume that this is used to bypass ntdll.dll hooking.

After a service check, it will decompress and execute shellcode, which in turn loads a DLL with the next stage. The DLL is stored, unencrypted, as part of the shellcode. The shellcode enumerates exports of ntdll.dll and builds an array with hashes of names of all Zw* functions (windows native API system calls) then sorts them by their RVA.
By doing this, the shellcode exploits the fact that the order of RVAs of Zw* functions equals the order of the corresponding syscalls, so an index of the Zw* function in this array is a syscall number, which can be called using the syscall instruction. Security solutions can therefore be bypassed based on the hooking of the API in userspace. Finally, the embedded core module DLL is loaded and executed.

The core module is a single DLL that is responsible for setting up the malware’s working directory, loading configuration files, updating its code, loading plugins, beaconing to C&C servers and waiting for commands.

It has a cascading structure with four steps:
The first part is dedicated to initial checks and a few evasion techniques. At first, the core module verifies that the DLL is being run by spdlogd.exe (an executable used for persistence, see below) or that it is not being run by rundll32.exe. If this check fails, the execution terminates. The DLL proceeds by hooking the GetProcAddress and FreeLibrary functions in order to execute the main function, similarly to the previous infection stages.

The malware then creates a new window (named Sample) with a custom callback function. A message with the ID 0x411 is sent to the window via SendMessageW which causes the aforementioned callback to execute the main function.
The callback function can also process the 0x412 message ID, even though no specific functionality is tied to it.

In the second step, the module tries to self-update, load configuration files and set up its working directory (WD).
The malware first looks for a file called new_version.dat – if it exists, its content is loaded into memory, executed in a new thread and a debug string “run code ok” is printed out.
Analysts did not come across this file, but based on its name and context, this is most likely a self update functionality.

Load configuration file inst.dat and set up working directory. First, the core module configuration file inst.dat is searched for in the following three locations:

the directory where the core module DLL is located
the directory where the EXE that loaded the core module DLL it is located
It contains the path to the malware’s working directory in plaintext. If it is not found, a hard-coded directory name is used and the directory is created. The working directory is a location the malware uses to drop or read any files it uses in subsequent execution phases.

Load configuration file smcache.dat.

After the working directory is set up, the sample will load the configuration file smcache.dat from it. This file contains the domains, protocols and port numbers used to communicate with C&C servers (details in Step 4) plus a “comment” string. This string is likely used to identify the campaign or individual victims.
It is used to create an empty file on the victim’s computer (see below) and it’s also sent as a part of the initial beacon when communicating with C&C servers.
Analysts refer to it as the “comment string” because Analysts have seen a few versions of smcache.dat where the content of the string was “the comment string here” and it is also present in another configuration file with the name comment.dat which has the INI file format and contains this string under the key COMMENT.

Create a log file

Right after the sample finds and reads smcache.dat, it creates a file based on the victim’s username and the comment string from smcache.dat. If the comment string is not present, it will use a default hard-coded value (for example M86_99.lck). Based on the extension it could be a log of some sort, but Analysts haven’t seen any part of the malware writing into it so it could just serve as a lockfile. After the file is successfully created, the malware creates a mutex and goes on to the next step.

Next, the malware collects information about the infected environment (such as username, DNS and NetBios computer names as well as OS version and architecture) and sets up its internal structures, most notably a list of “call objects”. Call objects are structures each associated with a particular function and saved into a “dispatcher” structure in a map with hard-coded 4-byte keys.
These keys are later used to call the functions based on commands from C&C servers.

The key values (IDs) seem to be structured, where the first three bytes are always the same within a given sample, while the last byte is always the same for a given usage across all the core module samples that were seen.
For example, the function that calls the RevertToSelf function is identified by the number 0x20210326 in some versions of the core module that were seen and 0x19181726 in others.
This suggests that the first three bytes of the ID number are tied to the core module version, or more likely the infrastructure version, while the last byte is the actual ID of a function.

While initializing the call objects the core module also tries to connect to the URL hxxps://dav.jianguoyun.com/dav/ with the username 12121jhksdf and password 121121212 by calling WNetAddConnection3W.
This address was not responsive at the time of analysis but jianguoyun[.]com is a Chinese file sharing service. Our hypothesis is that this is either a way to get plugin code or an updated version of the core module itself.

The core module contains a function that receives a buffer with plugin DLL data, saves it into a file with the name kbg.dat in the malware working directory, loads it into memory and then calls its exported function InitCorePlug.
The plugin file on disk is set to be deleted on reboot by calling MoveFileExW with the parameter MOVEFILE_DELAY_UNTIL_REBOOT. For more information about the plugins, see the dedicated Plugins section.

In the final step, the malware will iterate over C&C servers contained in the smcache.dat configuration file and will try to reach each one. The structure of the smcache.dat config file.
The protocol string can have one of nine possible values:

Depending on the protocol tied to the particular C&C domain, the malware sets up the connection, sends a beacon to the C&C and waits for commands.

When using the HTTP protocol, the core module first opens two persistent request handles – one for POST and one for GET requests, both to “/connect”. These handles are tested by sending an empty buffer in the POST request and checking the HTTP status code of the GET request.
Following this, the malware sends the initial beacon to the C&C server by calling the InternetWriteFile API with the previously opened POST request handle and reads data from the GET request handle by calling InternetReadFile.

The core module uses the following (mostly hard-coded) HTTP headers:

Accept: */*
x-cid: {} – new uuid is generated for each GET/POST request pair
Pragma: no-cache
Cache-control: no-transform
User-Agent: – generated from registry or hard-coded (see below)
Host: – C&C server domain or the value from hostcfg.dat (see below)
Connection: Keep-Alive
Content-Length: 4294967295 (max uint, only in the POST request)
User-Agent header

The User-Agent string is constructed from the registry the same way as in the Dropper 1 module (including the logged-on user impersonation when accessing registry) or a hard-coded string is used if the registry access fails: “Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)”.

When setting up this header, the malware looks for either a resource with the ID 1816 or a file called hostcfg.dat if the resource is not found. If the resource or file is found, the content is used as the value in the Host HTTP header for all C&C communication instead of the C&C domain found in smcache.dat.
It does not change the actual C&C domain to which the request is made – this suggests the possibility of the C&C server being behind a reverse proxy.

Initial beacon

The first data packet the malware sends to a C&C server contains a base64 encoded LZNT1-compressed buffer, including a newly generated uuid (different from the uuid used in the x-cid header), the victim’s username, OS version and architecture, computer DNS and BIOS names and the comment string found in smcache.dat or comment.dat. The value from comment.dat takes precedence if this file exists.

In the core module sample Analysts analyzed, there was actually a typo in the function that reads the value from comment.dat – it looks for the key “COMMNET” instead of “COMMENT”.

After this, the malware enters a loop waiting for commands from the C&C server in the form of the ID value of one of the call objects.
Each message sent to the C&C server contains a hard-coded four byte number value with the same structure as the values used as keys in the call-object map. The ID numbers associated with messages sent to C&C servers.

Analysts came across samples of the core module with only cleartext strings but also samples with certain strings obfuscated by XORing them with a unique (per sample) hard-coded key.

Even within the samples that contain obfuscated strings, there are many cleartext strings present and there seems to be no logic in deciding which string will be obfuscated and which won’t. For example, most format strings are obfuscated, but important IoCs such as credentials or filenames are not.

To illustrate this: most strings in the function that retrieves a value from the comment.dat file are obfuscated and the call to GetPrivateProfileStringW is dynamically resolved by the GetProcAddress API, but all the strings in the function that writes into the same config file are in cleartext and there is a direct call to WritePrivateProfileStringW.

Overall, the core module code is quite robust and contains many failsafes and options for different scenarios (for example, the amount of possible protocols used for C&C communication), however, Analysts probably only saw samples of this malware that are still in active development as there are many functions that are not yet implemented and only serve as placeholders.

In the section below, Analysts will describe the functionality of the plugins used by the Core Module (Proto8) to extend its functionality.

Analysts are going to describe three plugins with various functionalities, such as:

Achieving persistence
Bypassing UAC
Registering an RPC interface
Creating a new account
Backdoor capabilities
Core Plugin

This plugin is a DLL binary loaded by the fileless core module (Proto8) as mentioned above. It extends the malware’s functionality by adding methods for managing additional plugins. These additional plugins export the function “GetPlugin” which the core plugin executes.

This part uses the same command ID based calling convention.
All plugin binaries used by the core module are stored in the working directory under the name kbg.dat.


The DLL Analysts call Zload is an example of a plugin loaded by the Core Plugin. It exports four functions: “GetPlugin”, “Install”, “core_zload” and “zload”. The main functionality of this plugin is setting up persistence, creating a backdoor user account, and concealing itself on the infected system. Analysts will focus on the exported functions zload, core_zload and the default DllMain function, as they contain the most interesting functionality.

Zload (process starter)
This function is fairly simple, its main objective is to execute another binary. It first retrieves the path to the directory where the Zload plugin binary is located () and creates a new subfolder called “mec” in it. After this it renames and moves three files into it:

the Zload plugin binary itself as meclogexts.dll,
spdlogd.exe as mecspdagent.exe and
kb.ini as meckb.ini
After the files are renamed and moved, it creates a new process by executing the binary mecspdagent.exe (originally spdlogd.exe).

core_zload (persistence setup)
This function is responsible for persistence which it achieves by registering itself into the list of security support providers (SSPs). Windows SSP DLLs are loaded into the Local Security Authority (LSA) process when the system boots. The code of this function is notably similar to the mimikat_ssp/AddSecurityPackage_RawRPC source code found on github.

DllMain (sideloading, setup)
The default DllMain function leverages several persistence and evasion techniques. It also allows the attacker to create a backdoor account on the infected system and lower the overall system security.

The plugin first checks if its DLL was loaded either by the processes “lsass.exe” or “spdagent.exe”. If the DLL was loaded by “spdagent.exe”, it will adjust the token privileges of the current process.

If it was loaded by “lsass.exe”, it will retrieve the path “kb.dll” from the configuration file “kb.ini” and write it under the registry key HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WinSock2\Parameters AutodialDLL. This ensures persistence, as it causes the DLL “kb.dll” to be loaded each time the Winsock 2 library (ws2_32.dll) is invoked.

To avoid detection, the plugin first checks the list of running processes for “avp.exe” (Kaspersky Antivirus) or “NortonSecurity.exe” and exits if either of them is found. If these processes are not found on the system, it goes on to conceal itself by changing its own process name to “explorer.exe”.

The plugin also has the capability to bypass the UAC mechanisms and to elevate its process privileges through CMSTP COM interfaces, such as CMSTPLUA {3E5FC7F9-9A51-4367-9063-A120244FBEC7}.

Backdoor user account creation
Next, the plugin carries out registry manipulation (details can be found in the appendix), that lowers the system’s protection by:

Allowing local accounts to have full admin rights when they are authenticating via network logon
Enabling RDP connections to the machine without the user password
Disabling admin approval on an administrator account, which means that all applications run with full administrative privileges
Enabling anonymous SID to be part of the everyone group in Windows
Allowing “Null Session” users to list users and groups in the domain
Allowing “Null Session” users to access shared folders
Setting the name of the pipe that will be accessible to “Null Session” users
After this step, the plugin changes the WebClient service startup type to “Automatic”. It creates a new user with the name “DefaultAccount” and the password “Admin@1999!” which is then added to the “Administrator” and “Remote Desktop Users” groups. It also hides the new account on the logon screen.

As the last step, the plugin checks the list of running processes for process names “360tray.exe” and “360sd.exe” and executes the file “spdlogd.exe” if neither of them is found.


MecGame is another example of a plugin that can be loaded by the Core Plugin. Its main purpose is similar to the previously described Zload plugin – it executes the binary “spdlogd.exe” and achieves persistence by registering an RPC interface with UUID {1052E375-2CE2-458E-AA80-F3B7D6EA23AF}. This RPC interface represents a function that decodes and executes a base64 encoded shellcode.

The MecGame plugin has several methods for executing spdlogd.exe depending on the level of available privileges. It also creates a lockfile with the name MSSYS.lck or -XPS.lck depending on the name of the process that loaded it, and deletes the files atomxd.dll and logexts.dll.

It can be installed as a service with the service name “inteloem” or can be loaded by any executable that connects to the internet via the Winsock2 library.


This DLL is a backdoor module which exports four functions: “OperateRoutineW”, “StartRoutineW”, “StopRoutineW” and “WorkRoutineW”; the main malicious function being “StartRoutineW”.

For proper execution, the backdoor needs configuration data accessed through a shared object with the file mapping name either “Global\4ED8FD41-2D1B-4CC3-B874-02F0C60FF9CB” or “Local\4ED8FD41-2D1B-4CC3-B874-02F0C60FF9CB”. Unfortunately Analysts didn’t come across the configuration data, so Analysts are missing some information such as the C&C server domains this module uses.

There are 15 commands supported by this backdoor (although some of them are not implemented).

Communication protocol
The MulCom backdoor is capable of communicating via HTTP and TCP protocols. The data it exchanges with the C&C servers is encrypted and compressed by the RC4 and aPack algorithms respectively, using the RC4 key loaded from the configuration data object.

It is also capable of proxy server authentication using schemes such as Basic, NTLM, Negotiate or to authenticate via either the SOCKS4 and SOCKS5 protocols.

Sign Up For Threat Alerts

Threats Icon

Jul 04, 2023

Rhysida Ransomware RaaS Crawls Out of Crimeware...

The Rhysida ransomware-as-a-service (RaaS) group has gone from a dubious newcomer to a fully-fledged ransomware...

Threats Icon

Jun 26, 2023

Operation Magalenha – Long-Running Campaign Pursues Portuguese...

The attackers can steal credentials and exfiltrate users' data and personal information, which can be...

Threats Icon

Apr 24, 2023

Lazarus Group Adds Linux Malware to Arsenal...

Researchers have discovered a new campaign conducted by Lazarus, known as "Operation DreamJob," which targets...

Threats Icon

Apr 23, 2023

Additional IOCs for 3cx breach

Recently an unexpected malicious activity emanating from a legitimate, signed binary, 3CXDesktopApp was observed.

Threats Icon

Apr 23, 2023

Ex-Conti and FIN7 Actors Collaborate with New...

IBM Security X-Force recently discovered a new malware family Analysts have called "Domino," which Analysts...

Threats Icon

Apr 20, 2023

AuKill EDR killer malware abuses Process Explorer...

The AuKill tool abuses an outdated version of the driver used by version 16.32 of...

Threats Icon

Apr 20, 2023

Fake Chrome updates spread malware

A campaign running since the end of last year is using hacked sites to push...

Threats Icon

Apr 20, 2023

QBot using new attack vector in its...

QBot, also known as QakBot, previously operated as a banking trojan and has since transformed...

Threats Icon

Apr 20, 2023

CrossLock Ransomware Emerges: New Golang – Based...

The CrossLock ransomware employs the double extortion technique to increase the likelihood of payment from...

Threats Icon

Apr 20, 2023

Windows Zero-Day Vulnerability CVE-2023-28252 Exploited by Nokoyawa...

A zero-day vulnerability in the Microsoft Windows system, which also affects Windows 11, has been...

Threats Icon

Apr 18, 2023

Additional IOcs for 3cx breach

Recently an unexpected malicious activity emanating from a legitimate, signed binary, 3CXDesktopApp was observed. As...

Threats Icon

Apr 18, 2023

Additional IOcs for 3cx breach

Recently an unexpected malicious activity emanating from a legitimate, signed binary, 3CXDesktopApp was observed. As...

Threats Icon

Apr 18, 2023

APT36 Expands Interest Within Indian Education Sector

Symantec described UPS in 2016 report as Buckeye (also known as APT3 Gothic Panda UPS...

Threats Icon

Apr 17, 2023

ChinaZ DDoS Bot Malware Distributed To Linux...

The ChinaZ DDoS bot malware was discovered targeting Linux systems while a version for Microsoft...

Threats Icon

Apr 16, 2023

Resurgence Of The Mexals Cryptojacking Campaign

The Mexals crypto jacking campaign has been in operation since at least 2021 and continues...