Disclosing the BLOODALCHEMY backdoor — Elastic Security Labs
Cyril François

Disclosing the BLOODALCHEMY backdoor

BLOODALCHEMY is a new, actively developed, backdoor that leverages a benign binary as an injection vehicle, and is a part of the REF5961 intrusion set.

Disclosing the BLOODALCHEMY backdoor

Preamble

BLOODALCHEMY is an x86 backdoor written in C and found as shellcode injected into a signed benign process. It was discovered in our analysis and is part of the REF5961 intrusion set, which you can read about here.

BLOODALCHEMY requires a specific loader to be run because it isn't reflexive (it doesn’t have the capability to load and execute by itself). Additionally, BLOODALCHEMY isn’t compiled as position independent (when loaded at a different base address than the preferred one the binary has to be patched to take into account the new “position”).

In our analysis, the signed benign process was previously sideloaded with a malicious DLL. The DLL was missing from the sample data but was likely the container and the loader of the BLOODALCHEMY shellcode.

We believe from our research that the malware is part of a bigger toolset and is still in active development based on its current lack of capabilities, enabled debug logging of exceptions, and the existence of test strings used for persistence service setup.

Key takeaways

  • BLOODALCHEMY is likely a new backdoor and is still in active development
  • BLOODALCHEMY abuses a legitimate binary for loading
  • BLOODALCHEMY has multiple running modes, persistence mechanisms, and communication options

Initial execution

During the initial execution phase, the adversary deployed a benign utility, BrDifxapi.exe, which is vulnerable to DLL side-loading. When deploying this vulnerable utility the adversary could side-load the unsigned BLOODALCHEMY loader (BrLogAPI.dll) and inject shellcode into the current process.

BrDifxapi.exe is a binary developed by the Japanese company Brother Industries and the version we observed has a revoked signature.

The legitimate DLL named BrLogApi.dll is an unsigned DLL also by Brother Industries. BLOODALCHEMY uses the same DLL name.

Code analysis

Data Obfuscation

To hide its strings the BLOODALCHEMY malware uses a classic technique where each string is encrypted, preceded by a single-byte decryption key, and finally, all concatenated together to form what we call an encrypted blob.

While the strings are not null-terminated, the offset from the beginning of the blob, the string, and the size are passed as a parameter to the decryption function. Here is the encrypted blob format:

Blob = Key0 :EncryptedString0 + Key1:EncryptedString1 + ... + KeyN:EncryptedStringN

The implementation in Python of the string decryption algorithm is given below:

def decrypt_bytes(encrypted_data: bytes, offset: int, size: int) -> bytes:
    decrypted_size = size - 1
    decrypted_data = bytearray(decrypted_size)

    encrypted_data_ = encrypted_data[offset : offset + size]
    key = encrypted_data_[0]

    i = 0
    while i != decrypted_size:
            decrypted_data[i] = key ^ encrypted_data_[i + 1]
           key = (key + ((key << ((i % 5) + 1)) | (key >> (7 - (i % 5))))) & 0xFF
           i += 1

    return bytes(decrypted_data)

The strings contained in the configuration blob are encrypted using the same scheme, however the ids (or offsets) of each string are obfuscated; it adds two additional layers of obfuscation that must be resolved. Below, we can resolve additional obfuscation layers to decrypt strings from the configuration:

def decrypt_configuration_string(id: int) -> bytes:
        return decrypt_bytes(
                *get_configuration_encrypted_string(
                        get_configuration_dword(id)))

Each function is given below:

The get_configuration_dword function

def get_configuration_dword(id: int) -> int:
        b = ida_bytes.get_bytes(CONFIGURATION_VA + id, 4)
        return b[0] + (b[1] + (b[2] + (b[3] << 8) << 8) << 8)

The get_configuration_encrypted_strng function

def get_configuration_encrypted_string(id: int) -> tuple[int, int]:
         ea = CONFIGURATION_VA + id

        v2 = 0
        i = 0

        while i <= 63:
            c = ida_bytes.get_byte(ea)

            v6 = (c & 127) << i
            v2 = (v2 | v6) & 0xFFFFFFFF

            ea += 1

            if c >= 0:
                break
            
            i += 7
            return ea, v2

Persistence

BLOODALCHEMY maintains persistence by copying itself into its persistence folder with the path suffix \Test\test.exe,

The root directory of the persistence folder is chosen based on its current privilege level, it can be either:

  • %ProgramFiles%
  • %ProgramFiles(x86)%
  • %Appdata%
  • %LocalAppData%\Programs

Persistence is achieved via different methods depending on the configuration:

  • As a service
  • As a registry key
  • As a scheduled task
  • Using COM interfaces

To identify the persistence mechanisms, we can use the uninstall command to observe the different ways that the malware removes persistence.

As a service named Test.

As a registry key at CurrentVersion\Run

As a scheduled task, running with SYSTEM privilege via schtask.exe:

b'schtasks.exe /CREATE /SC %s /TN "%s" /TR "\'%s\'" /RU "NT AUTHORITY\\SYSTEM" /Fb'

Using the TaskScheduler::ITaskService COM interface. The intent of this persistence mechanism is currently unknown.

Running modes

The malware has different running modes depending on its configuration:

  • Within the main or separate process thread
  • Create a Windows process and inject a shellcode into it
  • As a service

The malware can either work within the main process thread.

Or run in a separate thread.

Or create a Windows process from a hardcoded list and inject a shellcode passed by parameter to the entry point using the WriteProcessMemory+QueueUserAPC+ResumeThread method.

The shellcode is contained in the parameters we call p_interesting_data. This parameter is actually a pointer to a structure containing both the malware configuration and executable binary data.

Or install and run itself as a service. In this scenario, the service name and description will be Test and Digital Imaging System:

Also when running as a service and started by the service manager the malware will masquerade itself as stopped by first setting the service status to “SERVICE_RUNNING” then setting the status to “SERVICE_STOPPED” while in fact the malware is still running.

Communication

The malware communicates using either the HTTP protocol, named pipes, or sockets.

When using the HTTP protocol the malware requests the following URI /Inform/logger/.

In this scenario, BLOODALCHEMY will try to use any proxy server found in the registry key SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings.

We did not uncover any C2 infrastructure with our sample, but the URL could look something like this: https://malwa[.]re/Inform/logger

When using a named pipe, the name is randomly generated using the current PID as seed.

While waiting for a client to connect to this named pipe the malware scans the running processes and checks that its parent process is still running, this may be to limit access to the named pipe. That said, the malware is not checking that the pipe client is the correct parent process, only that the parent process is running. This introduces flawed logic in protecting the named pipe.

From the malware strings and imports we know that the malware can also operate using TCP/UDP sockets.

While we haven’t made any conclusions about their usage, we list all the protocols found in the encrypted strings.

  • DNS://
  • HTTP://
  • HTTPS://
  • MUX://
  • UDP://
  • SMB://
  • SOCKS5://
  • SOCKS4://
  • TCP://

For all protocols the data can be encrypted, LZNT1 compressed, and/or Base64-encoded.

Commands

The malware only contains a few commands with actual effects:

  • Write/overwrite the malware toolset
  • Launch its malware binary Test.exe
  • Uninstall and terminate
  • Gather host information

There are three commands that write (or overwrite) the malware tool set with the received Base64-encoded binary data:

  • Either the malware binary (Test.exe)
  • the sideloaded DLL (BrLogAPI.dll)
  • or the main trusted binary (BrDifxapi.exe)

One command that launches the Test.exe binary in the persistence folder.

The uninstall and terminate itself command will first delete all its files at specific locations then remove any persistence registry key or scheduled task, then remove installed service and finish by terminating itself.

One host information gathering command: CPU, OS, display, network, etc.

Summary

BLOODALCHEMY is a backdoor shellcode containing only original code(no statically linked libraries). This code appears to be crafted by experienced malware developers.

The backdoor contains modular capabilities based on its configuration. These capabilities include multiple persistence, C2, and execution mechanisms.

While unconfirmed, the presence of so few effective commands indicates that the malware may be a subfeature of a larger intrusion set or malware package, still in development, or an extremely focused piece of malware for a specific tactical usage.

BLOODALCHEMY and MITRE ATT&CK

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

Tactics

Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.

Malware prevention capabilities

YARA

Elastic Security has created YARA rules to identify this activity. Below are YARA rules to identify the BLOODALCHEMY malware:

BLOODALCHEMY
rule Windows_Trojan_BloodAlchemy_1 {
    meta:
        author = "Elastic Security"
        creation_date = "2023-05-09"
        last_modified = "2023-06-13"
        threat_name = "Windows.Trojan.BloodAlchemy"
        license = "Elastic License v2"
        os = "windows"

    strings:
        $a1 = { 55 8B EC 51 83 65 FC 00 53 56 57 BF 00 20 00 00 57 6A 40 FF 15 }
        $a2 = { 55 8B EC 81 EC 80 00 00 00 53 56 57 33 FF 8D 45 80 6A 64 57 50 89 7D E4 89 7D EC 89 7D F0 89 7D }

    condition:
        all of them
}

rule Windows_Trojan_BloodAlchemy_2 {
    meta:
        author = "Elastic Security"
        creation_date = "2023-05-09"
        last_modified = "2023-06-13"
        threat_name = "Windows.Trojan.BloodAlchemy"
        license = "Elastic License v2"
        os = "windows"

    strings:
        $a1 = { 55 8B EC 83 EC 54 53 8B 5D 08 56 57 33 FF 89 55 F4 89 4D F0 BE 00 00 00 02 89 7D F8 89 7D FC 85 DB }
        $a2 = { 55 8B EC 83 EC 0C 56 57 33 C0 8D 7D F4 AB 8D 4D F4 AB AB E8 42 10 00 00 8B 7D F4 33 F6 85 FF 74 03 8B 77 08 }

    condition:
        any of them
}

rule Windows_Trojan_BloodAlchemy_3 {
    meta:
        author = "Elastic Security"
        creation_date = "2023-05-10"
        last_modified = "2023-06-13"
        threat_name = "Windows.Trojan.BloodAlchemy"
        license = "Elastic License v2"
        os = "windows"

    strings:
        $a = { 55 8B EC 83 EC 38 53 56 57 8B 75 08 8D 7D F0 33 C0 33 DB AB 89 5D C8 89 5D D0 89 5D D4 AB 89 5D }

    condition:
        all of them
}

rule Windows_Trojan_BloodAlchemy_4 {
    meta:
        author = "Elastic Security"
        creation_date = "2023-05-10"
        last_modified = "2023-06-13"
        threat_name = "Windows.Trojan.BloodAlchemy"
        license = "Elastic License v2"
        os = "windows"

    strings:
        $a = { 55 8B EC 83 EC 30 53 56 57 33 C0 8D 7D F0 AB 33 DB 68 02 80 00 00 6A 40 89 5D FC AB AB FF 15 28 }

    condition:
        all of them
}

Observations

All observables are also available for download in both ECS and STIX format in a combined zip bundle.

The following observables were discussed in this research.

ObservableTypeNameReference
e14ee3e2ce0010110c409f119d56f6151fdca64e20d902412db46406ed89009aSHA-256BrLogAPI.dllBLOODALCHEMY loader
25268bc07b64d0d1df441eb6f4b40dc44a6af568be0657533088d3bfd2a05455SHA-256NABLOODALCHEMY payload