Go back

From Analysis to Tooling: Automating Amatera C2 Extraction

This post serves as a technical update to the previous analysis of the Acreed threat actor. Following the investigation into “EtherHiding” techniques and cross-platform infection chains, the focus has shifted to improving automated analysis capabilities.

For the full background on the campaign, refer to the previous report: Acreed: On‑Chain C2 Evolution.

This update covers fixes implemented for open-source sandbox parsers and the release of a unified tool designed to streamline the analysis of this family.

Terminology: ACR Stealer vs. Amatera

The terms ACR Stealer and Amatera are used interchangeably in this documentation. While Amatera appears to be the modern evolution of the malware, most security tools and sandboxes (such as CAPE) classify them under the same family. Despite naming differences, the core behavior and configuration structures remain consistent.

CAPE Sandbox Updates

Recent Amatera samples have introduced rotation in how decryption keys (AES and XOR) are stored to evade standard static extraction. These changes caused failures in existing community parsers.

To address this, the obfuscation patterns were reverse-engineered and a fix was submitted to the CAPE Sandbox project:

This update allows CAPE to automatically extract configuration data from these newer variants.

Unified Static-Dynamic Extractor

A standalone script has been developed to combine static parsing logic with dynamic C2 interaction. This tool creates a unified pipeline that:

  1. Statically Extracts Keys: Parses the unpacked executable to locate AES and XOR keys, accounting for multiple obfuscation techniques.
  2. Dynamically Communicates: Uses the extracted keys to emulate a victim machine and perform the encrypted handshake with the C2.
  3. Downloads Payloads: Decrypts the JSON configuration and retrieves secondary payloads (such as Amadey or Discord stealers) defined in the loader (ld) section.

The script is available here: acreed_c2_download.py.

Handling Key Storage Variants

The script includes logic to handle recent samples where key storage prevents standard extraction. Amatera primarily utilizes two methods for this:

  1. Global Data: Keys are stored in the .data section and referenced via the stack.
  2. Stack Construction: Keys are constructed byte-by-byte via mov instructions directly on the stack to evade string-based detection.

The tool utilizes pefile and yara to dynamically detect the method used. The specific logic for differentiating between these storage methods is demonstrated in Listing 1.

def extract_config(data):
    # ... setup pefile ...

    # Scan for the XOR key pattern
    offset = yara_scan(data, RULE_SOURCE)
    
    # Variant A: Global Data Reference
    # Pattern: mov eax, dword ptr ds:szXorKey
    if data[offset] == 0xA1:  
        key_str_va = struct.unpack("i", data[offset + 1 : offset + 5])[0]
        # ... extract string from data section ...

    # Variant B: Stack Construction
    # Pattern: sub esp, 1Ch ... mov [ebp+var], reg
    elif data[offset] == 0x83: 
        key_bytes = bytearray()
        # ... parse the 'mov' instructions to reconstruct the key byte-by-byte ...
Listing 1: Logic to detect key storage method (Stack vs Global)

Share this post on:

Previous Post
Defender Timeline Downloader: Extending Data Retention for Incident Response
Next Post
Welcome to My Blog