Elastic charms SPECTRALVIPER

Key takeaways,

  • The REF2754 intrusion set leverages multiple PE loaders, backdoors, and PowerShell runners
  • SPECTRALVIPER is a heavily obfuscated, previously undisclosed, x64 backdoor that brings PE loading and injection, file upload and download, file and directory manipulation, and token impersonation capabilities
  • We are attributing REF2754 to a Vietnamese-based intrusion set and aligning with the Canvas Cyclone/APT32/OceanLotus threat actor
https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt305ddc4b5d1936ad/648202011fb2d3aa46494412/image22.png,image22.png,

The unsigned DLL (dbg.config) contained DONUTLOADER shellcode which it attempted to inject into sessionmsg.exe, the Microsoft Remote Session Message Server. DONUTLOADER was configured to load the SPECTRALVIPER backdoor, and ultimately the situationally-dependent P8LOADER or POWERSEAL malware families. Below is the execution flow for the REF2754 intrusion set.

https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0578460f09f26bc1/648201fc83c7fb24925f2f6a/image16.png,image16.png,

Our team also observed a similar workflow described above, but with different techniques to proxy their malicious execution. One example leveraged the Internet Explorer program (ExtExport.exe) to load a DLL, while another technique involved side-loading a malicious DLL (dnsapi.dll) using a legitimate application (nslookup.exe).

These techniques and malware families make up the REF2754 intrusion set.

https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfa4fa587a9c9ac75/6482020159539226fda03a4e/image30.png,image30.pngExecution flow,https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0b35b256530bd54e/648201fbee654959b5ccc50e/image14.png,image14.png,

The SPECTRALVIPER entrypoint is hidden within these exports. In order to find the right one, we can brute-force call them using PowerShell and rundll-ng. The PowerShell command depicted below calls each SPECTRALVIPER export in a for loop until we find the one launching the malware capabilities.

for($i=0; $i -lt 20; $i++){.\rundll-ng\rundll64-ng.exe “.\7e35ba39c2c77775b0394712f89679308d1a4577b6e5d0387835ac6c06e556cb.dll” “#$i”}https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc747b753b2f6d650/64820206224c075b6140321f/image33.png,image33.png,

Upon execution, the binary operates in either HTTP mode or pipe mode, determined by its hardcoded configuration.

Pipe mode,

In pipe mode, SPECTRALVIPER opens a named pipe with a hardcoded name and waits for incoming commands, in this example \.\pipe\raSeCIR4gg.

https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta156649a1fe2ab38/648201fbf7411b150d37b73e/image19.png,image19.png,

This named pipe doesn’t have any security attributes meaning it’s accessible by everyone. This is interesting because an unsecured named pipe can be overtaken by a co-resident threat actor (either known or unknown to the SPECTRALVIPER operator) or defensive teams as a way to interrupt this execution mode.

https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte8c365fb839324dc/648201f6595392beb9a03a4a/image6.png,image6.png,

However, a specific protocol is needed to communicate with this pipe. SPECTRALVIPER implements the Diffie-Helman key exchange protocol to exchange the key needed to encrypt and decrypt commands transmitted via the named pipe, which is AES-encrypted.

https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt83154260d0e7612a/648201fbe73df56e33a6ef25/image20.png,image20.png,

Using a debugger, we can force the binary to use the HTTP channel instead of the named pipe if the binary contains a hard-coded domain.

https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcec1dd29fc93499f/64820201616b14202715c56c/image28.png,image28.png,

Below is an HTTP request example.

https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4eb0ef35ce430057/648201fc224c073c6740321b/image15.png,image15.png,

The request contains a cookie header, “euconsent-v2”, which contains host-gathered information. This information is encrypted using RSA1024 asymmetric encryption and base64-encoded using Base64. Below is an example of the cookie content before encryption.

https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt67f7a070368697b4/648201f6cb67026d4d1568f1/image10.png,image10.png,

We believe that the first value, in this example “H9mktfe2k0ukk64nZjw1ow==”, is the randomly generated AES key that is shared with the server to encrypt communication data.

https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta62ab2f4828f2dd1/648201fc50d8ed7c742f064a/image17.png,image17.png,

Below is a table listing of the commands that were identified.

ID Name
2 DownloadFile
3 UploadFile
5 SetBeaconIntervals
8 CreateRundll32ProcessAndHollow
11 InjectShellcodeInProcess
12 CreateProcessAndInjectShellcode
13 InjectPEInProcess
14 CreateProcessAndHollow
20 CreateRundll32ProcessWithArgumentAndInjectPE
81 StealProcessToken
82 ImpersonateUser
83 RevertToSelf
84 AdjustPrivileges
85 GetCurrentUserName
103 ListFiles
106 ListRunningProcesses
108 CopyFile
109 DeleteFile
110 CreateDirectory
111 MoveFile
200 RunDLLInOwnProcess

In order to speed up the process of interacting with SPECTRALVIPER, we bypassed the communication protocols and injected our own backdoor into the binary. This backdoor will open a socket and call the handlers upon receiving our messages.

https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfe6056ebdb800c52/648201fbb9a076fd56925a53/image13.png,image13.png,

When the AdjustPrivileges command is executed, and depending on the process's current privilege level, the malware will try to set the following list of privileges.

https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltbc65a839008be6ed/648201f6f7411b61c037b732/image3.png,image3.pngDefense evasion,https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt366faff731f6556a/648202011fb2d3548c49440e/image21.png,image21.pngString obfuscation,

SPECTRALVIPER’s strings are obfuscated using a custom structure and AES decryption. The key is hardcoded ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f") and the IV is contained within the encrypted string structure.

https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltec7e8659e0a8e68f/64820201b9a0760257925a57/image24.png,image24.pnghttps://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta50088ddbde91e46/648201f61fb2d3141f494406/image2.png,image2.png,

We can decrypt the strings by instrumenting the malware and calling its AES decryption functions.

https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfb0c78510ddabb67/64820201359ef0429360ca4c/image27.png,image27.pnghttps://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta56f3c3ad6ffa040/6482020674d501d6df013bb0/image31.png,image31.pngSummary,

SPECTRALVIPER is an x64 backdoor discovered during intrusion analysis by Elastic Security Labs. It can be compiled as an executable or DLL which usually would imitate known binary exports.

It enables process loading/injection, token impersonation, and file manipulation. It utilizes encrypted communication channels (HTTP and named pipe) with AES encryption and Diffie-Hellman or RSA1024 key exchange.

All samples are heavily obfuscated using the same obfuscator with varying levels of hardening. 

Using the information we collected through static and dynamic analysis, we were able to identify several other samples in VirusTotal. Using the debugging process outlined above, we were also able to collect the C2 infrastructure for these samples.

https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt54e4780bc058353e/648201f6f7411b75f337b736/image5.png,image5.pngDiscovery,

P8LOADER was initially discovered when an unbacked shellcode alert was generated by the execution of a valid Windows process, RuntimeBroker.exe. Unbacked executable sections, or floating code, are the result of code section types set to “Private” instead of “Image” like you would see when code is mapped to a file on disk. Threads starting from these types of memory regions are anomalous and a good indicator of malicious activity.

https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6bd3664852df5b46/648201f6b9a076dbf1925a4f/image1.png,image1.pngExecution flow,

The loader exports two functions that have the capability to load PE binaries into its own process memory, either from a file or from memory.

https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltca3ca7b6ba3f109d/6482020175c2ae391705ed12/image26.png,image26.png,

The PE to be executed is loaded into memory using the VirtualAlloc method with a classic PE loading algorithm (loading sections, resolving imports, and applying relocations).

https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltec8b9280c6f52d09/648201f6207042642786b5ca/image9.png,image9.png,

Next, a new thread is allocated with the entry point of the PE as the starting address.

https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte895598b42d29fe9/64820206352ac64861da21c1/image34.png,image34.png,

Finally, the loaded PE’s STDOUT handle is replaced with a pipe and a reading pipe thread is created as a way to redirect the output of the binary to the loader logging system.

https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta66d3461065cdcfd/64820201207042134486b5ce/image29.png,image29.png,

On top of redirecting the loaded PE output, the loader uses an API interception mechanism to hook certain APIs of the loaded process, log any calls to it, and send the data through a named pipe (with a randomly generated UUID string as the name).

The hooking of the PE's import table is done at import resolution time by replacing the originally imported function addresses with their own stub.

https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte0835a67af164453/648201f6359ef0fa6a60ca44/image7.png,image7.pnghttps://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt41e21c99d871b8cb/64820201f71d776f9f001bc9/image23.png,image23.pnghttps://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb11fa789d1f8b774/64820201d5b9a5d0776db98c/image25.png,image25.pngSummary,

P8LOADER is a newly discovered x64 Windows loader that is used to execute a PE from a file or from memory. This malware is able to redirect the loaded PE output to its logging system and hook the PE imports to log import calls.

https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4d4bfdecff37c60a/648201fb1fb2d3142f49440a/image11.png,image11.pngDefense evasion,

Event Tracing for Windows (ETW) provides a mechanism to trace and log events that are raised by user-mode applications and kernel-mode drivers. The Anti Malware Scan Interface (AMSI) provides enhanced malware protection for data, applications, and workloads. POWERSEAL adopts well-known and publicly-available bypasses in order to patch these technologies in memory. This increases their chances of success while decreasing their detectable footprint.

For example, POWERSEAL employs common approaches to unhooking and bypassing AMSI in order to bypass Microsoft Defender’s signature

https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt25e2399880c5e1ca/648201f72429af0482f46cf8/image8.png,image8.pngLaunch PowerShell,

POWERSEAL’s primary function is to execute PowerShell. In the following depiction of POWERSEAL’s source code, we can see that POWERSEAL uses PowerShell to execute a script and arguments (command). The script and arguments are provided by the threat actor and were not observed in the environment.

https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt08bd32ac64791ff1/64820206d2420429851caba3/image32.png,image32.pngSummary,

POWERSEAL is a new and purpose-built PowerShell runner that borrows freely from a variety of open source offensive security tools, delivering offensive capabilities in a streamlined package with built-in defense evasion.

Campaign and adversary modeling,https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt51ca9bdb12690385/648201f6f7411b608737b73a/image4.png,image4.pngVictimology,

Using our SPECTRALVIPER YARA signature, we identified two endpoints in a second environment infected with SPECTRALVIPER implants. That environment was discussed in Elastic Security Labs research in 2022 which describes REF4322.

The REF4322 victim is a Vietnam-based financial services company. Elastic Security Labs first talked about this victim and activity group in 2022.

The REF2754 victim has been identified as a large Vietnam-based agribusiness.

Further third party intelligence from VirusTotal, based on retro-hunting the YARA rules available at the end of this research, indicate additional Vietnam-based victims. There were eight total Retrohunt hits:

  • All were manually confirmed to be SPECTRALVIPER
  • All samples were between 1.59MB and 1.77MB in size
  • All VirusTotal samples were initially submitted from Vietnam

Some samples were previously identified in our first party collection, and some were new to us.

,

At the time of publication, all known victims are large public companies physically within Vietnam, and conducting business primarily within Vietnam.

https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt37f42436747425ce/648201fbd5b9a5863c6db988/image18.png,image18.png,

This activity appears to be a handoff of access or swapping out of one tool for another.

,

Post-exploitation collection of intended effects has been limited, however, while speculative in nature, a motivation assessment based on malware, implant, and technical capabilities points to achieving initial access, maintaining persistence, and operating as a backdoor for intelligence gathering purposes.

Domains from REF4322, REF2754, and from samples collected from VirusTotal used for C2 have all been registered in the last year with the most recent being in late April 2023.

Domain: Created:
stablewindowsapp[.]com 2022-02-10
webmanufacturers[.]com 2022-06-10
toppaperservices[.]com 2022-12-15
hosting-wordpress-services[.]com 2023-03-15
appointmentmedia[.]com 2023-04-26

GEOs for associated IPs for these domains are globally distributed, and they use Sectigo, Rapid SSL, and Let’s Encrypt certs. Further infrastructure analysis did not uncover anything of note beyond their registration date, which does give us a campaign timebox. Based on the recent registration of appointmentmedia[.]com, this campaign could still be ongoing with new domains being registered for future intrusions.

https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt23ea2315719b8944/648201fc0f2d9b59c9ed3feb/image12.png,image12.pngObserved adversary tactics and techniques,

Elastic uses the MITRE ATT&CK framework to document common tactics, techniques, and procedures that advanced persistent threats use against enterprise networks.

rule Windows_Trojan_SpectralViper_1 { meta: author = "Elastic Security" creation_date = "2023-04-13" last_modified = "2023-05-26" os = "Windows" arch = "x86" category_type = "Trojan" family = "SpectralViper" threat_name = "Windows.Trojan.SpectralViper" reference_sample = "7e35ba39c2c77775b0394712f89679308d1a4577b6e5d0387835ac6c06e556cb" license = "Elastic License v2"
strings:
    $a1 = { 13 00 8D 58 FF 0F AF D8 F6 C3 01 0F 94 44 24 26 83 FD 0A 0F 9C 44 24 27 4D 89 CE 4C 89 C7 48 89 D3 48 89 CE B8 }
    $a2 = { 15 00 8D 58 FF 0F AF D8 F6 C3 01 0F 94 44 24 2E 83 FD 0A 0F 9C 44 24 2F 4D 89 CE 4C 89 C7 48 89 D3 48 89 CE B8 }
    $a3 = { 00 8D 68 FF 0F AF E8 40 F6 C5 01 0F 94 44 24 2E 83 FA 0A 0F 9C 44 24 2F 4C 89 CE 4C 89 C7 48 89 CB B8 }
    $a4 = { 00 48 89 C6 0F 29 30 0F 29 70 10 0F 29 70 20 0F 29 70 30 0F 29 70 40 0F 29 70 50 48 C7 40 60 00 00 00 00 48 89 C1 E8 }
    $a5 = { 41 0F 45 C0 45 84 C9 41 0F 45 C0 EB BA 48 89 4C 24 08 89 D0 EB B1 48 8B 44 24 08 48 83 C4 10 C3 56 57 53 48 83 EC 30 8B 05 }
    $a6 = { 00 8D 70 FF 0F AF F0 40 F6 C6 01 0F 94 44 24 25 83 FF 0A 0F 9C 44 24 26 89 D3 48 89 CF 48 }
    $a7 = { 48 89 CE 48 89 11 4C 89 41 08 41 0F 10 01 41 0F 10 49 10 41 0F 10 51 20 0F 11 41 10 0F 11 49 20 0F 11 51 30 }
    $a8 = { 00 8D 58 FF 0F AF D8 F6 C3 01 0F 94 44 24 22 83 FD 0A 0F 9C 44 24 23 48 89 D6 48 89 CF 4C 8D }
condition:
    5 of them

}rule Windows_Trojan_SpectralViper_2 {
meta:
author = “Elastic Security”
creation_date = “2023-05-10”
last_modified = “2023-05-10”
os = “Windows”
arch = “x86”
category_type = “Trojan”
family = “SpectralViper”
threat_name = “Windows.Trojan.SpectralViper”
reference_sample = “d1c32176b46ce171dbce46493eb3c5312db134b0a3cfa266071555c704e6cff8”
license = “Elastic License v2”

strings:
    $a1 = { 18 48 89 4F D8 0F 10 40 20 0F 11 47 E0 0F 10 40 30 0F 11 47 F0 48 8D }
    $a2 = { 24 27 48 83 C4 28 5B 5D 5F 5E C3 56 57 53 48 83 EC 20 48 89 CE 48 }
    $a3 = { C7 84 C9 0F 45 C7 EB 86 48 8B 44 24 28 48 83 C4 30 5B 5F 5E C3 48 83 }
    $s1 = { 40 53 48 83 EC 20 48 8B 01 48 8B D9 48 8B 51 10 48 8B 49 08 FF D0 48 89 43 18 B8 04 00 00 }
    $s2 = { 40 53 48 83 EC 20 48 8B 01 48 8B D9 48 8B 49 08 FF D0 48 89 43 10 B8 04 00 00 00 48 83 C4 20 5B }
    $s3 = { 48 83 EC 28 4C 8B 41 18 4C 8B C9 48 B8 AB AA AA AA AA AA AA AA 48 F7 61 10 48 8B 49 08 48 C1 EA }
condition:
    2 of ($a*) or any of ($s*)

}rule Windows_Trojan_PowerSeal_1 {
meta:
author = “Elastic Security”
creation_date = “2023-03-16”
last_modified = “2023-05-26”
os = “Windows”
arch = “x86”
category_type = “Trojan”
family = “PowerSeal”
threat_name = “Windows.Trojan.PowerSeal”
license = “Elastic License v2”

strings:
    $a1 = "PowerSeal.dll" wide fullword
    $a2 = "InvokePs" ascii fullword
    $a3 = "amsiInitFailed" wide fullword
    $a4 = "is64BitOperatingSystem" ascii fullword
condition:
    all of them

}rule Windows_Trojan_PowerSeal_2 {
meta:
author = “Elastic Security”
creation_date = “2023-05-10”
last_modified = “2023-05-10”
os = “Windows”
arch = “x86”
category_type = “Trojan”
family = “PowerSeal”
threat_name = “Windows.Trojan.PowerSeal”
license = “Elastic License v2”

strings:
    $a1 = "[+] Loading PowerSeal"
    $a2 = "[!] Failed to exec PowerSeal"
    $a3 = "AppDomain: unable to get the name!"
condition:
    2 of them

}rule Windows_Trojan_P8Loader {
meta:
author = “Elastic Security”
creation_date = “2023-04-13”
last_modified = “2023-05-26”
os = “Windows”
arch = “x86”
category_type = “Trojan”
family = “P8Loader”
threat_name = “Windows.Trojan.P8Loader”
license = “Elastic License v2”

strings:
    $a1 = "\t[+] Create pipe direct std success\n" fullword
    $a2 = "\tPEAddress: %p\n" fullword
    $a3 = "\tPESize: %ld\n" fullword
    $a4 = "DynamicLoad(%s, %s) %d\n" fullword
    $a5 = "LoadLibraryA(%s) FAILED in %s function, line %d" fullword
    $a6 = "\t[+] No PE loaded on memory\n" wide fullword
    $a7 = "\t[+] PE argument: %ws\n" wide fullword
    $a8 = "LoadLibraryA(%s) FAILED in %s function, line %d" fullword
condition:
    5 of them

}References,

The following were referenced throughout the above research:

Article Link: Elastic charms SPECTRALVIPER | Elastic