{
	"id": "92490394-6cf3-49bb-bed3-43f8c69c9507",
	"created_at": "2026-04-06T00:16:00.877529Z",
	"updated_at": "2026-04-10T13:12:23.687988Z",
	"deleted_at": null,
	"sha1_hash": "e5b8f3c54fa97e2e574428b3f16526afa2cbaca4",
	"title": "Operation Dragon Castling: APT group targeting betting companies",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 3125481,
	"plain_text": "Operation Dragon Castling: APT group targeting betting\r\ncompanies\r\nBy Threat Research TeamThreat Research Team\r\nArchived: 2026-04-05 18:40:41 UTC\r\nIntroduction\r\nWe recently discovered an APT campaign we are calling Operation Dragon Castling . The campaign is\r\ntargeting what appears to be betting companies in South East Asia , more specifically companies located in\r\nTaiwan , the Philippines , and Hong Kong . With moderate confidence, we can attribute the campaign to a\r\nChinese speaking APT group , but unfortunately cannot attribute the attack to a specific group and are not sure\r\nwhat the attackers are after.\r\nWe found notable code similarity between one of the modules used by this APT group (the MulCom backdoor )\r\nand the FFRat samples described by the BlackBerry Cylance Threat Research Team in their 2017 report and\r\nPalo Alto Networks in their 2015 report. Based on this, we suspect that the FFRat codebase is being shared\r\nbetween several Chinese adversary groups. Unfortunately, this is not sufficient for attribution as FFRat itself was\r\nnever reliably attributed.\r\nIn this blogpost we will describe the malware used in these attacks and the backdoor planted by the APT group, as\r\nwell as other malicious files used to gain persistence and access to the infected machines. We will also discuss the\r\ntwo infection vectors we saw being used to deliver the malware: an infected installer and exploitation of a\r\nvulnerable legitimate application, WPS Office .\r\nWe identified a new vulnerability (CVE-2022-24934) in the WPS Office updater wpsupdate.exe, which we\r\nsuspect that the attackers abused.\r\nWe would like to thank Taiwan’s TeamT5 for providing us with IoCs related to the infection vector.\r\nIn the diagram above, we describe the relations between the malicious files. Some of the relations might not be\r\naccurate, e.g. we are not entirely sure if the MulCom backdoor is loaded by the CorePlugin . However, we\r\nhttps://decoded.avast.io/luigicamastra/operation-dragon-castling-apt-group-targeting-betting-companies\r\nPage 1 of 17\n\nstrongly believe that it is one of the malicious files used in this campaign. \r\nInfection Vector\r\nWe’ve seen multiple infection vectors used in this campaign. Among others, an attacker sent an email with an\r\ninfected installer to the support team of one of the targeted companies asking to check for a bug in their software.\r\nIn this post, we are going to describe another vector we’ve seen: a fake WPS Office update package. We suspect\r\nan attacker exploited a bug in the WPS updater wpsupdate.exe , which is a part of the WPS Office installation\r\npackage. We have contacted WPS Office team about the vulnerability ( CVE-2022-24934 ), which we discovered,\r\nand it has since been fixed.\r\nDuring our investigation we saw suspicious behavior in the WPS updater process. When analyzing the binary we\r\ndiscovered a potential security issue that allows an attacker to use the updater to communicate with a server\r\ncontrolled by the attacker to perform actions on the victim’s system, including downloading and running arbitrary\r\nexecutables. To exploit the vulnerability, a registry key under HKEY_CURRENT_USER needs to be modified, and by\r\ndoing this an attacker gains persistence on the system and control over the update process. In the case we\r\nanalyzed, the malicious binary was downloaded from the domain update.wps[.]cn , which is a domain\r\nbelonging to Kingsoft , but the serving IP ( 103.140.187.16 ) has no relationship to the company, so we assume\r\nthat it is a fake update server used by the attackers. \r\nThe downloaded binary ( setup_CN_2052_11.1.0.8830_PersonalDownload_Triale.exe -\r\nB9BEA7D1822D9996E0F04CB5BF5103C48828C5121B82E3EB9860E7C4577E2954 ) drops two files for sideloading: a signed\r\nQMSpeedupRocketTrayInjectHelper64.exe - Tencent Technology\r\n(a3f3bc958107258b3aa6e9e959377dfa607534cc6a426ee8ae193b463483c341) and a malicious DLL\r\nQMSpeedupRocketTrayStub64.dll.\r\nDropper 1 (QMSpeedupRocketTrayStub64.dll)\r\n76adf4fd93b70c4dece4b536b4fae76793d9aa7d8d6ee1750c1ad1f0ffa75491\r\nThe first stage is a backdoor communicating with a C\u0026C ( mirrors.centos.8788912[.]com ). Before contacting\r\nthe C\u0026C server, the backdoor performs several preparational operations. It hooks three functions:\r\nGetProcAddress , FreeLibrary , LdrUnloadDll . To get the C\u0026C domain, it maps itself to the memory and\r\nreads data starting at the offset 1064 from the end. The domain name is not encrypted in any way and is stored\r\nas a wide string in clear text in the binary. \r\nThen it initializes an object for a JScript class with the named item ScriptHelper .  The dropper uses the\r\nImpersonateLoggedOnUser API Call to re-use a token from explorer.exe so it effectively runs under the same\r\nuser. Additionally, it uses RegOverridePredefKey to redirect the current HKEY_CURRENT_USER to\r\nHKEY_CURRENT_USER of an impersonated user. For communication with C\u0026C it constructs a UserAgent string\r\nwith some system information e.g. Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1;.NET CLR 2.0). The\r\ninformation that is exfiltrated is: Internet Explorer version, Windows version, the value of the “User\r\nAgent\\Post Platform” registry values.\r\nhttps://decoded.avast.io/luigicamastra/operation-dragon-castling-apt-group-targeting-betting-companies\r\nPage 2 of 17\n\nAfter that, the sample constructs JScript code to execute. The header of the code contains definitions of two\r\nvariables: server with the C\u0026C domain name and a hardcoded key . Then it sends the HTTP GET request to\r\n/api/connect, the response should be encrypted JScript code that is decrypted, appended to the constructed\r\nheader and executed using the JScript class created previously.\r\nAt the time of analysis, the C\u0026C was not responding, but from the telemetry data we can conclude that it was\r\ndownloading the next stage from\r\nhxxp://mirrors.centos.8788912.com/upload/ea76ad28a3916f52a748a4f475700987.exe to\r\n%ProgramData%\\icbc_logtmp.exe and executing it.\r\nDropper 2 (IcbcLog)\r\na428351dcb235b16dc5190c108e6734b09c3b7be93c0ef3d838cf91641b328b3\r\nThe second dropper is a runner that, when executed, tries to escalate privileges via the COM Session Moniker\r\nPrivilege Escalation ( MS17-012 ) , then dropping a few binaries, which are stored with the following\r\nresource IDs:\r\nThe encrypted payloads have the following structure:\r\nThe encryption key is a wide string starting from offset 0x8 . The encrypted data starts at the offset 0x528 . To\r\ndecrypt 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\r\nthat, the decrypted data is decompressed with RtlDecompressBuffer . To verify that the decryption went well, the\r\nCRC32 of the data is computed and compared to the value at the offset 0x4 of the original resource data. When\r\nall the payloads are dropped to the disk, bdservicehost.exe is executed to run the next stage.\r\nLoader (CoreX)\r\n97c392ca71d11de76b69d8bf6caf06fa3802d0157257764a0e3d6f0159436c42\r\nThe Loader (CoreX) DLL is sideloaded during the previous stage (Dropper 2) and acts as a dropper.\r\nSimilarly to Dropper 1 , it hooks the GetProcAddress and FreeLibrary API functions. These hooks execute\r\nthe main code of this library. The main code first checks whether it was loaded by regsvr32.exe and then it\r\nretrieves encrypted data from its resources. This data is dropped into the same folder as syscfg.dat . The file is\r\nthen loaded and decrypted using AES-256 with the following options for setup:\r\nhttps://decoded.avast.io/luigicamastra/operation-dragon-castling-apt-group-targeting-betting-companies\r\nPage 3 of 17\n\nKey is the computer name and IV is qwertyui12345678\r\nAES-256 setup parameters are embedded in the resource in the format \u003ckey\u003e#\u003cIV\u003e . So you may e.g. see\r\ncbfc2vyuzckloknf#8o3yfn0uee429m8d\r\nAES-256 setup parameters\r\nThe main code continues to check if the process ekrn.exe is running. ekrn.exe is an ESET Kernel service. If\r\nthe ESET Kernel service is running, it will try to remap ntdll.dll . We assume that this is used to bypass\r\nntdll.dll hooking. \r\nAfter a service check, it will decompress and execute shellcode, which in turn loads a DLL with the next stage.\r\nThe DLL is stored, unencrypted, as part of the shellcode. The shellcode enumerates exports of ntdll.dll and\r\nbuilds an array with hashes of names of all Zw* functions (windows native API system calls) then sorts them by\r\ntheir RVA. By doing this, the shellcode exploits the fact that the order of RVAs of Zw* functions equals the order\r\nof the corresponding syscalls, so an index of the Zw* function in this array is a syscall number, which can be\r\ncalled using the syscall instruction. Security solutions can therefore be bypassed based on the hooking of the API\r\nin userspace. Finally, the embedded core module DLL is loaded and executed.\r\nProto8 (Core module)\r\nf3ed09ee3fe869e76f34eee1ef974d1b24297a13a58ebff20ea4541b9a2d86c7\r\nThe core module is a single DLL that is responsible for setting up the malware’s working directory, loading\r\nconfiguration files, updating its code, loading plugins, beaconing to C\u0026C servers and waiting for commands.\r\nIt has a cascading structure with four steps:\r\nStep 1\r\nThe first part is dedicated to initial checks and a few evasion techniques. At first, the core module verifies that the\r\nDLL is being run by spdlogd.exe (an executable used for persistence, see below) or that it is not being run by\r\nrundll32.exe. If this check fails, the execution terminates. The DLL proceeds by hooking the GetProcAddress\r\nand FreeLibrary functions in order to execute the main function, similarly to the previous infection stages.\r\nThe GetProcAddress hook contains an interesting debug output “in googo”.\r\nhttps://decoded.avast.io/luigicamastra/operation-dragon-castling-apt-group-targeting-betting-companies\r\nPage 4 of 17\n\nThe malware then creates a new window (named Sample ) with a custom callback function. A message with the\r\nID 0x411 is sent to the window via SendMessageW which causes the aforementioned callback to execute the\r\nmain function. The callback function can also process the 0x412 message ID, even though no specific\r\nfunctionality is tied to it.\r\nExported function Core2 sends message 0x411\r\nExported function Ldr2 sends message 0x412\r\nThe window callback only contains implementation for message 0x411 but there is a check for 0x412 as well\r\nStep 2\r\nIn the second step, the module tries to self-update, load configuration files and set up its working directory (WD).\r\nhttps://decoded.avast.io/luigicamastra/operation-dragon-castling-apt-group-targeting-betting-companies\r\nPage 5 of 17\n\nSelf-update\r\nThe malware first looks for a file called new_version.dat – if it exists, its content is loaded into memory,\r\nexecuted in a new thread and a debug string “run code ok” is printed out. We did not come across this file, but\r\nbased on its name and context, this is most likely a self update functionality.\r\nLoad configuration file inst.dat and set up working directory. First, the core module configuration file inst.dat\r\nis searched for in the following three locations:\r\nthe directory where the core module DLL is located\r\nthe directory where the EXE that loaded the core module DLL it is located\r\nC:\\ProgramData\\\r\nIt contains the path to the malware’s working directory in plaintext. If it is not found, a hard-coded directory name\r\nis used and the directory is created. The working directory is a location the malware uses to drop or read any files\r\nit uses in subsequent execution phases.\r\nLoad configuration file smcache.dat .\r\nAfter the working directory is set up, the sample will load the configuration file smcache.dat from it. This file\r\ncontains the domains, protocols and port numbers used to communicate with C\u0026C servers (details in Step 4) plus\r\na “comment” string. This string is likely used to identify the campaign or individual victims. It is used to create\r\nan empty file on the victim’s computer (see below) and it’s also sent as a part of the initial beacon when\r\ncommunicating with C\u0026C servers. We refer to it as the “comment string” because we have seen a few versions\r\nof smcache.dat where the content of the string was “the comment string here” and it is also present in another\r\nconfiguration file with the name comment.dat which has the INI file format and contains this string under the\r\nkey COMMENT.\r\nCreate a log file\r\nhttps://decoded.avast.io/luigicamastra/operation-dragon-castling-apt-group-targeting-betting-companies\r\nPage 6 of 17\n\nRight after the sample finds and reads smcache.dat, it creates a file based on the victim’s username and the\r\ncomment string from smcache.dat. If the comment string is not present, it will use a default hard-coded value (for\r\nexample M86_99.lck ). Based on the extension it could be a log of some sort, but we haven’t seen any part of the\r\nmalware writing into it so it could just serve as a lockfile. After the file is successfully created, the malware\r\ncreates a mutex and goes on to the next step.\r\nStep 3\r\nNext, the malware collects information about the infected environment (such as username, DNS and NetBios\r\ncomputer names as well as OS version and architecture) and sets up its internal structures, most notably a list of\r\n“call objects” . Call objects are structures each associated with a particular function and saved into a\r\n“dispatcher” structure in a map with hard-coded 4-byte keys. These keys are later used to call the functions\r\nbased on commands from C\u0026C servers. \r\nThe key values (IDs) seem to be structured, where the first three bytes are always the same within a given sample,\r\nwhile the last byte is always the same for a given usage across all the core module samples that we’ve seen. For\r\nexample, the function that calls the RevertToSelf function is identified by the number 0x20210326 in some\r\nversions of the core module that we’ve seen and 0x19181726 in others. This suggests that the first three bytes of\r\nthe ID number are tied to the core module version, or more likely the infrastructure version, while the last byte is\r\nthe actual ID of a function. \r\nWebdav \r\nWhile initializing the call objects the core module also tries to connect to the URL\r\nhxxps://dav.jianguoyun.com/dav/ with the username 12121jhksdf and password 121121212 by calling\r\nWNetAddConnection3W . This address was not responsive at the time of analysis but jianguoyun[.]com is a\r\nChinese file sharing service. Our hypothesis is that this is either a way to get plugin code or an updated version of\r\nthe core module itself.\r\nPlugins\r\nThe core module contains a function that receives a buffer with plugin DLL data, saves it into a file with the name\r\nkbg\u003ctick_count\u003e.dat in the malware working directory, loads it into memory and then calls its exported\r\nfunction InitCorePlug . The plugin file on disk is set to be deleted on reboot by calling MoveFileExW with the\r\nparameter MOVEFILE_DELAY_UNTIL_REBOOT . For more information about the plugins, see the dedicated Plugins\r\nsection.\r\nStep 4\r\nhttps://decoded.avast.io/luigicamastra/operation-dragon-castling-apt-group-targeting-betting-companies\r\nPage 7 of 17\n\nIn the final step, the malware will iterate over C\u0026C servers contained in the smcache.dat configuration file and\r\nwill try to reach each one. The structure of the smcache.dat config file is as follows:\r\nThe structure of the smcache.dat config file\r\nThe protocol string can have one of nine possible values: \r\nTCP\r\nHTTPS\r\nUDP\r\nDNS\r\nICMP\r\nHTTPSIPV6\r\nWEB\r\nSSH\r\nHTTP\r\nDepending on the protocol tied to the particular C\u0026C domain, the malware sets up the connection, sends a beacon\r\nto the C\u0026C and waits for commands.\r\nIn this blogpost, we will mainly focus on the HTTP protocol option as we’ve seen it being used by the attackers.\r\nhttps://decoded.avast.io/luigicamastra/operation-dragon-castling-apt-group-targeting-betting-companies\r\nPage 8 of 17\n\nWhen using the HTTP protocol, the core module first opens two persistent request handles – one for POST and\r\none for GET requests, both to “/connect” . These handles are tested by sending an empty buffer in the POST\r\nrequest and checking the HTTP status code of the GET request. Following this, the malware sends the initial\r\nbeacon to the C\u0026C server by calling the InternetWriteFile API with the previously opened POST request\r\nhandle and reads data from the GET request handle by calling InternetReadFile .\r\nHTTP packet order\r\nHTTP POST beacon\r\nThe core module uses the following (mostly hard-coded) HTTP headers:\r\nAccept: */*\r\nx-cid: {\u003cuuid\u003e} – new uuid is generated for each GET/POST request pair\r\nPragma: no-cache\r\nCache-control: no-transform\r\nUser-Agent: \u003cuser_agent\u003e – generated from registry or hard-coded (see below)\r\nHost: \u003chost_value\u003e – C\u0026C server domain or the value from hostcfg.dat (see below)\r\nConnection: Keep-Alive\r\nContent-Length: 4294967295 (max uint, only in the POST request)\r\nUser-Agent header\r\nThe User-Agent string is constructed from the registry the same way as in the Dropper 1 module (including the\r\nlogged-on user impersonation when accessing registry) or a hard-coded string is used if the registry access fails:\r\n“Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727;\r\n.NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)” .\r\nHost header\r\nWhen setting up this header, the malware looks for either a resource with the ID 1816 or a file called\r\nhostcfg.dat if the resource is not found. If the resource or file is found, the content is used as the value in the\r\nHost HTTP header for all C\u0026C communication instead of the C\u0026C domain found in smcache.dat . It does not\r\nchange the actual C\u0026C domain to which the request is made – this suggests the possibility of the C\u0026C server\r\nbeing behind a reverse proxy.\r\nhttps://decoded.avast.io/luigicamastra/operation-dragon-castling-apt-group-targeting-betting-companies\r\nPage 9 of 17\n\nInitial beacon\r\nThe first data packet the malware sends to a C\u0026C server contains a base64 encoded LZNT1-compressed buffer,\r\nincluding a newly generated uuid (different from the uuid used in the x-cid header), the victim’s username, OS\r\nversion and architecture, computer DNS and BIOS names and the comment string found in smcache.dat or\r\ncomment.dat . The value from comment.dat takes precedence if this file exists. \r\nIn the core module sample we analyzed, there was actually a typo in the function that reads the value from\r\ncomment.dat – it looks for the key “COMMNET” instead of “COMMENT” .\r\nAfter this, the malware enters a loop waiting for commands from the C\u0026C server in the form of the ID value of\r\none of the call objects.\r\nEach message sent to the C\u0026C server contains a hard-coded four byte number value with the same structure as the\r\nvalues used as keys in the call-object map. The ID numbers associated with messages sent to C\u0026C servers that\r\nwe’ve seen are:\r\nInteresting observations about the protocols, other than the HTTP protocol:\r\nHTTPS does not use persistent request handles\r\nHTTPS uses HTTP GET request with data Base64-encoded in the cookie header to send the initial beacon\r\nHTTPS, TCP and UDP use a custom “magic” header: Magic-Code: hhjjdfgh\r\nGeneral observations on the core module\r\nThe core samples we observed often output debug strings via OutputDebugStringA and OutputDebugStringW\r\nor by sending them to the C\u0026C server. Examples of debug strings used by the core module are: its filepath at the\r\nbeginning of execution, “run code ok” after self-update, “In googo” in the hook of GetProcAddress , “recv\r\nbomb” and “sent bomb” in the main C\u0026C communicating function, etc.\r\nString obfuscation\r\nWe came across samples of the core module with only cleartext strings but also samples with certain strings\r\nobfuscated by XORing them with a unique (per sample) hard-coded key. \r\nEven within the samples that contain obfuscated strings, there are many cleartext strings present and there seems\r\nto be no logic in deciding which string will be obfuscated and which won’t. For example, most format strings are\r\nhttps://decoded.avast.io/luigicamastra/operation-dragon-castling-apt-group-targeting-betting-companies\r\nPage 10 of 17\n\nobfuscated, but important IoCs such as credentials or filenames are not. \r\nTo illustrate this: most strings in the function that retrieves a value from the comment.dat file are obfuscated and\r\nthe call to GetPrivateProfileStringW is dynamically resolved by the GetProcAddress API, but all the strings\r\nin the function that writes into the same config file are in cleartext and there is a direct call to\r\nWritePrivateProfileStringW . \r\nOverall, the core module code is quite robust and contains many failsafes and options for different scenarios (for\r\nexample, the amount of possible protocols used for C\u0026C communication), however, we probably only saw\r\nsamples of this malware that are still in active development as there are many functions that are not yet\r\nimplemented and only serve as placeholders.\r\nPlugins\r\nIn the section below, we will describe the functionality of the plugins used by the Core Module (Proto8) to\r\nextend its functionality. \r\nWe are going to describe three plugins with various functionalities, such as:\r\nAchieving persistence\r\nBypassing UAC\r\nRegistering an RPC interface\r\nCreating a new account\r\nBackdoor capabilities\r\nCore Plugin\r\n0985D65FA981ABD57A4929D8ECD866FC72CE8C286BA9EB252CA180E280BD8755\r\nThis plugin is a DLL binary loaded by the fileless core module ( Proto8 ) as mentioned above. It extends the\r\nmalware’s functionality by adding methods for managing additional plugins. These additional plugins  export the\r\nfunction \"GetPlugin\" which the core plugin executes.\r\nThis part uses the same command ID based calling convention as the core module (see above), adding three new\r\nmethods:\r\nAll plugin binaries used by the core module are stored in the working directory under the name\r\nkbg\u003ctick_count\u003e.dat . After the Core Plugin is loaded, it first removes all plugins from the working directory –\r\nsee the image below.\r\nhttps://decoded.avast.io/luigicamastra/operation-dragon-castling-apt-group-targeting-betting-companies\r\nPage 11 of 17\n\nZload(Atomx.dll,xps1.dll)\r\n2ABC43865E49F8835844D30372697FDA55992E5A6A13808CFEED1C37BA8F7876\r\nThe DLL we call Zload is an example of a plugin loaded by the Core Plugin . It exports four functions:\r\n“GetPlugin” , “Install” , “core_zload” and ”zload” . The main functionality of this plugin is setting up\r\npersistence, creating a backdoor user account, and concealing itself on the infected system. We will focus on the\r\nexported functions zload , core_zload and the default DllMain function, as they contain the most interesting\r\nfunctionality.\r\nZload (process starter)\r\nThis function is fairly simple, its main objective is to execute another binary. It first retrieves the path to the\r\ndirectory where the Zload plugin binary is located (\u003croot_folder\u003e) and creates a new subfolder called\r\n\"mec\" in it. After this it renames and moves three files into it:\r\nthe Zload plugin binary itself as \u003croot_folder\u003e\\mec\\logexts.dll ,\r\n\u003croot_folder\u003e\\spdlogd.exe as \u003croot_folder\u003e\\mec\\spdagent.exe and\r\n\u003croot_folder\u003e\\kb.ini as \u003croot_folder\u003e\\mec\\kb.ini\r\nAfter the files are renamed and moved, it creates a new process by executing the binary\r\n\u003croot_folder\u003e\\mec\\spdagent.exe (originally \u003croot_folder\u003e\\spdlogd.exe ).\r\ncore_zload (persistence setup)\r\nThis function is responsible for persistence which it achieves by registering itself into the list of security support\r\nproviders (SSPs). Windows SSP DLLs are loaded into the Local Security Authority (LSA) process when the\r\nsystem boots. The code of this function is notably similar to the mimikat_ssp/AddSecurityPackage_RawRPC\r\nsource code found on github.\r\nDllMain (sideloading, setup)\r\nThe default DllMain function leverages several persistence and evasion techniques. It also allows the attacker to\r\ncreate a backdoor account on the infected system and lower the overall system security.\r\nPersistence\r\nhttps://decoded.avast.io/luigicamastra/operation-dragon-castling-apt-group-targeting-betting-companies\r\nPage 12 of 17\n\nThe plugin first checks if its DLL was loaded either by the processes “lsass.exe” or “spdagent.exe” . If the\r\nDLL was loaded by “spdagent.exe” , it will adjust the token privileges of the current process.\r\nIf it was loaded by “lsass.exe” , it will retrieve the path “kb\u003cnum\u003e.dll” from the configuration file “kb.ini”\r\nand write it under the registry key\r\nHKEY_LOCAL_MACHINE\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\WinSock2\\\\Parameters AutodialDLL . This\r\nensures persistence, as it causes the DLL “kb\u003cnum\u003e.dll” to be loaded each time the Winsock 2 library\r\n( ws2_32.dll ) is invoked.\r\nEvasion\r\nTo avoid detection, the plugin first checks the list of running processes for “avp.exe” (Kaspersky Antivirus) or\r\n“NortonSecurity.exe” and exits if either of them is found. If these processes are not found on the system, it goes\r\non to conceal itself by changing its own process name to “explorer.exe” .\r\nThe plugin also has the capability to bypass the UAC mechanisms and to elevate its process privileges through\r\nCMSTP COM interfaces, such as CMSTPLUA {3E5FC7F9-9A51-4367-9063-A120244FBEC7} .\r\nBackdoor user account creation\r\nNext, the plugin carries out registry manipulation (details can be found in the appendix), that lowers the system’s\r\nprotection by:\r\nAllowing local accounts to have full admin rights when they are authenticating via network logon\r\nEnabling RDP connections to the machine without the user password\r\nDisabling admin approval on an administrator account, which means that all applications run with full\r\nadministrative privileges\r\nEnabling anonymous SID to be part of the everyone group in Windows\r\nAllowing “Null Session” users to list users and groups in the domain\r\nAllowing “Null Session” users to access shared folders\r\nSetting the name of the pipe that will be accessible to “Null Session” users\r\nAfter this step, the plugin changes the WebClient service startup type to “Automatic” . It creates a new user\r\nwith the name “DefaultAccount” and the password “Admin@1999!” which is then added to the\r\n“Administrator” and “Remote Desktop Users” groups. It also hides the new account on the logon screen.\r\nAs the last step, the plugin checks the list of running processes for process names “360tray.exe” and\r\n“360sd.exe” and executes the file \"spdlogd.exe\" if neither of them is found.\r\nMecGame(kb%num%.dll)\r\n4C73A62A9F19EEBB4FEFF4FDB88E4682EF852E37FFF957C9E1CFF27C5E5D47AD\r\nMecGame is another example of a plugin that can be loaded by the Core Plugin . Its main purpose is similar to\r\nthe previously described Zload plugin – it executes the binary “spdlogd.exe” and achieves persistence by\r\nhttps://decoded.avast.io/luigicamastra/operation-dragon-castling-apt-group-targeting-betting-companies\r\nPage 13 of 17\n\nregistering an RPC interface with UUID {1052E375-2CE2-458E-AA80-F3B7D6EA23AF} . This RPC interface\r\nrepresents a function that decodes and executes a base64 encoded shellcode.\r\nThe MecGame plugin has several methods for executing spdlogd.exe depending on the level of available\r\nprivileges. It also creates a lockfile with the name MSSYS.lck or \u003cUserName\u003e-XPS.lck depending on the name\r\nof the process that loaded it, and deletes the files atomxd.dll and logexts.dll .\r\nIt can be installed as a service with the service name “inteloem” or can be loaded by any executable that\r\nconnects to the internet via the Winsock2 library.\r\nMulCom\r\nABA89668C6E9681671A95B3D7A08AAE2A067DEED2D835BA6F6FD18556C88A5F2\r\nThis DLL is a backdoor module which exports four functions: “OperateRoutineW” , “StartRoutineW” ,\r\n“StopRoutineW” and ”WorkRoutineW” ; the main malicious function being “StartRoutineW” .\r\nFor proper execution, the backdoor needs configuration data accessed through a shared object with the file\r\nmapping name either “Global\\\\4ED8FD41-2D1B-4CC3-B874-02F0C60FF9CB” or \"Local\\\\4ED8FD41-2D1B-4CC3-\r\nB874-02F0C60FF9CB” . Unfortunately we didn’t come across the configuration data, so we are missing some\r\ninformation such as the C\u0026C server domains this module uses.\r\nThere are 15 commands supported by this backdoor (although some of them are not implemented) referred to by\r\nthe following numerical identifiers:\r\nCommunication protocol\r\nThe MulCom backdoor is capable of communicating via HTTP and TCP protocols. The data it exchanges with the\r\nC\u0026C servers is encrypted and compressed by the RC4 and aPack algorithms respectively, using the RC4 key\r\nhttps://decoded.avast.io/luigicamastra/operation-dragon-castling-apt-group-targeting-betting-companies\r\nPage 14 of 17\n\nloaded from the configuration data object.\r\nIt is also capable of proxy server authentication using schemes such as Basic, NTLM, Negotiate or to authenticate\r\nvia either the SOCKS4 and SOCKS5 protocols.\r\nAfter successful authentication with a proxy server, the backdoor sends data xorred by the constant 0xBC . This\r\ndata is a set with the following structure:\r\nData structure\r\nAnother interesting capability of this backdoor is the usage of layered C\u0026C servers. If this option is enabled in the\r\nconfiguration object (it is not the default option), the first request goes to the first layer C\u0026C server, which returns\r\nthe IP address of the second layer. Any subsequent communication goes to the second layer directly.\r\nAs previously stated, we found several code similarities between the MulCom DLL and the FFRat (a.k.a.\r\nFormerFirstRAT ).\r\nConclusion\r\nWe have described a robust and modular toolset used most likely by a Chinese speaking APT group targeting\r\ngambling-related companies in South East Asia. As we mentioned in this blogpost, there are notable code\r\nsimilarities between FFRat samples and the MulCom backdoor. FFRat or \"FormerFirstRAT'' has been\r\npublicly associated with the DragonOK group according to the Palo Alto Network report, which has in turn been\r\nassociated with backdoors like PoisonIvy and PlugX – tools commonly used by Chinese speaking attackers.\r\nWe also described two different infection vectors, one of which weaponized a vulnerable WPS Office updater. We\r\nrate the threat this infection vector represents as very high, as WPS Office claims to have 1.2 billion installations\r\nworldwide, and this vulnerability potentially allows a simple way to execute arbitrary code on any of these\r\ndevices. We have contacted WPS Office about the vulnerability we discovered and it has since been fixed.\r\nOur research points to some unanswered questions, such as reliable attribution and the attackers’ motivation.\r\nAppendix\r\nList of processes:\r\n360sd.exe\r\n360rp.exe\r\n360Tray.exe\r\n360Safe.exe\r\n360rps.exe\r\nZhuDongFangYu.exe\r\nkxetray.exe\r\nhttps://decoded.avast.io/luigicamastra/operation-dragon-castling-apt-group-targeting-betting-companies\r\nPage 15 of 17\n\nkxescore.exe\r\nKSafeTray.exe\r\nKSafe.exe\r\naudiodg.exe\r\niexplore.exe\r\nMicrosoftEdge.exe\r\nMicrosoftEdgeCP.exe\r\nchrome.exe\r\nRegistry values changed by the Zload plugin:\r\nCore module working directory (WD)\r\nDefault hard-coded WD names (created either in C:\\ProgramData\\ or in %TEMP% ):\r\nspptools\r\nNewGame\r\nTspSoft\r\nInstallAtomx\r\nFile used to test permissions: game_\u003ctick_count\u003e.log – the WD path is written into it and then the file is deleted.\r\nHard-coded security descriptor used for WD access: “D:(A;;GA;;;WD)(A;OICIIO;GA;;;WD)” . \r\nLockfile name format: “\u003cworking_dir\u003e\\\u003cvictim_username\u003e-\u003ccomment_string\u003e.log”\r\nCore module mutexes:\r\nGlobal\\sysmon-windows-%x (%x is a CRC32 of an MD5 hash of the victim’s username)\r\nGlobal\\IntelGameSpeed-%x (%x is a CRC32 of an MD5 hash of the victim’s username\r\nGlobal\\TencentSecuriryAgent-P01-%s (%s is the victim’s username)\r\nIndicators of Compromise (IoC)\r\n Repository: https://github.com/avast/ioc/tree/master/OperationDragonCastling\r\n List of SHA-256: https://github.com/avast/ioc/blob/master/OperationDragonCastling/samples.sha256\r\nhttps://decoded.avast.io/luigicamastra/operation-dragon-castling-apt-group-targeting-betting-companies\r\nPage 16 of 17\n\nA group of elite researchers who like to stay under the radar.\r\nSource: https://decoded.avast.io/luigicamastra/operation-dragon-castling-apt-group-targeting-betting-companies\r\nhttps://decoded.avast.io/luigicamastra/operation-dragon-castling-apt-group-targeting-betting-companies\r\nPage 17 of 17",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"MISPGALAXY",
		"Malpedia"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://decoded.avast.io/luigicamastra/operation-dragon-castling-apt-group-targeting-betting-companies"
	],
	"report_names": [
		"operation-dragon-castling-apt-group-targeting-betting-companies"
	],
	"threat_actors": [
		{
			"id": "5ffe400c-6025-44c2-9aa1-7c34a7a192b0",
			"created_at": "2023-01-06T13:46:38.469688Z",
			"updated_at": "2026-04-10T02:00:02.987949Z",
			"deleted_at": null,
			"main_name": "DragonOK",
			"aliases": [
				"Moafee",
				"BRONZE OVERBROOK",
				"G0017",
				"G0002",
				"Shallow Taurus"
			],
			"source_name": "MISPGALAXY:DragonOK",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "7ebda3c6-1789-4d84-97cf-47fb18a0cb28",
			"created_at": "2022-10-25T15:50:23.78829Z",
			"updated_at": "2026-04-10T02:00:05.415039Z",
			"deleted_at": null,
			"main_name": "DragonOK",
			"aliases": [
				"DragonOK"
			],
			"source_name": "MITRE:DragonOK",
			"tools": [
				"PoisonIvy",
				"PlugX"
			],
			"source_id": "MITRE",
			"reports": null
		},
		{
			"id": "06260304-49f9-4d51-a22d-373c7fcb80ca",
			"created_at": "2022-10-25T16:07:23.944881Z",
			"updated_at": "2026-04-10T02:00:04.801806Z",
			"deleted_at": null,
			"main_name": "Operation Dragon Castling",
			"aliases": [],
			"source_name": "ETDA:Operation Dragon Castling",
			"tools": [],
			"source_id": "ETDA",
			"reports": null
		},
		{
			"id": "593dd07d-853c-46cd-8117-e24061034bbf",
			"created_at": "2025-08-07T02:03:24.648074Z",
			"updated_at": "2026-04-10T02:00:03.625859Z",
			"deleted_at": null,
			"main_name": "BRONZE OVERBROOK",
			"aliases": [
				"Danti ",
				"DragonOK ",
				"Samurai Panda ",
				"Shallow Taurus ",
				"Temp.DragonOK "
			],
			"source_name": "Secureworks:BRONZE OVERBROOK",
			"tools": [
				"Aveo",
				"DDKONG",
				"Godzilla Webshell",
				"HelloBridge",
				"IsSpace",
				"NFLog Trojan",
				"PLAINTEE",
				"PlugX",
				"Rambo"
			],
			"source_id": "Secureworks",
			"reports": null
		},
		{
			"id": "340d1673-0678-4e1f-8b75-30da2f65cc80",
			"created_at": "2022-10-25T16:07:23.552036Z",
			"updated_at": "2026-04-10T02:00:04.653109Z",
			"deleted_at": null,
			"main_name": "DragonOK",
			"aliases": [
				"Bronze Overbrook",
				"G0017",
				"Shallow Taurus"
			],
			"source_name": "ETDA:DragonOK",
			"tools": [
				"Agent.dhwf",
				"CT",
				"Chymine",
				"Darkmoon",
				"Destroy RAT",
				"DestroyRAT",
				"FF-RAT",
				"FormerFirstRAT",
				"Gen:Trojan.Heur.PT",
				"HTran",
				"HUC Packet Transmit Tool",
				"HelloBridge",
				"IsSpace",
				"KHRAT",
				"Kaba",
				"Korplug",
				"Mongall",
				"NFlog",
				"NewCT",
				"NfLog RAT",
				"PlugX",
				"Poison Ivy",
				"Rambo",
				"RedDelta",
				"SPIVY",
				"Sogu",
				"SysGet",
				"TIGERPLUG",
				"TVT",
				"Thoper",
				"TidePool",
				"Xamtrav",
				"brebsd",
				"ffrat",
				"pivy",
				"poisonivy"
			],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775434560,
	"ts_updated_at": 1775826743,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/e5b8f3c54fa97e2e574428b3f16526afa2cbaca4.pdf",
		"text": "https://archive.orkl.eu/e5b8f3c54fa97e2e574428b3f16526afa2cbaca4.txt",
		"img": "https://archive.orkl.eu/e5b8f3c54fa97e2e574428b3f16526afa2cbaca4.jpg"
	}
}