Connects to any signal across any vendor stack and powers adaptive AI Operatives that expose, detect, and neutralize cyberattacks.
Atlas Operations CenterSee what our SOC sees, review investigations, and see how we are protecting your business.
Technology IntegrationsAtlas connects to any signal across your current security tools. Whatever you're running, we're running with you.
Extend your team with immediate expertise, hands-on remediation, and the human accountability layer that boards, regulators, and cyber insurers require.
Threat Response UnitProactive threat intelligence, original threat research and a world-class team of seasoned industry veterans.
Response and RemediationPairs machine-speed containment with human judgment, delivering full threat response that's policy-bounded, reversible, and explainable.
MDR that moves first, multi-signal attack surface coverage, and 24/7 Elite threat hunters working as one continuous security program across any vendor stack.
Get unlimited Incident Response with threat suppression guarantee- anytime, anywhere.
Full alignment to the five-stages of CTEM operations; scope, discover, prioritize, validate, and mobilize against exposures attackers would use against you.
Flexible MDR pricing and packages that fit your unique security requirements.
Entry level foundational MDR coverage
Comprehensive Next Level eSentire MDR
Next Level eSentire MDR with Cyber Risk Advisors to continuously advance your security program
Stop ransomware before it spreads.
Identity ResponseStop identity-based cyberattacks.
Zero Day AttacksDetect and respond to zero-day exploits.
Cybersecurity ComplianceMeet regulatory compliance mandates.
Third-Party RiskDefend third-party and supply chain risk.
Cloud MisconfigurationEnd misconfigurations and policy violations.
Cyber RiskAdopt a risk-based security approach.
Mid-Market SecurityMid-market security essentials to prioritize.
Sensitive Data SecurityProtect your most sensitive data.
Cyber InsuranceMeet insurability requirements with MDR.
Cyber Threat IntelligenceOperationalize cyber threat intelligence.
Security LeadershipBuild a proven security program.
On May 5th, 2026, Palo Alto Networks disclosed CVE-2026-0300 (CVSS: 9.3), a critical zero-day buffer overflow vulnerability that impacts the User-ID Authentication Portal (aka Captive…
On April 29th, 2026, cPanel disclosed a critical Authentication Bypass vulnerability, tracked as CVE-2026-41940 (CVSS 9.8), that impacts the control panel solutions cPanel and Web Host…
eSentire is The Authority in Managed Detection and Response Services, protecting the critical data and applications of 2000+ organizations in 80+ countries from known and unknown cyber threats. Founded in 2001, the company’s mission is to hunt, investigate and stop cyber threats before they become business disrupting events.
About Us Leadership Careers Event Calendar → Newsroom → Aston Villa Football Club →We provide sophisticated cybersecurity solutions for Managed Security Service Providers (MSSPs), Managed Service Providers (MSPs), and Value-Added Resellers (VARs). Find out why you should partner with eSentire, the Authority in Managed Detection and Response, today.
Search our site
Multi-Signal MDR with 300+ technology integrations to support your existing investments.
24/7 SOC-as-a-Service with unlimited threat hunting and incident handling.
We offer three flexible MDR pricing packages that can be customized to your unique needs.
The latest security advisories, blogs, reports, industry publications and webinars published by TRU.
Compare eSentire to other Managed Detection and Response vendors to see how we stack up against the competition.
See why 2000+ organizations globally have chosen eSentire for their MDR Solution.
In late April 2026, eSentire's Threat Response Unit (TRU) intercepted an attempted delivery of Amatera Stealer within a customer environment in the Finance industry. Amatera Stealer is a rebranded version of ACR (AcridRain) Stealer, a C++ based information stealer previously marketed as Malware-as-a-Service (MaaS) on underground forums by the threat actor SheldIO. The stealer has existed in one form or another since at least 2018, with its source code sold in 2024, making it a threat that has withstood the test of time.
This blog covers the shellcode loader observed in the attack and notable changes in Amatera Stealer since our last blog on the threat in November 2025, EVALUSION Campaign Delivers Amatera Stealer and NetSupport RAT:
The attack chain begins with ClickFix and leads to several stages of PowerShell that ultimately execute 32-bit shellcode that decrypts, decompresses, and executes Amatera Stealer in memory (in the context of PowerShell).

Functions as a reflective loader [T1620] that decrypts, decompresses, and transfers execution to a DLL or EXE payload. It uses a 128‑byte XOR key to first decrypt the encrypted payload blob, then aPLib to decompress it. At offset 0, a call instruction transfers execution to the reflective loader routine (displayed in the figure below as mw_reflective_loader) and in doing so, passes the return address onto the stack. The return address isn't code, but rather it is the payload blob. The navigation bar shown in the figure below clarifies the layout of the shellcode binary, which follows the format: [ mw_reflective_loader_call_instruction | payload_blob | mw_reflective_loader ].

The structure below displays the format of the payload blob. This blob contains the compressed size, decompressed size, XOR key, a boolean flag to erase PE headers after mapping the payload via reflective PE injection, and the payload buffer itself.
The figure below shows an annotated view of the blob in a hex editor, with a legend clarifying the structure described above.

The shellcode walks the list of loaded modules and for each module walks its EAT (Export Address Table) and hashes export names using a polynomial rolling hash algorithm. Seven APIs are resolved in this process: VirtualAlloc, VirtualProtect, ExitProcess, VirtualFree, LoadLibraryA, GetModuleHandleA, and GetProcAddress. As a means of preventing hash collisions, especially because the shellcode doesn't validate the names of modules, ALL resolved API/export address pointers are checked for NULL, otherwise the shellcode moves onto the next loaded module.
This process is described as follows:

The figure below displays the instructions responsible for calculating/comparing export name hashes via polynomial rolling hash. The seed, algorithm, and hash to export-name are shown as comments. Note, the bitwise or with 0x20 converts each character to lowercase by setting the 5th bit, e.g. 'V' (01010110) | 0x20 → 'v' (01110110).

The python code snippet shown below reproduces the hashing algorithm and prints the hash for VirtualAlloc "0x91a71a6c".
The next figure displays the instructions responsible for checking resolved exports, allocating memory, and copying the encrypted/compressed payload buffer into the allocated region.

The buffer is then XOR decrypted via the basic block shown in the next figure. This block is responsible for enumerating over the 128-byte XOR key and XORing each byte of the buffer, yielding the aPLib compressed payload.

The payload buffer is then decompressed via aPLib and the reflective injection process begins by mapping the payload's sections into a newly allocated PAGE_READWRITE buffer.
It then fixes up the payload's Import Address Table (IAT), resolving imports by ordinal and by name via GetProcAddress. For each imported function, it gets a handle to the module via GetModuleHandleA (or LoadLibraryA if the module isn't already loaded), then calls GetProcAddress with the module handle and passes the function's ordinal/name to obtain the function pointer.
Finally, it writes that resolved address into the corresponding IAT slot in the mapped image (replacing the original placeholder/RVA-based entry with the resolved address). After resolving imports, the loader calls VirtualProtect to change protection on the .text section to PAGE_EXECUTE_READ, simulating the OS loader and avoiding PAGE_EXECUTE_READWRITE.

The handle for ntdll.dll is then resolved via GetModuleHandleA, and used in finding the address of LdrpHandleTlsData - an undocumented ntdll function that initializes support for TLS (Thread Local Storage). The shellcode then checks the PEB fields OSMajorVersion and OSMinorVersion, ensuring LdrpHandleTlsData is only called on hosts running Windows 8.1 or higher. TLS callbacks are then invoked (if any).
If configured to do so (by the payload blob structure's "eraseHeaders" field), the shellcode then performs what is essentially a memset, overwriting 0x400 (1024) bytes at the payload's base address with null (0x00) bytes, effectively erasing the payload's PE headers from memory. The memory storing the decrypted/decompressed payload copy is then freed from memory via VirtualFree for hygiene purposes - can't leave a full copy of the payload with non-erased PE headers in memory!
Finally, the loader determines whether the payload is a DLL by checking the payload's COFF File Header (e_lfanew + 0x4) Characteristics field via the bt (Bit Test) instruction with Operand 2 as 0x0D (13), effectively checking if the payload is a DLL (13th bit is set in IMAGE_FILE_DLL (0x2000)).
If the payload is a DLL (IMAGE_FILE_DLL) the AddressOfEntryPoint is resolved and called with the "DllMain" function prototype. Otherwise it is assumed the payload is either shellcode or an executable and the AddressOfEntryPoint is simply called without any arguments.

The list below provides an overview of changes we have observed in Amatera Stealer since our last blog in Nov 2025, EVALUSION Campaign Delivers Amatera Stealer and NetSupport RAT:
The figure below shows pseudo-code for the top-level XTEA decryption routine "xtea_decrypt_buf" located at offset 0x12245. The implementation uses ECB mode with the standard XTEA delta constant 0x9E3779B9 and writes up to the length specified by the third parameter, "dwLength". This routine is called by hundreds of wrapper functions, each of which allocates a buffer for the plaintext result, calls the XTEA decryption function, and stores the returned pointer in a corresponding global variable. On subsequent calls, if the global variable is already populated, the decrypted string pointer is returned without repeating the decryption process.

Pseudo-code for one such wrapper function is seen below, which checks a global variable to determine if the string was already decrypted in a previous invocation and returns that pointer, otherwise it calls the xtea_decrypt_buf method to decrypt the string.

The figure below displays the routine responsible for returning the XTEA Delta, 0x9E3779B9.

To bypass EDR/AV inline hooks in ntdll, Amatera employs RecycledGate - a SysCall number (SSN) resolution technique that combines elements of the FreshyCalls and Hell's Gate techniques.
It begins by walking the in-memory module list and resolving ntdll's base address through a case-insensitive tail-match for the substring L"NTDLL.DLL" against each module entry's FullDllName.Buffer wide string. It then walks ntdll's Export Address Table (IMAGE_EXPORT_DIRECTORY), for export names beginning with "Nt". Each export name is hashed via djb2-XOR, as shown in the example python below.

The array of "Nt" exports, shown in the figure above as g_NtTriples, is then sorted by virtual address (ascending), where each index in the array is the SSN - this technique is known as FreshyCalls. For each of the 44 Nt* SysCalls, the resolver gets the index of the element with the matching djb2-XOR name hash. This index is effectively the FreshyCalls SSN, and the resolver inspects the corresponding stub's bytes to decide whether to trust that index or the SSN within the SysCall stub code itself, which is checked for hooks. Each SSN is XOR-encoded with the key 0x0E53D952 and stored in its corresponding slot within a global array for later use.

For each resolved SSN, there is a wrapper function that issues the SysCall. The example shown below is the specific wrapper function for the NtQueryInformationProcess SysCall. Each stub loads its corresponding XOR-encoded SSN from a dedicated global variable (in this case g_SSN_NtQueryInformationProcess) into eax and XOR decodes it via key 0x0E53D952.

The global array containing the djb2-XOR hashes (DWORDs) of the required APIs is shown in the figure below, starting with the hash for NtDelayExecution (0x3566DCA3).

Mapping each hash to associated API reveals a total of 44 SSNs and are shown in the JSON map below in the format: djb2_hash => api_name.
For APIs not invoked by SysCall, Amatera uses the standard djb2 algorithm for hashing export names (as well as module names, with the exception that module names are first converted to uppercase). The Python snippet below reimplements the djb2 algorithm using the seed extracted from the sample and prints the resulting hash for AcquireCredentialsHandleA (0x263D76CC). Note, export names are not converted to lowercase in this process - unlike the API hashing algorithm used by the previously described shellcode.
Anti-debug functionality is common throughout the malware, especially checks against fields in the PEB (Process Environment Block). The list below describes the sequential anti-debug checks specific to the core anti-debug routine at offset 0x13CEE. The routine returns a boolean result of whether or not a debugger is present. If so, the process exits via NtTerminateProcess SysCall.


Later in the malware's execution, it attempts to hide its main thread from debuggers by calling the routine shown below several times. This routine issues a SysCall for NtSetInformationThread, specifying the ThreadHandle as the current thread (0xFFFFFFFE) and ThreadInformationClass as ThreadHideFromDebugger (0x11), effectively hiding the thread from a debugger.

The table below summarizes Amatera Stealer's checks designed to evade sandboxes.
mw_has_kaspersky_drivers
The malware detects Kaspersky-affiliated driver files by issuing NtQueryAttributesFile SysCalls. For each check, it constructs an OBJECT_ATTRIBUTES structure and populates the ObjectName member with a pointer to a UNICODE_STRING, whose Buffer field references one of the following fully qualified object paths.
If all files are found, the malware exits. Adding to the malware developer's list of embarrassments, the code fails to account for WoW64 File System Redirection, causing the malware to check for files in C:\Windows\SysWOW64\drivers rather than the intended C:\Windows\System32\drivers directory.

The PowerShell snippet below creates decoy files in C:\Windows\SysWOW64\drivers to exploit this bug as a vaccine. Since Kaspersky's actual files reside in C:\Windows\System32\drivers, this will not interfere with its installation. Note, an elevated PowerShell session is required to run these commands.
mw_has_ukraine_keyboard_layout
The routine responsible for checking the victim's active keyboard layout for Ukraine-affiliation is shown annotated in the figure below. This routine is responsible for walking memory modules, resolving the base address for User32.dll, and walking User32's EAT to resolve the GetKeyboardLayout function.
This function retrieves the victim's current keyboard layout, and the low byte is checked for 0x22 (Ukrainian keyboard layout).

mw_check_token_lacks_user_privileges
The figure below displays the pseudo-code of the routine responsible for checking if the current process's token lacks normal user privileges. First, the current process's token is acquired by issuing a SysCall to NtOpenProcessToken, followed by issuing a SysCall to NtQueryInformationToken to obtain the token's privileges.
If the token has no privileges (TokenInformation->PrivilegeCount == 0) or lacks SeShutdownPrivilege and SeUndockPrivilege privileges, the malware exits.

mw_anti_emulator_less_than_5_installed_programs
The malware calls NtOpenKey via SysCall to obtain a handle to the registry key \Registry\Machine\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall, then iterates over its subkeys via NtEnumerateKey SysCall, counting each one.
If fewer than 5 subkeys are found, the scoring variable is incremented by 20 - a heuristic likely designed to detect emulated environments. The scoring variable acts as a cumulative evasion threshold: if it reaches 45 or higher, the malware terminates execution.

mw_anti_emulator_less_than_6_processes_running
The next routine is also an anti-emulator check that increments the scoring variable by 25 if fewer than 6 processes are running. The malware invokes NtQuerySystemInformation via SysCall with SystemInformationClass set to SystemProcessInformation to retrieve a list of running processes as an array of SYSTEM_PROCESS_INFORMATION structures. A fixed 64 KB buffer is allocated for the output SystemInformation parameter, however, in our analysis this proved insufficient, causing the call to fail.

mw_detect_sandbox_vm_processes
The function at offset 0x13163 issues a SysCall to NtAllocateVirtualMemory, allocating a fixed 128 KB buffer. It then issues a SysCall for NtQuerySystemInformation to enumerate running processes and compares each process name, after lowercasing, against the following substrings.
In our analysis, the NtQuerySystemInformation SysCall failed because the 128 KB buffer was insufficient, causing the malware to immediately free the allocation via NtFreeVirtualMemory SysCall and skip the enumeration entirely - effectively a bug in the malware's implementation.

Since our previous blog, EVALUSION Campaign Delivers Amatera Stealer and NetSupport RAT, Amatera's developers have made significant changes to thwart traffic inspection, replacing AES-256-CBC with a hard-coded key in favor of an ECDH (Elliptic Curve Diffie-Hellman) key exchange using NIST P-256, followed by ChaCha20-Poly1305.
Session Establishment
In the figure shown below (in red), the client initiates a session by sending an HTTP POST to the C2's root path (/) with X-Request-ID set to 0. The request body contains the client's NIST P-256 public key and random padding that is discarded by the C2.
In the figure shown below (in blue), the C2 responds with its own NIST P-256 public key and random padding (discarded by the client) and a session ID in X-Request-ID. All subsequent requests to the C2 include this session ID header/value.

Data Transfer
All subsequent communications to and from the C2 use the Authenticated Encryption with Associated Data (AEAD) algorithm ChaCha20-Poly1305 and follow the format shown below. Without the victim's NIST P-256 private key (64 bytes, generated by function call at offset 0xEEB6) or shared secret (both obtainable only from memory) decryption from a network capture alone is not possible.

Decrypted Communications
The first message is similar to early builds of Amatera, and asks the C2 for endpoints to use for subsequent communications with the C2 backend. What is new are the attributes containing the victim's locale, Active Directory domain name, and whether or not the victim has a Ukrainian keyboard layout, i.e. '"ukr":false'. The purpose of the ukr attribute is unclear, as our analysis found that the malware already refuses to execute on machines where the active keyboard layout is Ukrainian.
Next, the C2 responds with the "endpoints" (URI paths) JSON:
When looking at TLS-decrypted traffic, specifically the randomized URI paths, it is obvious that Amatera Stealer is present:

Using the URI path obtained from the "c" key in the endpoint's JSON shown above, the next request to the C2 is an HTTP POST with a JSON encoded blob. In the blob, the key "Id" specifies a GUID that is hard coded in the payload and is needed to retrieve the malware configuration from the C2. Without the correct GUID, the C2 returns a bad response, and the client goes back to square 1 (session establishment).
With the correct GUID, the C2 responds with the malware configuration. In order to decrypt it, we must navigate from TLS -> ChaCha20-Poly1305 AEAD -> Base64 -> XOR. Hooking or setting a breakpoint on the DecryptMessage API allows for capturing the TLS-decrypted message. Having already captured the client's NIST P-256 private key, the configuration is decrypted from ChaCha20.
This reveals the same format we covered in our previous blog, a base64 + XOR encoded string. The same XOR key is still used to decrypt the configuration: 852149723\x00 (including the NULL terminator). The full configuration is available for analysis here.

Decrypting further communication with the C2 reveals the same format we covered in our previous blog (zip archives with exfiltrated data). Every zip archive contains a txt file at the root named like <guid>.txt that stores the victim device fingerprint in the format <timestamp><computer_name><machine guid>.

The C2 was offline at the time of analysis; however, the following list highlights changes we observed being delivered by an active C2 discovered in a separate case.
Browsers
The following 27 browsers were added to the harvesting configuration, bringing the total from 37 to 65:
Browser-based Extensions
The table below lists newly added browser extensions we've identified in recent malware configs.
Messenger Applications
Discord was added as a harvesting target and Signal coverage was expanded to include the attachments.noindex directory, which stores exchanged attachments between the victim and Signal contacts.
Desktop-Based Cryptocurrency Wallets
The table below lists cryptocurrency wallets targeted in the current configuration, which has tripled from the previous config.
File Grabber
The file grabber now searches the victim's Downloads folder for files of interest. The patterns below demonstrate the broad range of targeted files, including private keys, seed phrases, and other potentially sensitive data. This highlights the importance of not storing sensitive data unencrypted on disk - especially crypto-wallet seed phrases, private keys, or passwords.
eSentire has created a script available here for IDA Pro that finds the XTEA decryption routine, decrypts strings/sets comments, and resolves API hashes to associated APIs.

To learn how your organization can build cyber resilience and prevent business disruption with eSentire’s Next Level MDR, connect with an eSentire Security Specialist now.
GET STARTEDThe eSentire Threat Response Unit (TRU) is an industry-leading threat research team committed to helping your organization become more resilient. TRU is an elite team of threat hunters and researchers that supports our 24/7 Security Operations Centers (SOCs), builds threat detection models across the eSentire XDR Cloud Platform, and works as an extension of your security team to continuously improve our Managed Detection and Response service. By providing complete visibility across your attack surface and performing global threat sweeps and proactive hypothesis-driven threat hunts augmented by original threat research, we are laser-focused on defending your organization against known and unknown threats.